From cf98276b32159b007c313a0dc8e47250f653f40d Mon Sep 17 00:00:00 2001 From: Jesse McConnell Date: Fri, 15 Feb 2013 11:59:39 -0600 Subject: [PATCH 01/16] [Bug 394064] ensure that JarFile instances are closed on JarFileResource.release() --- .../jetty/util/resource/JarFileResource.java | 20 ++++++++--- .../jetty/util/resource/ResourceTest.java | 32 ++++++++++-------- .../TestData/alphabet.txt | 0 .../resource => resources}/TestData/alt.zip | Bin .../TestData/extract.zip | Bin .../resource => resources}/TestData/test.zip | Bin .../TestData/test/META-INF/MANIFEST.MF | 3 ++ .../src/test/resources/TestData/test/alphabet | 1 + .../src/test/resources/TestData/test/numbers | 1 + .../resources/TestData/test/subdir/alphabet | 1 + .../resources/TestData/test/subdir/numbers | 1 + .../TestData/test/subdir/subsubdir/alphabet | 1 + .../TestData/test/subdir/subsubdir/numbers | 1 + .../org/eclipse/jetty/webapp/Descriptor.java | 12 ++++--- 14 files changed, 50 insertions(+), 23 deletions(-) rename jetty-util/src/test/{java/org/eclipse/jetty/util/resource => resources}/TestData/alphabet.txt (100%) rename jetty-util/src/test/{java/org/eclipse/jetty/util/resource => resources}/TestData/alt.zip (100%) rename jetty-util/src/test/{java/org/eclipse/jetty/util/resource => resources}/TestData/extract.zip (100%) rename jetty-util/src/test/{java/org/eclipse/jetty/util/resource => resources}/TestData/test.zip (100%) create mode 100755 jetty-util/src/test/resources/TestData/test/META-INF/MANIFEST.MF create mode 100755 jetty-util/src/test/resources/TestData/test/alphabet create mode 100755 jetty-util/src/test/resources/TestData/test/numbers create mode 100755 jetty-util/src/test/resources/TestData/test/subdir/alphabet create mode 100755 jetty-util/src/test/resources/TestData/test/subdir/numbers create mode 100755 jetty-util/src/test/resources/TestData/test/subdir/subsubdir/alphabet create mode 100755 jetty-util/src/test/resources/TestData/test/subdir/subsubdir/numbers diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java index e6752f0d0ba..3ae7a10e6ba 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java @@ -65,6 +65,19 @@ class JarFileResource extends JarResource _list=null; _entry=null; _file=null; + + if ( _jarFile != null ) + { + try + { + _jarFile.close(); + } + catch ( IOException ioe ) + { + LOG.ignore(ioe); + } + } + _jarFile=null; super.release(); } @@ -166,7 +179,7 @@ class JarFileResource extends JarResource if (jarFile!=null && _entry==null && !_directory) { // OK - we have a JarFile, lets look at the entries for our path - Enumeration e=jarFile.entries(); + Enumeration e=jarFile.entries(); while(e.hasMoreElements()) { JarEntry entry = (JarEntry) e.nextElement(); @@ -301,12 +314,11 @@ class JarFileResource extends JarResource } } - Enumeration e=jarFile.entries(); + Enumeration e=jarFile.entries(); String dir=_urlString.substring(_urlString.indexOf("!/")+2); while(e.hasMoreElements()) { - - JarEntry entry = (JarEntry) e.nextElement(); + JarEntry entry = e.nextElement(); String name=entry.getName().replace('\\','/'); if(!name.startsWith(dir) || name.length()==dir.length()) { diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java index 119facafc29..ead6b170522 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java @@ -35,8 +35,11 @@ import java.util.Date; import java.util.HashSet; import java.util.Set; import java.util.TimeZone; +import java.util.jar.JarFile; import java.util.zip.ZipFile; +import junit.framework.Assert; + import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.OS; import org.eclipse.jetty.util.IO; @@ -125,14 +128,14 @@ public class ResourceTest URI uri = file.toURI(); __userURL=uri.toURL(); - __userURL = new URL(__userURL.toString() + "src/test/java/org/eclipse/jetty/util/resource/"); - FilePermission perm = (FilePermission) __userURL.openConnection().getPermission(); - __userDir = new File(perm.getName()).getCanonicalPath() + File.separatorChar; - __relDir = "src/test/java/org/eclipse/jetty/util/resource/".replace('/', File.separatorChar); + __userURL = MavenTestingUtils.getTestResourcesDir().toURI().toURL(); + FilePermission perm = (FilePermission) __userURL.openConnection().getPermission(); + __userDir = new File(perm.getName()).getCanonicalPath() + File.separatorChar; + __relDir = "src/test/resources/".replace('/', File.separatorChar); - System.err.println("User Dir="+__userDir); - System.err.println("Rel Dir="+__relDir); - System.err.println("User URL="+__userURL); + //System.err.println("User Dir="+__userDir); + //System.err.println("Rel Dir="+__relDir); + //System.err.println("User URL="+__userURL); tmpFile=File.createTempFile("test",null).getCanonicalFile(); tmpFile.deleteOnExit(); @@ -146,15 +149,15 @@ public class ResourceTest data[i++]=new Data(__userURL,EXISTS,DIR); data[i++]=new Data(__userDir,EXISTS,DIR); data[i++]=new Data(__relDir,EXISTS,DIR); - data[i++]=new Data(__userURL+"ResourceTest.java",EXISTS,!DIR); - data[i++]=new Data(__userDir+"ResourceTest.java",EXISTS,!DIR); - data[i++]=new Data(__relDir+"ResourceTest.java",EXISTS,!DIR); + data[i++]=new Data(__userURL+"jetty-logging.properties",EXISTS,!DIR); + data[i++]=new Data(__userDir+"jetty-logging.properties",EXISTS,!DIR); + data[i++]=new Data(__relDir+"jetty-logging.properties",EXISTS,!DIR); data[i++]=new Data(__userURL+"NoName.txt",!EXISTS,!DIR); data[i++]=new Data(__userDir+"NoName.txt",!EXISTS,!DIR); data[i++]=new Data(__relDir+"NoName.txt",!EXISTS,!DIR); - data[i++]=new Data(data[rt],"ResourceTest.java",EXISTS,!DIR); - data[i++]=new Data(data[rt],"/ResourceTest.java",EXISTS,!DIR); + data[i++]=new Data(data[rt],"jetty-logging.properties",EXISTS,!DIR); + data[i++]=new Data(data[rt],"/jetty-logging.properties",EXISTS,!DIR); data[i++]=new Data(data[rt],"NoName.txt",!EXISTS,!DIR); data[i++]=new Data(data[rt],"/NoName.txt",!EXISTS,!DIR); @@ -327,15 +330,14 @@ public class ResourceTest { String s = "jar:"+__userURL+"TestData/test.zip!/subdir/numbers"; - // TODO move this into src/test/resources!!! - ZipFile zf = new ZipFile(MavenTestingUtils.getProjectFile("src/test/java/org/eclipse/jetty/util/resource/TestData/test.zip")); + ZipFile zf = new ZipFile(MavenTestingUtils.getTestResourceFile("TestData/test.zip")); long last = zf.getEntry("subdir/numbers").getTime(); Resource r = Resource.newResource(s); assertEquals(last,r.lastModified()); // Known date value inside zip } - + /* ------------------------------------------------------------ */ @Test public void testJarFileCopyToDirectoryTraversal () throws Exception diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/TestData/alphabet.txt b/jetty-util/src/test/resources/TestData/alphabet.txt similarity index 100% rename from jetty-util/src/test/java/org/eclipse/jetty/util/resource/TestData/alphabet.txt rename to jetty-util/src/test/resources/TestData/alphabet.txt diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/TestData/alt.zip b/jetty-util/src/test/resources/TestData/alt.zip similarity index 100% rename from jetty-util/src/test/java/org/eclipse/jetty/util/resource/TestData/alt.zip rename to jetty-util/src/test/resources/TestData/alt.zip diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/TestData/extract.zip b/jetty-util/src/test/resources/TestData/extract.zip similarity index 100% rename from jetty-util/src/test/java/org/eclipse/jetty/util/resource/TestData/extract.zip rename to jetty-util/src/test/resources/TestData/extract.zip diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/TestData/test.zip b/jetty-util/src/test/resources/TestData/test.zip similarity index 100% rename from jetty-util/src/test/java/org/eclipse/jetty/util/resource/TestData/test.zip rename to jetty-util/src/test/resources/TestData/test.zip diff --git a/jetty-util/src/test/resources/TestData/test/META-INF/MANIFEST.MF b/jetty-util/src/test/resources/TestData/test/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..b1f95107ebf --- /dev/null +++ b/jetty-util/src/test/resources/TestData/test/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Created-By: 1.2.2 (Sun Microsystems Inc.) + diff --git a/jetty-util/src/test/resources/TestData/test/alphabet b/jetty-util/src/test/resources/TestData/test/alphabet new file mode 100755 index 00000000000..72d007b6edb --- /dev/null +++ b/jetty-util/src/test/resources/TestData/test/alphabet @@ -0,0 +1 @@ +ABCDEFGHIJKLMNOPQRSTUVWXYZ diff --git a/jetty-util/src/test/resources/TestData/test/numbers b/jetty-util/src/test/resources/TestData/test/numbers new file mode 100755 index 00000000000..a32a4347a4e --- /dev/null +++ b/jetty-util/src/test/resources/TestData/test/numbers @@ -0,0 +1 @@ +1234567890 diff --git a/jetty-util/src/test/resources/TestData/test/subdir/alphabet b/jetty-util/src/test/resources/TestData/test/subdir/alphabet new file mode 100755 index 00000000000..72d007b6edb --- /dev/null +++ b/jetty-util/src/test/resources/TestData/test/subdir/alphabet @@ -0,0 +1 @@ +ABCDEFGHIJKLMNOPQRSTUVWXYZ diff --git a/jetty-util/src/test/resources/TestData/test/subdir/numbers b/jetty-util/src/test/resources/TestData/test/subdir/numbers new file mode 100755 index 00000000000..a32a4347a4e --- /dev/null +++ b/jetty-util/src/test/resources/TestData/test/subdir/numbers @@ -0,0 +1 @@ +1234567890 diff --git a/jetty-util/src/test/resources/TestData/test/subdir/subsubdir/alphabet b/jetty-util/src/test/resources/TestData/test/subdir/subsubdir/alphabet new file mode 100755 index 00000000000..72d007b6edb --- /dev/null +++ b/jetty-util/src/test/resources/TestData/test/subdir/subsubdir/alphabet @@ -0,0 +1 @@ +ABCDEFGHIJKLMNOPQRSTUVWXYZ diff --git a/jetty-util/src/test/resources/TestData/test/subdir/subsubdir/numbers b/jetty-util/src/test/resources/TestData/test/subdir/subsubdir/numbers new file mode 100755 index 00000000000..a32a4347a4e --- /dev/null +++ b/jetty-util/src/test/resources/TestData/test/subdir/subsubdir/numbers @@ -0,0 +1 @@ +1234567890 diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Descriptor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Descriptor.java index 0e9d216c296..038230b4e11 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Descriptor.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Descriptor.java @@ -60,10 +60,14 @@ public abstract class Descriptor if (_root == null) { - //boolean oldValidating = _processor.getParser().getValidating(); - //_processor.getParser().setValidating(_validating); - _root = _parser.parse(_xml.getURL().toString()); - //_processor.getParser().setValidating(oldValidating); + try + { + _root = _parser.parse(_xml.getInputStream()); + } + finally + { + _xml.release(); + } } } From e210dfbccada69e08111a4b7ab2ccdce06bca0aa Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 19 Feb 2013 09:38:32 -0700 Subject: [PATCH 02/16] 401211 - Remove requirement for jetty-websocket.jar in WEB-INF/lib + Adding appropriate configuration in WebAppContext to use WebSocketServlet from server classloader. Similar to how the WebSocket interface and WebSocketFactory are also defined. + Marking jetty-websocket as provided in test webapp --- .../src/main/java/org/eclipse/jetty/webapp/WebAppContext.java | 2 ++ test-jetty-webapp/pom.xml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java index 0cb4dfb1acf..68651352243 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java @@ -109,6 +109,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL "org.eclipse.jetty.plus.jaas.", // webapp cannot change jaas classes "org.eclipse.jetty.websocket.WebSocket", // WebSocket is a jetty extension "org.eclipse.jetty.websocket.WebSocketFactory", // WebSocket is a jetty extension + "org.eclipse.jetty.websocket.WebSocketServlet", // webapp cannot change WebSocketServlet "org.eclipse.jetty.servlet.DefaultServlet" // webapp cannot change default servlets } ; @@ -123,6 +124,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL "-org.eclipse.jetty.plus.jaas.", // don't hide jaas classes "-org.eclipse.jetty.websocket.WebSocket", // WebSocket is a jetty extension "-org.eclipse.jetty.websocket.WebSocketFactory", // WebSocket is a jetty extension + "-org.eclipse.jetty.websocket.WebSocketServlet", // don't hide WebSocketServlet "-org.eclipse.jetty.servlet.DefaultServlet", // don't hide default servlet "-org.eclipse.jetty.servlet.listener.", // don't hide useful listeners "org.eclipse.jetty." // hide other jetty classes diff --git a/test-jetty-webapp/pom.xml b/test-jetty-webapp/pom.xml index 399e0474288..d9789af3ff1 100644 --- a/test-jetty-webapp/pom.xml +++ b/test-jetty-webapp/pom.xml @@ -176,7 +176,7 @@ org.eclipse.jetty jetty-websocket ${project.version} - + provided org.eclipse.jetty From 27cad4960b06f2f5277bd35ef3dc677caedec844 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 21 Feb 2013 12:43:18 +1100 Subject: [PATCH 03/16] 401382 Prevent parseAvailable from parsing next chunk when previous has not been consumed --- .../org/eclipse/jetty/http/HttpParser.java | 6 +-- .../jetty/servlets/ProxyServletTest.java | 48 +++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) 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 f8a7442890b..1bad26499c7 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 @@ -225,8 +225,8 @@ public class HttpParser implements Parser /* ------------------------------------------------------------------------------- */ /** * Parse until END state. - * This method will parse any remaining content in the current buffer. It does not care about the - * {@link #getState current state} of the parser. + * This method will parse any remaining content in the current buffer as long as there is + * no unconsumed content. It does not care about the {@link #getState current state} of the parser. * @see #parse * @see #parseNext */ @@ -235,7 +235,7 @@ public class HttpParser implements Parser boolean progress=parseNext()>0; // continue parsing - while (!isComplete() && _buffer!=null && _buffer.length()>0) + while (!isComplete() && _buffer!=null && _buffer.length()>0 && !_contentView.hasContent()) { progress |= parseNext()>0; } diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java index fd1ccd3fe4b..e52bbc6b4b5 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java @@ -32,6 +32,8 @@ import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.StringUtil; import org.hamcrest.core.Is; import org.hamcrest.core.IsEqual; import org.junit.After; @@ -44,6 +46,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.MalformedURLException; +import java.net.Socket; import java.util.Arrays; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -239,4 +242,49 @@ public class ProxyServletTest exchange.waitForDone(); assertThat(excepted.get(),equalTo(true)); } + + + @Test + public void testChunkedPut() throws Exception + { + init(new HttpServlet() + { + @Override + protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + resp.setContentType("text/plain"); + String message=IO.toString(req.getInputStream()); + resp.getOutputStream().print(message); + } + }); + + + Socket client = new Socket("localhost",_connector.getLocalPort()); + client.setSoTimeout(1000000); + client.getOutputStream().write(( + "PUT /proxy/test HTTP/1.1\r\n"+ + "Host: localhost:"+_connector.getLocalPort()+"\r\n"+ + "Transfer-Encoding: chunked\r\n"+ + "Content-Type: text/plain\r\n"+ + "Connection: close\r\n"+ + "\r\n"+ + "A\r\n"+ + "0123456789\r\n"+ + "9\r\n"+ + "ABCDEFGHI\r\n"+ + "8\r\n"+ + "JKLMNOPQ\r\n"+ + "7\r\n"+ + "RSTUVWX\r\n"+ + "2\r\n"+ + "YZ\r\n"+ + "0\r\n" + ).getBytes(StringUtil.__ISO_8859_1_CHARSET)); + + + String response=IO.toString(client.getInputStream()); + Assert.assertTrue(response.contains("200 OK")); + Assert.assertTrue(response.contains("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")); + + } } From bed3ea04f8fd9731a73b0d97c10b9f35fdb950b2 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 21 Feb 2013 14:57:36 +1100 Subject: [PATCH 04/16] 401382 Prevent parseAvailable from parsing next chunk when previous has not been consumed. Handle no content-type in chunked request. --- .../main/java/org/eclipse/jetty/servlets/ProxyServlet.java | 6 ++++++ .../java/org/eclipse/jetty/servlets/ProxyServletTest.java | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java index d4501d25af5..67fdbd7175d 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java @@ -581,6 +581,12 @@ public class ProxyServlet implements Servlet String hdr = (String)enm.nextElement(); String lhdr = hdr.toLowerCase(); + if ("transfer-encoding".equals(lhdr)) + { + if (request.getHeader("transfer-encoding").indexOf("chunk")>=0) + hasContent = true; + } + if (_DontProxyHeaders.contains(lhdr)) continue; if (connectionHdr != null && connectionHdr.indexOf(lhdr) >= 0) diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java index e52bbc6b4b5..74c762fe33a 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java @@ -265,7 +265,6 @@ public class ProxyServletTest "PUT /proxy/test HTTP/1.1\r\n"+ "Host: localhost:"+_connector.getLocalPort()+"\r\n"+ "Transfer-Encoding: chunked\r\n"+ - "Content-Type: text/plain\r\n"+ "Connection: close\r\n"+ "\r\n"+ "A\r\n"+ From ecfd7f74e6a5779bfb41aa2b64bdbbc501017b34 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 21 Feb 2013 17:15:19 +0100 Subject: [PATCH 05/16] 376273 - Early EOF because of SSL Protocol Error on https://api-3t.paypal.com/nvp. This was caused by the fact that the other peer closed the raw socket after sending data. SslConnection was reading the data, but not notifying the application of the data, then reading the abrupt close, which was causing an exception, ending up in the application never being notified of the data that arrived. Now we catch and ignore the exception during SSLEngine.closeInbound(), and we properly send an alert to the other peer (instead of hard closing the connection as well). In this way, the application has the chance to read the data and then close the connection. --- .../jetty/client/ExternalSiteTest.java | 64 +++++++++++++++++++ .../jetty/client/SslBytesServerTest.java | 22 ++++--- .../eclipse/jetty/io/nio/SslConnection.java | 14 +++- .../io/nio/SelectChannelEndPointSslTest.java | 23 ++++++- 4 files changed, 110 insertions(+), 13 deletions(-) create mode 100644 jetty-client/src/test/java/org/eclipse/jetty/client/ExternalSiteTest.java diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ExternalSiteTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ExternalSiteTest.java new file mode 100644 index 00000000000..cf390538e0a --- /dev/null +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ExternalSiteTest.java @@ -0,0 +1,64 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.client; + +import java.io.IOException; +import java.net.Socket; + +import org.eclipse.jetty.http.HttpSchemes; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +public class ExternalSiteTest +{ + @Test + public void testExternalSSLSite() throws Exception + { + HttpClient client = new HttpClient(new SslContextFactory()); + client.start(); + + String host = "api-3t.paypal.com"; + int port = 443; + + // Verify that we have connectivity + try + { + new Socket(host, port).close(); + } + catch (IOException x) + { + Assume.assumeNoException(x); + } + + ContentExchange exchange = new ContentExchange(true); + exchange.setScheme(HttpSchemes.HTTPS_BUFFER); + exchange.setAddress(new Address(host, port)); + exchange.setRequestURI("/nvp"); + client.send(exchange); + int done = exchange.waitForDone(); + Assert.assertEquals(HttpExchange.STATUS_COMPLETED, done); + Assert.assertEquals(HttpStatus.OK_200, exchange.getResponseStatus()); + Assert.assertNotNull(exchange.getResponseContentBytes()); + + client.stop(); + } +} diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java index 9d93daa34a4..55edb01d197 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java @@ -18,8 +18,6 @@ package org.eclipse.jetty.client; -import static org.hamcrest.Matchers.*; - import java.io.BufferedReader; import java.io.EOFException; import java.io.File; @@ -39,7 +37,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; - import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSocket; @@ -72,6 +69,11 @@ import org.junit.Assume; import org.junit.Before; import org.junit.Test; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.lessThan; +import static org.hamcrest.Matchers.not; + public class SslBytesServerTest extends SslBytesTest { private final AtomicInteger sslHandles = new AtomicInteger(); @@ -847,7 +849,9 @@ public class SslBytesServerTest extends SslBytesTest // Close the raw socket, this generates a truncation attack proxy.flushToServer((TLSRecord)null); - // Expect raw close from server + // Expect alert + raw close from server + record = proxy.readFromServer(); + Assert.assertEquals(TLSRecord.Type.ALERT, record.getType()); record = proxy.readFromServer(); Assert.assertNull(String.valueOf(record), record); proxy.flushToClient(record); @@ -1631,9 +1635,9 @@ public class SslBytesServerTest extends SslBytesTest //System.err.println(((Dumpable)server.getConnectors()[0]).dump()); Assert.assertThat(((Dumpable)server.getConnectors()[0]).dump(),containsString("SCEP@")); - + completeClose(client); - + TimeUnit.MILLISECONDS.sleep(200); //System.err.println(((Dumpable)server.getConnectors()[0]).dump()); Assert.assertThat(((Dumpable)server.getConnectors()[0]).dump(),not(containsString("SCEP@"))); @@ -1748,13 +1752,13 @@ public class SslBytesServerTest extends SslBytesTest // Close Alert record = proxy.readFromServer(); proxy.flushToClient(record); - + // Socket close record = proxy.readFromServer(); Assert.assertNull(String.valueOf(record), record); proxy.flushToClient(record); } - + private void completeClose(SSLSocket client) throws Exception { client.close(); @@ -1770,6 +1774,6 @@ public class SslBytesServerTest extends SslBytesTest // Close Alert record = proxy.readFromServer(); proxy.flushToClient(record); - + } } diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java index fd3bdf2578f..6487ba96656 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java @@ -406,7 +406,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection // pass on ishut/oshut state if (_endp.isOpen() && _endp.isInputShutdown() && !_inbound.hasContent()) - _engine.closeInbound(); + closeInbound(); if (_endp.isOpen() && _engine.isOutboundDone() && !_outbound.hasContent()) _endp.shutdownOutput(); @@ -428,6 +428,18 @@ public class SslConnection extends AbstractConnection implements AsyncConnection return some_progress; } + private void closeInbound() + { + try + { + _engine.closeInbound(); + } + catch (SSLException x) + { + _logger.debug(x); + } + } + private synchronized boolean wrap(final Buffer buffer) throws IOException { ByteBuffer bbuf=extractByteBuffer(buffer); diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java index ddfbbccb4a4..7a9031fe869 100644 --- a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java +++ b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java @@ -26,6 +26,7 @@ import java.nio.channels.SocketChannel; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import javax.net.ssl.SSLException; import javax.net.ssl.SSLSocket; import org.eclipse.jetty.io.EndPoint; @@ -188,12 +189,28 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest Assert.assertEquals("HelloWorld",reply); - SelectorManager.LOG.info("javax.net.ssl.SSLException: Inbound closed... is expected soon"); - if (debug) System.err.println("\nSudden Death"); + if (debug) System.err.println("Shutting down output"); client.socket().shutdownOutput(); filled=client.read(sslIn); - Assert.assertEquals(-1,filled); + if (debug) System.err.println("in="+filled); + sslIn.flip(); + try + { + // Since the client closed abruptly, the server is sending a close alert with a failure + engine.unwrap(sslIn, appIn); + Assert.fail(); + } + catch (SSLException x) + { + // Expected + } + + sslIn.clear(); + filled = client.read(sslIn); + Assert.assertEquals(-1, filled); + + Assert.assertFalse(server.isOpen()); } @Test From ad6e4b37f0c4ef35e1cca82105e26ea85b31af77 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Fri, 22 Feb 2013 10:47:57 +1100 Subject: [PATCH 06/16] 401474 Performance problem in org.eclipse.jetty.annotation.AnnotationParser --- .../java/org/eclipse/jetty/annotations/AnnotationParser.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java index 8761dc6a558..334ba55007a 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java @@ -25,12 +25,13 @@ import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.jar.JarEntry; import org.eclipse.jetty.util.Loader; @@ -54,7 +55,7 @@ public class AnnotationParser { private static final Logger LOG = Log.getLogger(AnnotationParser.class); - protected List _parsedClassNames = new ArrayList(); + protected Set _parsedClassNames = new HashSet(); protected Map> _annotationHandlers = new HashMap>(); protected List _classHandlers = new ArrayList(); protected List _methodHandlers = new ArrayList(); From 3d179bc418f31594edaadff2a8f57af0ea40c39a Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 21 Feb 2013 13:43:17 -0700 Subject: [PATCH 07/16] Making testcase JDK 1.5 compatible --- .../test/java/org/eclipse/jetty/servlets/ProxyServletTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java index 74c762fe33a..e8e761fd1f8 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java @@ -278,7 +278,7 @@ public class ProxyServletTest "2\r\n"+ "YZ\r\n"+ "0\r\n" - ).getBytes(StringUtil.__ISO_8859_1_CHARSET)); + ).getBytes(StringUtil.__ISO_8859_1)); String response=IO.toString(client.getInputStream()); From c7dd114cb62649d29b86424a2ce5182fddc209cf Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 21 Feb 2013 17:21:29 -0700 Subject: [PATCH 08/16] 401317 - Make Safari 5.x websocket support minVersion level error more clear + Making error message about minVersion configurable more clear on both the Logging on the server side, and the HTTP/1.1 400 error response line --- .../jetty/websocket/WebSocketFactory.java | 20 ++- .../websocket/WebSocketMinVersionTest.java | 119 ++++++++++++++++++ .../jetty/websocket/helper/SafariD00.java | 14 +++ 3 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketMinVersionTest.java diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketFactory.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketFactory.java index 1378956342f..7459887bb79 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketFactory.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketFactory.java @@ -230,6 +230,8 @@ public class WebSocketFactory extends AbstractLifeCycle // Old pre-RFC version specifications (header not present in RFC-6455) draft = request.getIntHeader("Sec-WebSocket-Draft"); } + // Remember requested version for possible error message later + int requestedVersion = draft; AbstractHttpConnection http = AbstractHttpConnection.getCurrentConnection(); if (http instanceof BlockingHttpConnection) throw new IllegalStateException("Websockets not supported on blocking connectors"); @@ -252,7 +254,7 @@ public class WebSocketFactory extends AbstractLifeCycle draft=Integer.MAX_VALUE; switch (draft) { - case -1: // unspecified draft/version + case -1: // unspecified draft/version (such as early OSX Safari 5.1 and iOS 5.x) case 0: // Old school draft/version { connection = new WebSocketServletConnectionD00(this, websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol); @@ -283,7 +285,6 @@ public class WebSocketFactory extends AbstractLifeCycle } default: { - LOG.warn("Unsupported Websocket version: " + draft); // Per RFC 6455 - 4.4 - Supporting Multiple Versions of WebSocket Protocol // Using the examples as outlined String versions="13"; @@ -295,7 +296,20 @@ public class WebSocketFactory extends AbstractLifeCycle versions+=", 0"; response.setHeader("Sec-WebSocket-Version", versions); - throw new HttpException(400, "Unsupported websocket version specification: " + draft); + + // Make error clear for developer / end-user + StringBuilder err = new StringBuilder(); + err.append("Unsupported websocket client version specification "); + if(requestedVersion >= 0) { + err.append("[").append(requestedVersion).append("]"); + } else { + err.append(""); + } + err.append(", configured minVersion [").append(_minVersion).append("]"); + err.append(", reported supported versions [").append(versions).append("]"); + LOG.warn(err.toString()); // Log it + // use spec language for unsupported versions + throw new HttpException(400, "Unsupported websocket version specification"); // Tell client } } diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketMinVersionTest.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketMinVersionTest.java new file mode 100644 index 00000000000..5fb4713c0f2 --- /dev/null +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketMinVersionTest.java @@ -0,0 +1,119 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.websocket; + +import static org.hamcrest.Matchers.*; + +import java.net.URI; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.websocket.helper.CaptureSocket; +import org.eclipse.jetty.websocket.helper.SafariD00; +import org.eclipse.jetty.websocket.helper.WebSocketCaptureServlet; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class WebSocketMinVersionTest +{ + private Server server; + private WebSocketCaptureServlet servlet; + private URI serverUri; + + @BeforeClass + public static void initLogging() + { + // Configure Logging + // System.setProperty("org.eclipse.jetty.util.log.class",StdErrLog.class.getName()); + System.setProperty("org.eclipse.jetty.websocket.helper.LEVEL","DEBUG"); + } + + @Before + public void startServer() throws Exception + { + // Configure Server + server = new Server(0); + + ServletContextHandler context = new ServletContextHandler(); + context.setContextPath("/"); + server.setHandler(context); + + // Serve capture servlet + servlet = new WebSocketCaptureServlet(); + ServletHolder holder = new ServletHolder(servlet); + holder.setInitParameter("minVersion","8"); + context.addServlet(holder,"/"); + + // Start Server + server.start(); + + Connector conn = server.getConnectors()[0]; + String host = conn.getHost(); + if (host == null) + { + host = "localhost"; + } + int port = conn.getLocalPort(); + serverUri = new URI(String.format("ws://%s:%d/",host,port)); + // System.out.printf("Server URI: %s%n",serverUri); + } + + @Test + public void testAttemptUpgrade() throws Exception + { + SafariD00 safari = new SafariD00(serverUri); + + try + { + safari.connect(); + safari.issueHandshake(); + Assert.fail("Expected upgrade failure"); + } + catch(IllegalStateException e) { + String respHeader = e.getMessage(); + Assert.assertThat("Response Header", respHeader, allOf( + containsString("HTTP/1.1 400 Unsupported"), + containsString("minVersion [8]"), + containsString("[13, 8]"))); + } + finally + { + // System.out.println("Closing client socket"); + safari.disconnect(); + } + } + + public static void threadSleep(int dur, TimeUnit unit) throws InterruptedException + { + long ms = TimeUnit.MILLISECONDS.convert(dur,unit); + Thread.sleep(ms); + } + + @After + public void stopServer() throws Exception + { + server.stop(); + } +} diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/helper/SafariD00.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/helper/SafariD00.java index d1a91e83ca4..ac3c4757d0b 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/helper/SafariD00.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/helper/SafariD00.java @@ -23,6 +23,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; +import java.net.ConnectException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; @@ -35,6 +36,7 @@ import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.StdErrLog; import org.junit.Assert; +import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.is; public class SafariD00 @@ -109,12 +111,14 @@ public class SafariD00 // Read HTTP 101 Upgrade / Handshake Response InputStreamReader reader = new InputStreamReader(in); + StringBuilder respHeaders = new StringBuilder(); LOG.debug("Reading http headers"); int crlfs = 0; while (true) { int read = in.read(); + respHeaders.append((char)read); if (read == '\r' || read == '\n') ++crlfs; else @@ -122,6 +126,16 @@ public class SafariD00 if (crlfs == 4) break; } + + if(respHeaders.toString().startsWith("HTTP/1.1 101 ") == false) { + String respLine = respHeaders.toString(); + int idx = respLine.indexOf('\r'); + if(idx > 0) { + respLine = respLine.substring(0,idx); + } + LOG.debug("Response Headers: {}",respHeaders.toString()); + throw new IllegalStateException(respLine); + } // Read expected handshake hixie bytes byte hixieHandshakeExpected[] = TypeUtil.fromHexString("c7438d956cf611a6af70603e6fa54809"); From 0664cee41d696677b55511763b3f14396c6c56c8 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 22 Feb 2013 12:12:53 +1100 Subject: [PATCH 09/16] add example from documentation --- .../embedded/src/main/java/HelloWorld.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 examples/embedded/src/main/java/HelloWorld.java diff --git a/examples/embedded/src/main/java/HelloWorld.java b/examples/embedded/src/main/java/HelloWorld.java new file mode 100644 index 00000000000..2806fc30a37 --- /dev/null +++ b/examples/embedded/src/main/java/HelloWorld.java @@ -0,0 +1,50 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; +import java.io.IOException; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.handler.AbstractHandler; + +public class HelloWorld extends AbstractHandler +{ + @Override + public void handle(String target, + Request baseRequest, + HttpServletRequest request, + HttpServletResponse response) + throws IOException, ServletException + { + response.setContentType("text/html;charset=utf-8"); + response.setStatus(HttpServletResponse.SC_OK); + baseRequest.setHandled(true); + response.getWriter().println("

Hello World

"); + } + + public static void main(String[] args) throws Exception + { + Server server = new Server(8080); + server.setHandler(new HelloWorld()); + + server.start(); + server.join(); + } +} From 1153e0455c9a38bb37d1ea0e1b61f4dc8c039c60 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Fri, 22 Feb 2013 13:00:07 +1100 Subject: [PATCH 10/16] Use etc/jetty-plus.xml and etc/jetty-annotations.xml in start.ini for test-spec webapp --- .../src/main/templates/annotations-context-header.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test-webapps/test-servlet-spec/test-spec-webapp/src/main/templates/annotations-context-header.xml b/tests/test-webapps/test-servlet-spec/test-spec-webapp/src/main/templates/annotations-context-header.xml index 775008fb660..1ec49c7c2fc 100644 --- a/tests/test-webapps/test-servlet-spec/test-spec-webapp/src/main/templates/annotations-context-header.xml +++ b/tests/test-webapps/test-servlet-spec/test-spec-webapp/src/main/templates/annotations-context-header.xml @@ -18,6 +18,9 @@ + /test-spec /webapps/test-spec.war From b2b888d18a8e2ada0c0b05361f74fb6dd9f26602 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Fri, 22 Feb 2013 15:22:40 +1100 Subject: [PATCH 11/16] Use etc/jetty-plus.xml from start.ini by preference for test-jndi-webapp --- .../src/main/templates/jetty-test-jndi-header.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test-webapps/test-jndi-webapp/src/main/templates/jetty-test-jndi-header.xml b/tests/test-webapps/test-jndi-webapp/src/main/templates/jetty-test-jndi-header.xml index 0faae621b0b..de012e74cc5 100644 --- a/tests/test-webapps/test-jndi-webapp/src/main/templates/jetty-test-jndi-header.xml +++ b/tests/test-webapps/test-jndi-webapp/src/main/templates/jetty-test-jndi-header.xml @@ -15,6 +15,8 @@ + /test-jndi /webapps/test-jndi.war From c302a404cdf560f0a9d48f69d60401f61dbdecbe Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 22 Feb 2013 15:49:38 +1100 Subject: [PATCH 12/16] refined jetty embedded examples --- .../eclipse/jetty/embedded/LikeJettyXml.java | 136 ++++++++++++------ .../jetty/embedded/ManyConnectors.java | 84 ++++------- .../eclipse/jetty/embedded/OneConnector.java | 57 ++++++++ .../eclipse/jetty/embedded/SpdyConnector.java | 94 ++++++++++++ .../src/main/config/etc/jetty-https.xml | 15 +- jetty-server/src/main/config/etc/jetty.xml | 15 +- 6 files changed, 293 insertions(+), 108 deletions(-) create mode 100644 examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneConnector.java create mode 100644 examples/embedded/src/main/java/org/eclipse/jetty/embedded/SpdyConnector.java diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java index bd01c93dc0b..181e6c5c933 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java @@ -21,15 +21,20 @@ package org.eclipse.jetty.embedded; import java.lang.management.ManagementFactory; import org.eclipse.jetty.deploy.DeploymentManager; +import org.eclipse.jetty.deploy.PropertiesConfigurationManager; import org.eclipse.jetty.deploy.providers.WebAppProvider; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.security.HashLoginService; +import org.eclipse.jetty.server.ForwardedRequestCustomizer; import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.LowResourceMonitor; import org.eclipse.jetty.server.NCSARequestLog; +import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerCollection; @@ -46,31 +51,55 @@ public class LikeJettyXml String jetty_home = System.getProperty("jetty.home","../../jetty-distribution/target/distribution"); System.setProperty("jetty.home",jetty_home); + + // === jetty.xml === // Setup Threadpool QueuedThreadPool threadPool = new QueuedThreadPool(); threadPool.setMaxThreads(500); + // Server Server server = new Server(threadPool); - server.manage(threadPool); + + // Scheduler + server.addBean(new TimerScheduler()); + + // HTTP Configuration + HttpConfiguration http_config = new HttpConfiguration(); + http_config.setSecureScheme("https"); + http_config.setSecurePort(8443); + http_config.setOutputBufferSize(32768); + http_config.setRequestHeaderSize(8192); + http_config.setResponseHeaderSize(8192); + http_config.setSendServerVersion(true); + http_config.setSendDateHeader(false); + // httpConfig.addCustomizer(new ForwardedRequestCustomizer()); + + // Handler Structure + HandlerCollection handlers = new HandlerCollection(); + ContextHandlerCollection contexts = new ContextHandlerCollection(); + handlers.setHandlers(new Handler[] { contexts, new DefaultHandler() }); + server.setHandler(handlers); + + // Extra options server.setDumpAfterStart(false); server.setDumpBeforeStop(false); - - server.addBean(new TimerScheduler()); + server.setStopAtShutdown(true); - // Setup JMX + + // === jetty-jmx.xml === MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer()); server.addBean(mbContainer); - // Setup Connectors - HttpConnectionFactory http = new HttpConnectionFactory(); - http.getHttpConfiguration().setSecurePort(8443); - http.getHttpConfiguration().setSendServerVersion(true); - ServerConnector connector = new ServerConnector(server,http); - connector.setPort(8080); - connector.setIdleTimeout(30000); - - server.addConnector(connector); + + // === jetty-http.xml === + ServerConnector http = new ServerConnector(server,new HttpConnectionFactory(http_config)); + http.setPort(8080); + http.setIdleTimeout(30000); + server.addConnector(http); + + // === jetty-https.xml === + // SSL Context Factory SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath(jetty_home + "/etc/keystore"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); @@ -85,52 +114,75 @@ public class LikeJettyXml "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"); - ServerConnector sslConnector = new ServerConnector(server,sslContextFactory); + + // SSL HTTP Configuration + HttpConfiguration https_config = new HttpConfiguration(http_config); + https_config.addCustomizer(new SecureRequestCustomizer()); + + // SSL Connector + ServerConnector sslConnector = new ServerConnector(server, + new SslConnectionFactory(sslContextFactory,"http/1.1"), + new HttpConnectionFactory(https_config)); sslConnector.setPort(8443); server.addConnector(sslConnector); - sslConnector.open(); - HandlerCollection handlers = new HandlerCollection(); - ContextHandlerCollection contexts = new ContextHandlerCollection(); - RequestLogHandler requestLogHandler = new RequestLogHandler(); - handlers.setHandlers(new Handler[] { contexts, new DefaultHandler(), requestLogHandler }); - - StatisticsHandler stats = new StatisticsHandler(); - stats.setHandler(handlers); - - server.setHandler(stats); - - // Setup deployers + // === jetty-deploy.xml === DeploymentManager deployer = new DeploymentManager(); deployer.setContexts(contexts); - server.addBean(deployer); + deployer.setContextAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",".*/servlet-api-[^/]*\\.jar$"); WebAppProvider webapp_provider = new WebAppProvider(); webapp_provider.setMonitoredDirName(jetty_home + "/webapps"); - webapp_provider.setParentLoaderPriority(false); + webapp_provider.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml"); + webapp_provider.setScanInterval(1); webapp_provider.setExtractWars(true); - webapp_provider.setScanInterval(2); - //webapp_provider.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml"); - deployer.addAppProvider(webapp_provider); + webapp_provider.setConfigurationManager(new PropertiesConfigurationManager()); + deployer.addAppProvider(webapp_provider); + server.addBean(deployer); + + + // === jetty-stats.xml === + StatisticsHandler stats = new StatisticsHandler(); + stats.setHandler(server.getHandler()); + server.setHandler(stats); + + + // === jetty-requestlog.xml === + NCSARequestLog requestLog = new NCSARequestLog(); + requestLog.setFilename(jetty_home + "/logs/jetty-yyyy_mm_dd.log"); + requestLog.setFilenameDateFormat("yyyy_MM_dd"); + requestLog.setRetainDays(90); + requestLog.setAppend(true); + requestLog.setExtended(false); + requestLog.setLogCookies(false); + requestLog.setLogTimeZone("GMT"); + RequestLogHandler requestLogHandler = new RequestLogHandler(); + requestLogHandler.setRequestLog(requestLog); + handlers.addHandler(requestLogHandler); + + + // === jetty-lowresources.xml === + LowResourceMonitor lowResourcesMonitor=new LowResourceMonitor(server); + lowResourcesMonitor.setPeriod(1000); + lowResourcesMonitor.setLowResourcesIdleTimeout(200); + lowResourcesMonitor.setMonitorThreads(true); + lowResourcesMonitor.setMaxConnections(0); + lowResourcesMonitor.setMaxMemory(0); + lowResourcesMonitor.setMaxLowResourcesTime(5000); + server.addBean(lowResourcesMonitor); + + + // === test-realm.xml === HashLoginService login = new HashLoginService(); login.setName("Test Realm"); login.setConfig(jetty_home + "/etc/realm.properties"); + login.setRefreshInterval(0); server.addBean(login); - NCSARequestLog requestLog = new NCSARequestLog(jetty_home + "/logs/jetty-yyyy_mm_dd.log"); - requestLog.setExtended(false); - requestLogHandler.setRequestLog(requestLog); - - server.setStopAtShutdown(true); - - LowResourceMonitor lowResourcesMonitor=new LowResourceMonitor(server); - lowResourcesMonitor.setLowResourcesIdleTimeout(1000); - lowResourcesMonitor.setMaxConnections(2); - lowResourcesMonitor.setPeriod(1200); - server.addBean(lowResourcesMonitor); + // Start the server server.start(); server.join(); } diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java index 259ee525795..c8b5f94c4f5 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java @@ -18,100 +18,64 @@ package org.eclipse.jetty.embedded; -import org.eclipse.jetty.io.ArrayByteBufferPool; -import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.ForwardedRequestCustomizer; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SslConnectionFactory; -import org.eclipse.jetty.spdy.server.NPNServerConnectionFactory; -import org.eclipse.jetty.spdy.server.http.HTTPSPDYServerConnectionFactory; -import org.eclipse.jetty.spdy.server.http.PushStrategy; -import org.eclipse.jetty.spdy.server.http.ReferrerPushStrategy; import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.eclipse.jetty.util.thread.TimerScheduler; /* ------------------------------------------------------------ */ /** * A Jetty server with multiple connectors. - * */ public class ManyConnectors { public static void main(String[] args) throws Exception { - String jetty_home = System.getProperty("jetty.home","../jetty-server/src/main/config"); + String jetty_home = System.getProperty("jetty.home","../../jetty-distribution/target/distribution"); System.setProperty("jetty.home", jetty_home); + // The Server Server server = new Server(); - // HTTP connector - ServerConnector connector0 = new ServerConnector(server); - connector0.setPort(8080); - connector0.setIdleTimeout(30000); + // HTTP Configuration + HttpConfiguration http_config = new HttpConfiguration(); + http_config.setSecureScheme("https"); + http_config.setSecurePort(8443); + http_config.setOutputBufferSize(32768); - // HTTPS connector + // HTTP connector + ServerConnector http = new ServerConnector(server,new HttpConnectionFactory(http_config)); + http.setPort(8080); + http.setIdleTimeout(30000); + + // SSL Context Factory for HTTPS and SPDY SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath(jetty_home + "/etc/keystore"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); - ServerConnector connector1 = new ServerConnector(server,sslContextFactory); - connector1.setPort(8443); + // HTTPS Configuration + HttpConfiguration https_config = new HttpConfiguration(http_config); + https_config.addCustomizer(new SecureRequestCustomizer()); - - // A verbosely fully configured connector with SSL, SPDY and HTTP - - HttpConfiguration config = new HttpConfiguration(); - config.setSecureScheme("https"); - config.setSecurePort(8443); - config.setOutputBufferSize(32768); - config.setRequestHeaderSize(8192); - config.setResponseHeaderSize(8192); - config.addCustomizer(new ForwardedRequestCustomizer()); - config.addCustomizer(new SecureRequestCustomizer()); - - HttpConnectionFactory http = new HttpConnectionFactory(config); - http.setInputBufferSize(16384); - - PushStrategy push = new ReferrerPushStrategy(); - HTTPSPDYServerConnectionFactory spdy2 = new HTTPSPDYServerConnectionFactory(2,config,push); - spdy2.setInputBufferSize(8192); - spdy2.setInitialWindowSize(32768); - - HTTPSPDYServerConnectionFactory spdy3 = new HTTPSPDYServerConnectionFactory(3,config,push); - spdy2.setInputBufferSize(8192); - - NPNServerConnectionFactory npn = new NPNServerConnectionFactory(spdy3.getProtocol(),spdy2.getProtocol(),http.getProtocol()); - npn.setDefaultProtocol(http.getProtocol()); - npn.setInputBufferSize(1024); - - SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory,npn.getProtocol()); - - QueuedThreadPool threadPool = new QueuedThreadPool(); - threadPool.setMaxThreads(256); - TimerScheduler scheduler = new TimerScheduler(); - ByteBufferPool bufferPool= new ArrayByteBufferPool(32,4096,32768); - - ServerConnector connector2 = new ServerConnector(server,threadPool,scheduler,bufferPool,2,2,ssl,npn,spdy3,spdy2,http); - connector2.setDefaultProtocol("ssl-npn"); - connector2.setPort(8444); - connector2.setIdleTimeout(30000); - connector2.setSoLingerTime(10000); + // HTTPS connector + ServerConnector https = new ServerConnector(server, + new SslConnectionFactory(sslContextFactory,"http/1.1"), + new HttpConnectionFactory(https_config)); + https.setPort(8443); // Set the connectors - server.setConnectors(new Connector[] { connector0, connector1, connector2 }); - + server.setConnectors(new Connector[] { http, https }); + // Set a handler server.setHandler(new HelloHandler()); + // Start the server server.start(); - server.dumpStdErr(); server.join(); } } diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneConnector.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneConnector.java new file mode 100644 index 00000000000..cab95a6966a --- /dev/null +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneConnector.java @@ -0,0 +1,57 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.embedded; + +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +/* ------------------------------------------------------------ */ +/** + * A Jetty server with one connectors. + */ +public class OneConnector +{ + public static void main(String[] args) throws Exception + { + // The Server + Server server = new Server(); + + // HTTP connector + ServerConnector http = new ServerConnector(server); + http.setHost("localhost"); + http.setPort(8080); + http.setIdleTimeout(30000); + + // Set the connectors + server.setConnectors(new Connector[] { http }); + + // Set a handler + server.setHandler(new HelloHandler()); + + // Start the server + server.start(); + server.join(); + } +} diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/SpdyConnector.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/SpdyConnector.java new file mode 100644 index 00000000000..0cb8e2b70ed --- /dev/null +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/SpdyConnector.java @@ -0,0 +1,94 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.embedded; + +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.spdy.server.NPNServerConnectionFactory; +import org.eclipse.jetty.spdy.server.SPDYServerConnectionFactory; +import org.eclipse.jetty.spdy.server.http.HTTPSPDYServerConnectionFactory; +import org.eclipse.jetty.spdy.server.http.ReferrerPushStrategy; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +/* ------------------------------------------------------------ */ +/** + * A Jetty server with HTTP and SPDY connectors. + */ +public class SpdyConnector +{ + public static void main(String[] args) throws Exception + { + String jetty_home = System.getProperty("jetty.home","../../jetty-distribution/target/distribution"); + System.setProperty("jetty.home", jetty_home); + + // The Server + Server server = new Server(); + + // HTTP Configuration + HttpConfiguration http_config = new HttpConfiguration(); + http_config.setSecureScheme("https"); + http_config.setSecurePort(8443); + + // HTTP connector + ServerConnector http = new ServerConnector(server,new HttpConnectionFactory(http_config)); + http.setPort(8080); + server.addConnector(http); + + // SSL Context Factory for HTTPS and SPDY + SslContextFactory sslContextFactory = new SslContextFactory(); + sslContextFactory.setKeyStorePath(jetty_home + "/etc/keystore"); + sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); + sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); + + // HTTPS Configuration + HttpConfiguration https_config = new HttpConfiguration(http_config); + https_config.addCustomizer(new SecureRequestCustomizer()); + + // SPDY versions + HTTPSPDYServerConnectionFactory spdy2 = + new HTTPSPDYServerConnectionFactory(2,https_config); + + HTTPSPDYServerConnectionFactory spdy3 = + new HTTPSPDYServerConnectionFactory(3,https_config,new ReferrerPushStrategy()); + + // NPN Factory + SPDYServerConnectionFactory.checkNPNAvailable(); + NPNServerConnectionFactory npn = new NPNServerConnectionFactory(spdy3.getProtocol(),spdy2.getProtocol(),http.getDefaultProtocol()); + npn.setDefaultProtocol(http.getDefaultProtocol()); + + // SSL Factory + SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory,npn.getProtocol()); + + // SPDY Connector + ServerConnector spdyConnector = new ServerConnector(server,ssl,npn,spdy3,spdy2,http.getDefaultConnectionFactory()); + spdyConnector.setPort(8443); + server.addConnector(spdyConnector); + + // Set a handler + server.setHandler(new HelloHandler()); + + // Start the server + server.start(); + server.join(); + } +} diff --git a/jetty-server/src/main/config/etc/jetty-https.xml b/jetty-server/src/main/config/etc/jetty-https.xml index 82a57d608d9..a4aad5940d4 100644 --- a/jetty-server/src/main/config/etc/jetty-https.xml +++ b/jetty-server/src/main/config/etc/jetty-https.xml @@ -24,6 +24,17 @@ OBF:1u2u1wml1z7s1z7a1wnl1u2g /etc/keystore OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4 + + + SSL_RSA_WITH_DES_CBC_SHA + SSL_DHE_RSA_WITH_DES_CBC_SHA + SSL_DHE_DSS_WITH_DES_CBC_SHA + SSL_RSA_EXPORT_WITH_RC4_40_MD5 + SSL_RSA_EXPORT_WITH_DES40_CBC_SHA + SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA + SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA + + @@ -32,7 +43,7 @@ - + @@ -65,7 +76,7 @@ - + diff --git a/jetty-server/src/main/config/etc/jetty.xml b/jetty-server/src/main/config/etc/jetty.xml index 477ba55746a..8a4c6953232 100644 --- a/jetty-server/src/main/config/etc/jetty.xml +++ b/jetty-server/src/main/config/etc/jetty.xml @@ -49,6 +49,15 @@ false + + + + + + + + + @@ -71,10 +80,8 @@ 32768 8192 8192 - - + true + false