diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java index d7290cf4170..3672db4c0f2 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java @@ -51,18 +51,32 @@ public class AnnotationConfiguration extends AbstractConfiguration private static final Logger LOG = Log.getLogger(AnnotationConfiguration.class); 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_INITIALIZER_LISTENER = "org.eclipse.jetty.containerInitializerListener"; + + protected List _discoverableAnnotationHandlers = new ArrayList(); protected ClassInheritanceHandler _classInheritanceHandler; protected List _containerInitializerAnnotationHandlers = new ArrayList(); + - + @Override 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) @@ -224,8 +238,12 @@ public class AnnotationConfiguration extends AbstractConfiguration //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); + context.setAttribute(CONTAINER_INITIALIZER_LISTENER, listener); context.addBean(listener, true); } diff --git a/jetty-deploy/src/test/resources/jetty.xml b/jetty-deploy/src/test/resources/jetty.xml index fa285624ea4..732adfb3f74 100644 --- a/jetty-deploy/src/test/resources/jetty.xml +++ b/jetty-deploy/src/test/resources/jetty.xml @@ -14,12 +14,10 @@ - - - 200 - 10 - - + + 10 + 200 + diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index 49923335f57..1cf9e85ad45 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -1151,6 +1151,9 @@ public class HttpParser break; case END: + // eat white space + while (buffer.remaining()>0 && buffer.get(buffer.position())<=HttpTokens.SPACE) + buffer.get(); return false; case CLOSED: diff --git a/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty.xml b/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty.xml index 4bde8d7222e..5c882b05143 100644 --- a/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty.xml +++ b/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty.xml @@ -14,13 +14,10 @@ - - - - 10 - 200 - - + + 10 + 200 + diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml index 4bde8d7222e..170530b80e6 100644 --- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml +++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml @@ -14,14 +14,11 @@ - + - - 10 - 200 - - - + 10 + 200 + diff --git a/jetty-server/src/main/config/etc/jetty.xml b/jetty-server/src/main/config/etc/jetty.xml index a551326cc6a..b88ceb217da 100644 --- a/jetty-server/src/main/config/etc/jetty.xml +++ b/jetty-server/src/main/config/etc/jetty.xml @@ -42,14 +42,15 @@ - - - - - - false - - + + + + + + false + diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/EncodingHttpWriter.java b/jetty-server/src/main/java/org/eclipse/jetty/server/EncodingHttpWriter.java index db42f8c0c31..fd8c1c5eea2 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/EncodingHttpWriter.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/EncodingHttpWriter.java @@ -54,7 +54,7 @@ public class EncodingHttpWriter extends HttpWriter out.close(); return; } - + while (length > 0) { _bytes.reset(); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index 76bbb9d6b66..316f8320866 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -569,8 +569,7 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable throw new IllegalStateException(); } - // Either handle now or wait for first content/message complete - return _expect100Continue; + return true; } @Override @@ -581,7 +580,8 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable @SuppressWarnings("unchecked") HttpInput input = (HttpInput)_request.getHttpInput(); input.content(item); - return true; + + return false; } @Override diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java index 3f5853b5762..6b21598f57a 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java @@ -428,20 +428,20 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http that uses the calling thread to block on a readable callback and then to do the parsing before before attempting the read. */ - while (true) + while (!_parser.isComplete()) { // 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 // need to call blockForContent again - while (event && BufferUtil.hasContent(_requestBuffer) && _parser.inContentState()) - _parser.parseNext(_requestBuffer); + while (!event && BufferUtil.hasContent(_requestBuffer) && _parser.inContentState()) + event=_parser.parseNext(_requestBuffer); - // If we have an event, return - if (event) + // If we have content, return + if (_parser.isComplete() || available()>0) return; - + // Do we have content ready to parse? if (BufferUtil.isEmpty(_requestBuffer)) { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java index c0d572fb5a8..de8e0ae0a63 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java @@ -22,7 +22,6 @@ import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritePendingException; import java.util.concurrent.atomic.AtomicReference; import javax.servlet.RequestDispatcher; @@ -204,6 +203,9 @@ write completed - - - ASYNC READY->owp return; } break; + public void closeOutput() throws IOException + { + _channel.getResponse().closeOutput(); } } @@ -332,6 +334,8 @@ write completed - - - ASYNC READY->owp _aggregate = _channel.getByteBufferPool().acquire(getBufferSize(), false); BufferUtil.append(_aggregate, (byte)b); + boolean complete=_channel.getResponse().isAllContentWritten(_written); + // Check if all written or full if (complete || BufferUtil.isFull(_aggregate)) { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Iso88591HttpWriter.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Iso88591HttpWriter.java index e13bbc3e0fd..0f4abd90fbb 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Iso88591HttpWriter.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Iso88591HttpWriter.java @@ -37,7 +37,7 @@ public class Iso88591HttpWriter extends HttpWriter HttpOutput out = _out; if (length==0 && out.isAllContentWritten()) { - out.close(); + close(); return; } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Utf8HttpWriter.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Utf8HttpWriter.java index fcee714fc89..6028109f8ea 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Utf8HttpWriter.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Utf8HttpWriter.java @@ -45,10 +45,10 @@ public class Utf8HttpWriter extends HttpWriter HttpOutput out = _out; if (length==0 && out.isAllContentWritten()) { - out.close(); + close(); return; } - + while (length > 0) { _bytes.reset(); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java index b717edf6c16..5a5f5945e11 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java @@ -466,10 +466,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture // Pick fragment points at random for (int j = 0; j < points.length; ++j) - { points[j] = random.nextInt(bytes.length); - } - // System.err.println("points "+points[0]+" "+points[1]); // Sort the list Arrays.sort(points); @@ -1138,15 +1135,20 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture InputStream in = request.getInputStream(); 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(); out.println(avail); + // block for the first character String buf = ""; + buf += (char)in.read(); + + // read remaining available bytes + avail = in.available(); + out.println(avail); for (int i = 0; i < avail; i++) buf += (char)in.read(); - avail = in.available(); out.println(avail); @@ -1238,10 +1240,11 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture BufferedReader reader = new BufferedReader(new InputStreamReader(is)); // skip header 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)); - assertEquals(0, Integer.parseInt(reader.readLine())); - assertThat(Integer.parseInt(reader.readLine()), Matchers.greaterThan(0)); - assertEquals(0, Integer.parseInt(reader.readLine())); + assertThat(Integer.parseInt(reader.readLine()), Matchers.equalTo(0)); assertEquals("1234567890abcdefghijklmnopqrst", reader.readLine()); } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelServerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelServerTest.java index 0b19b2069e6..7d43055c726 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelServerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelServerTest.java @@ -30,11 +30,4 @@ public class SelectChannelServerTest extends HttpServerTestBase { startServer(new ServerConnector(_server)); } - - @Override - public void testBlockingWhileWritingResponseContent() throws Exception - { - super.testBlockingWhileWritingResponseContent(); - } - } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java index 03d4e32837e..5a3339e2b3e 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java @@ -270,6 +270,7 @@ public class SSLEngineTest { ((HttpsURLConnection)conn).setHostnameVerifier(new HostnameVerifier() { + @Override public boolean verify(String urlHostName, SSLSession session) { return true; diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/AbstractCompressedStream.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/AbstractCompressedStream.java index 8517616e5c9..3f30f531884 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/AbstractCompressedStream.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/AbstractCompressedStream.java @@ -180,7 +180,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream if (_out == null || _bOut != null) { 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); else doCompress(); @@ -241,7 +241,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream if (_encoding!=null) { - setHeader("Content-Encoding", _encoding); + setHeader("Content-Encoding", _encoding); if (_response.containsHeader("Content-Encoding")) { addHeader("Vary",_vary); @@ -308,27 +308,43 @@ public abstract class AbstractCompressedStream extends ServletOutputStream throw new IOException("CLOSED"); if (_out == null) - { - long length=_wrapper.getContentLength(); - if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize())) - doNotCompress(false); - else if (lengthToWrite > _wrapper.getMinCompressSize()) - doCompress(); + { + // If this first write is larger than buffer size, then we are committing now + if (lengthToWrite>_wrapper.getBufferSize()) + { + // 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(); + } else + { + // start aggregating writes into a buffered output stream _out = _bOut = new ByteArrayOutputStream2(_wrapper.getBufferSize()); + } } - else if (_bOut != null) + // else are we aggregating writes? + else if (_bOut !=null) { - long length=_wrapper.getContentLength(); - if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize())) - doNotCompress(false); - else if (lengthToWrite >= (_bOut.getBuf().length - _bOut.getCount())) - doCompress(); + // We are aggregating into the buffered output stream. + + // If this write fills the buffer, then we are committing + if (lengthToWrite>=(_bOut.getBuf().length - _bOut.getCount())) + { + // 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() { diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java index 879e2069355..3314316522a 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java @@ -1166,7 +1166,8 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor String welcome = indexNode.toString(false, true); //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)); } }