Merge remote-tracking branch 'origin/master' into servlet-3.1-api

Conflicts:
	jetty-server/src/main/java/org/eclipse/jetty/server/EncodingHttpWriter.java
	jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
	jetty-server/src/main/java/org/eclipse/jetty/server/Iso88591HttpWriter.java
	jetty-server/src/main/java/org/eclipse/jetty/server/Utf8HttpWriter.java
This commit is contained in:
Greg Wilkins 2013-05-30 17:17:54 +10:00
commit b59949253d
17 changed files with 112 additions and 80 deletions

View File

@ -51,18 +51,32 @@ public class AnnotationConfiguration extends AbstractConfiguration
private static final Logger LOG = Log.getLogger(AnnotationConfiguration.class); private static final Logger LOG = Log.getLogger(AnnotationConfiguration.class);
public static final String CLASS_INHERITANCE_MAP = "org.eclipse.jetty.classInheritanceMap"; public static final String CLASS_INHERITANCE_MAP = "org.eclipse.jetty.classInheritanceMap";
public static final String CONTAINER_INITIALIZERS = "org.eclipse.jetty.containerInitializers"; public static final String CONTAINER_INITIALIZERS = "org.eclipse.jetty.containerInitializers";
public static final String CONTAINER_INITIALIZER_LISTENER = "org.eclipse.jetty.containerInitializerListener";
protected List<DiscoverableAnnotationHandler> _discoverableAnnotationHandlers = new ArrayList<DiscoverableAnnotationHandler>(); protected List<DiscoverableAnnotationHandler> _discoverableAnnotationHandlers = new ArrayList<DiscoverableAnnotationHandler>();
protected ClassInheritanceHandler _classInheritanceHandler; protected ClassInheritanceHandler _classInheritanceHandler;
protected List<ContainerInitializerAnnotationHandler> _containerInitializerAnnotationHandlers = new ArrayList<ContainerInitializerAnnotationHandler>(); protected List<ContainerInitializerAnnotationHandler> _containerInitializerAnnotationHandlers = new ArrayList<ContainerInitializerAnnotationHandler>();
@Override
public void preConfigure(final WebAppContext context) throws Exception public void preConfigure(final WebAppContext context) throws Exception
{ {
} }
@Override
public void deconfigure(WebAppContext context) throws Exception
{
context.removeAttribute(CLASS_INHERITANCE_MAP);
context.removeAttribute(CONTAINER_INITIALIZERS);
ServletContainerInitializerListener listener = (ServletContainerInitializerListener)context.getAttribute(CONTAINER_INITIALIZER_LISTENER);
if (listener != null)
{
context.removeBean(listener);
context.removeAttribute(CONTAINER_INITIALIZER_LISTENER);
}
}
/** /**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext) * @see org.eclipse.jetty.webapp.AbstractConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)
@ -224,8 +238,12 @@ public class AnnotationConfiguration extends AbstractConfiguration
//add a bean which will call the servletcontainerinitializers when appropriate //add a bean which will call the servletcontainerinitializers when appropriate
ServletContainerInitializerListener listener = new ServletContainerInitializerListener(); ServletContainerInitializerListener listener = (ServletContainerInitializerListener)context.getAttribute(CONTAINER_INITIALIZER_LISTENER);
if (listener != null)
throw new IllegalStateException("ServletContainerInitializerListener already exists");
listener = new ServletContainerInitializerListener();
listener.setWebAppContext(context); listener.setWebAppContext(context);
context.setAttribute(CONTAINER_INITIALIZER_LISTENER, listener);
context.addBean(listener, true); context.addBean(listener, true);
} }

View File

@ -14,12 +14,10 @@
<!-- =========================================================== --> <!-- =========================================================== -->
<!-- Server Thread Pool --> <!-- Server Thread Pool -->
<!-- =========================================================== --> <!-- =========================================================== -->
<Arg name="threadPool"> <Get name="ThreadPool">
<New class="org.eclipse.jetty.util.thread.QueuedThreadPool"> <Set name="minThreads" type="int">10</Set>
<Set name="maxThreads">200</Set> <Set name="maxThreads" type="int">200</Set>
<Set name="minThreads">10</Set> </Get>
</New>
</Arg>
<!-- =========================================================== --> <!-- =========================================================== -->
<!-- Set connectors --> <!-- Set connectors -->

View File

@ -1151,6 +1151,9 @@ public class HttpParser
break; break;
case END: case END:
// eat white space
while (buffer.remaining()>0 && buffer.get(buffer.position())<=HttpTokens.SPACE)
buffer.get();
return false; return false;
case CLOSED: case CLOSED:

View File

@ -14,13 +14,10 @@
<!-- =========================================================== --> <!-- =========================================================== -->
<!-- Server Thread Pool --> <!-- Server Thread Pool -->
<!-- =========================================================== --> <!-- =========================================================== -->
<Arg name="threadpool"> <Get name="ThreadPool">
<!-- Default queued blocking threadpool --> <Set name="minThreads">10</Set>
<New class="org.eclipse.jetty.util.thread.QueuedThreadPool"> <Set name="maxThreads">200</Set>
<Set name="minThreads">10</Set> </Get>
<Set name="maxThreads">200</Set>
</New>
</Arg>
<!-- =========================================================== --> <!-- =========================================================== -->

View File

@ -14,14 +14,11 @@
<!-- =========================================================== --> <!-- =========================================================== -->
<!-- Server Thread Pool --> <!-- Server Thread Pool -->
<!-- =========================================================== --> <!-- =========================================================== -->
<Arg name="threadpool"> <Get name="ThreadPool">
<!-- Default queued blocking threadpool --> <!-- Default queued blocking threadpool -->
<New class="org.eclipse.jetty.util.thread.QueuedThreadPool"> <Set name="minThreads">10</Set>
<Set name="minThreads">10</Set> <Set name="maxThreads">200</Set>
<Set name="maxThreads">200</Set> </Get>
</New>
</Arg>
<!-- =========================================================== --> <!-- =========================================================== -->
<!-- Set handler Collection Structure --> <!-- Set handler Collection Structure -->

View File

@ -42,14 +42,15 @@
<!-- Consult the javadoc of o.e.j.util.thread.QueuedThreadPool --> <!-- Consult the javadoc of o.e.j.util.thread.QueuedThreadPool -->
<!-- for all configuration that may be set here. --> <!-- for all configuration that may be set here. -->
<!-- =========================================================== --> <!-- =========================================================== -->
<Arg name="threadpool"> <!-- uncomment to change type of threadpool
<New id="threadpool" class="org.eclipse.jetty.util.thread.QueuedThreadPool"> <Arg name="threadpool"><New id="threadpool" class="org.eclipse.jetty.util.thread.QueuedThreadPool"/></Arg>
<Arg name="minThreads" type="int"><Property name="threads.min" default="10"/></Arg> -->
<Arg name="maxThreads" type="int"><Property name="threads.max" default="200"/></Arg> <Get name="ThreadPool">
<Arg name="idleTimeout" type="int"><Property name="threads.timeout" default="60000"/></Arg> <Set name="minThreads" type="int"><Property name="threads.min" default="10"/></Set>
<Set name="detailedDump">false</Set> <Set name="maxThreads" type="int"><Property name="threads.max" default="200"/></Set>
</New> <Set name="idleTimeout" type="int"><Property name="threads.timeout" default="60000"/></Set>
</Arg> <Set name="detailedDump">false</Set>
</Get>
<!-- =========================================================== --> <!-- =========================================================== -->
<!-- Add shared Scheduler instance --> <!-- Add shared Scheduler instance -->

View File

@ -54,7 +54,7 @@ public class EncodingHttpWriter extends HttpWriter
out.close(); out.close();
return; return;
} }
while (length > 0) while (length > 0)
{ {
_bytes.reset(); _bytes.reset();

View File

@ -569,8 +569,7 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
throw new IllegalStateException(); throw new IllegalStateException();
} }
// Either handle now or wait for first content/message complete return true;
return _expect100Continue;
} }
@Override @Override
@ -581,7 +580,8 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
HttpInput<T> input = (HttpInput<T>)_request.getHttpInput(); HttpInput<T> input = (HttpInput<T>)_request.getHttpInput();
input.content(item); input.content(item);
return true;
return false;
} }
@Override @Override

View File

@ -428,20 +428,20 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
that uses the calling thread to block on a readable callback and that uses the calling thread to block on a readable callback and
then to do the parsing before before attempting the read. then to do the parsing before before attempting the read.
*/ */
while (true) while (!_parser.isComplete())
{ {
// Can the parser progress (even with an empty buffer) // Can the parser progress (even with an empty buffer)
boolean event=_parser.parseNext(_requestBuffer==null?BufferUtil.EMPTY_BUFFER:_requestBuffer); boolean event=_parser.parseNext(_requestBuffer==null?BufferUtil.EMPTY_BUFFER:_requestBuffer);
// If there is more content to parse, loop so we can queue all content from this buffer now without the // If there is more content to parse, loop so we can queue all content from this buffer now without the
// need to call blockForContent again // need to call blockForContent again
while (event && BufferUtil.hasContent(_requestBuffer) && _parser.inContentState()) while (!event && BufferUtil.hasContent(_requestBuffer) && _parser.inContentState())
_parser.parseNext(_requestBuffer); event=_parser.parseNext(_requestBuffer);
// If we have an event, return // If we have content, return
if (event) if (_parser.isComplete() || available()>0)
return; return;
// Do we have content ready to parse? // Do we have content ready to parse?
if (BufferUtil.isEmpty(_requestBuffer)) if (BufferUtil.isEmpty(_requestBuffer))
{ {

View File

@ -22,7 +22,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritePendingException;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.RequestDispatcher; import javax.servlet.RequestDispatcher;
@ -204,6 +203,9 @@ write completed - - - ASYNC READY->owp
return; return;
} }
break; break;
public void closeOutput() throws IOException
{
_channel.getResponse().closeOutput();
} }
} }
@ -332,6 +334,8 @@ write completed - - - ASYNC READY->owp
_aggregate = _channel.getByteBufferPool().acquire(getBufferSize(), false); _aggregate = _channel.getByteBufferPool().acquire(getBufferSize(), false);
BufferUtil.append(_aggregate, (byte)b); BufferUtil.append(_aggregate, (byte)b);
boolean complete=_channel.getResponse().isAllContentWritten(_written);
// Check if all written or full // Check if all written or full
if (complete || BufferUtil.isFull(_aggregate)) if (complete || BufferUtil.isFull(_aggregate))
{ {

View File

@ -37,7 +37,7 @@ public class Iso88591HttpWriter extends HttpWriter
HttpOutput out = _out; HttpOutput out = _out;
if (length==0 && out.isAllContentWritten()) if (length==0 && out.isAllContentWritten())
{ {
out.close(); close();
return; return;
} }

View File

@ -45,10 +45,10 @@ public class Utf8HttpWriter extends HttpWriter
HttpOutput out = _out; HttpOutput out = _out;
if (length==0 && out.isAllContentWritten()) if (length==0 && out.isAllContentWritten())
{ {
out.close(); close();
return; return;
} }
while (length > 0) while (length > 0)
{ {
_bytes.reset(); _bytes.reset();

View File

@ -466,10 +466,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
// Pick fragment points at random // Pick fragment points at random
for (int j = 0; j < points.length; ++j) for (int j = 0; j < points.length; ++j)
{
points[j] = random.nextInt(bytes.length); points[j] = random.nextInt(bytes.length);
}
// System.err.println("points "+points[0]+" "+points[1]);
// Sort the list // Sort the list
Arrays.sort(points); Arrays.sort(points);
@ -1138,15 +1135,20 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
InputStream in = request.getInputStream(); InputStream in = request.getInputStream();
ServletOutputStream out = response.getOutputStream(); ServletOutputStream out = response.getOutputStream();
// should always be some input available, because of deferred dispatch. // this should initially be 0 bytes available.
int avail = in.available(); int avail = in.available();
out.println(avail); out.println(avail);
// block for the first character
String buf = ""; String buf = "";
buf += (char)in.read();
// read remaining available bytes
avail = in.available();
out.println(avail);
for (int i = 0; i < avail; i++) for (int i = 0; i < avail; i++)
buf += (char)in.read(); buf += (char)in.read();
avail = in.available(); avail = in.available();
out.println(avail); out.println(avail);
@ -1238,10 +1240,11 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
BufferedReader reader = new BufferedReader(new InputStreamReader(is)); BufferedReader reader = new BufferedReader(new InputStreamReader(is));
// skip header // skip header
while (reader.readLine().length() > 0) ; while (reader.readLine().length() > 0) ;
assertThat(Integer.parseInt(reader.readLine()), Matchers.equalTo(0));
assertThat(Integer.parseInt(reader.readLine()), Matchers.equalTo(9));
assertThat(Integer.parseInt(reader.readLine()), Matchers.equalTo(0));
assertThat(Integer.parseInt(reader.readLine()), Matchers.greaterThan(0)); assertThat(Integer.parseInt(reader.readLine()), Matchers.greaterThan(0));
assertEquals(0, Integer.parseInt(reader.readLine())); assertThat(Integer.parseInt(reader.readLine()), Matchers.equalTo(0));
assertThat(Integer.parseInt(reader.readLine()), Matchers.greaterThan(0));
assertEquals(0, Integer.parseInt(reader.readLine()));
assertEquals("1234567890abcdefghijklmnopqrst", reader.readLine()); assertEquals("1234567890abcdefghijklmnopqrst", reader.readLine());
} }
} }

View File

@ -30,11 +30,4 @@ public class SelectChannelServerTest extends HttpServerTestBase
{ {
startServer(new ServerConnector(_server)); startServer(new ServerConnector(_server));
} }
@Override
public void testBlockingWhileWritingResponseContent() throws Exception
{
super.testBlockingWhileWritingResponseContent();
}
} }

View File

@ -270,6 +270,7 @@ public class SSLEngineTest
{ {
((HttpsURLConnection)conn).setHostnameVerifier(new HostnameVerifier() ((HttpsURLConnection)conn).setHostnameVerifier(new HostnameVerifier()
{ {
@Override
public boolean verify(String urlHostName, SSLSession session) public boolean verify(String urlHostName, SSLSession session)
{ {
return true; return true;

View File

@ -180,7 +180,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
if (_out == null || _bOut != null) if (_out == null || _bOut != null)
{ {
long length=_wrapper.getContentLength(); long length=_wrapper.getContentLength();
if (length<0 && _bOut==null || length >= 0 && length < _wrapper.getMinCompressSize()) if (length<0 &&_bOut==null || length >= 0 && length < _wrapper.getMinCompressSize())
doNotCompress(false); doNotCompress(false);
else else
doCompress(); doCompress();
@ -241,7 +241,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
if (_encoding!=null) if (_encoding!=null)
{ {
setHeader("Content-Encoding", _encoding); setHeader("Content-Encoding", _encoding);
if (_response.containsHeader("Content-Encoding")) if (_response.containsHeader("Content-Encoding"))
{ {
addHeader("Vary",_vary); addHeader("Vary",_vary);
@ -308,27 +308,43 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
throw new IOException("CLOSED"); throw new IOException("CLOSED");
if (_out == null) if (_out == null)
{ {
long length=_wrapper.getContentLength(); // If this first write is larger than buffer size, then we are committing now
if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize())) if (lengthToWrite>_wrapper.getBufferSize())
doNotCompress(false); {
else if (lengthToWrite > _wrapper.getMinCompressSize()) // if we know this is all the content and it is less than minimum, then do not compress, otherwise do compress
doCompress(); long length=_wrapper.getContentLength();
if (length>=0 && length<_wrapper.getMinCompressSize())
doNotCompress(false); // Not compressing by size, so no vary on request headers
else
doCompress();
}
else else
{
// start aggregating writes into a buffered output stream
_out = _bOut = new ByteArrayOutputStream2(_wrapper.getBufferSize()); _out = _bOut = new ByteArrayOutputStream2(_wrapper.getBufferSize());
}
} }
else if (_bOut != null) // else are we aggregating writes?
else if (_bOut !=null)
{ {
long length=_wrapper.getContentLength(); // We are aggregating into the buffered output stream.
if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize()))
doNotCompress(false); // If this write fills the buffer, then we are committing
else if (lengthToWrite >= (_bOut.getBuf().length - _bOut.getCount())) if (lengthToWrite>=(_bOut.getBuf().length - _bOut.getCount()))
doCompress(); {
// if we know this is all the content and it is less than minimum, then do not compress, otherwise do compress
long length=_wrapper.getContentLength();
if (length>=0 && length<_wrapper.getMinCompressSize())
doNotCompress(false); // Not compressing by size, so no vary on request headers
else
doCompress();
}
} }
} }
/** /**
* @see org.eclipse.jetty.http.gzip.CompressedStream#createOutputStream() * @see org.eclipse.jetty.servlets.gzip.CompressedStream#getOutputStream()
*/ */
public OutputStream getOutputStream() public OutputStream getOutputStream()
{ {

View File

@ -1166,7 +1166,8 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
String welcome = indexNode.toString(false, true); String welcome = indexNode.toString(false, true);
//Servlet Spec 3.0 p. 74 welcome files are additive //Servlet Spec 3.0 p. 74 welcome files are additive
context.setWelcomeFiles((String[])ArrayUtil.addToArray(context.getWelcomeFiles(),welcome,String.class)); if (welcome != null && welcome.trim().length() > 0)
context.setWelcomeFiles((String[])ArrayUtil.addToArray(context.getWelcomeFiles(),welcome,String.class));
} }
} }