diff options
author | Greg Wilkins | 2016-01-14 00:00:06 +0000 |
---|---|---|
committer | Greg Wilkins | 2016-01-14 00:00:06 +0000 |
commit | c5cbc64e7799409101e6dd28c143dbea397724cf (patch) | |
tree | 6505450207f77caf51950534b5c5cfa22e7fae82 | |
parent | 122ac9c4459818313bed8bf1663680b6cc93f29d (diff) | |
parent | 6e85554aadf6bb0e4904a93f0841c9d23c346efc (diff) | |
download | org.eclipse.jetty.project-c5cbc64e7799409101e6dd28c143dbea397724cf.tar.gz org.eclipse.jetty.project-c5cbc64e7799409101e6dd28c143dbea397724cf.tar.xz org.eclipse.jetty.project-c5cbc64e7799409101e6dd28c143dbea397724cf.zip |
Merge remote-tracking branch 'origin/jetty-9.3.x'
32 files changed, 844 insertions, 172 deletions
diff --git a/VERSION.txt b/VERSION.txt index 57dd1679c5..d63ae5a19c 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1,5 +1,54 @@ jetty-9.4.0-SNAPSHOT +jetty-9.3.7.RC0 - 05 January 2016 + + 458745 Async ISE in async Echo + + 481567 permessage-deflate causing data-dependent ju.zip.DataFormatException: + invalid stored block lengths + + 482173 Track original Query string in Rewrite RuleContainer too + + 482243 Fixed GzipHandler for Include. + + 482270 Expose upgrade request locales. + + 482272 Fixed relative symlink checking + + 482506 HTTP/2 load test with h2load fails. + + 482670 HttpURI wrongly parser URI paths starting with /@ + + 482855 Content-Length omitted for POST requests with empty body + + 482959 Local stream count never decrements when closing a stream causing + IllegalStateException. + + 483009 MultiPartContentProvider may send wrong Content-Length. + + 483039 HTTP2 Upgrade case sensitivity on Connection header + + 483344 text/csv Mime Type For CSV in mime properties File + + 483413 Warn on @Deprecated servlet/filter use + + 483422 Empty chunked body in 304 Response + + 483620 Servlet annotation mapping to "/" should override webdefault.xml + mapping + + 483857 jetty-client onComplete isn't called in case of exception in + GZIPContentDecoder. + + 483878 Parallel requests stuck via the http client transport over HTTP/2. + + 484167 GOAWAY frames aren't handling disconnects appropriately on Client. + + 484210 HttpClient over HTTP/2 should honor maxConcurrentStreams. + + 484262 Race condition between GOAWAY disconnect and ability to make new + request. + + 484349 Promote WebSocket PathMappings / PathSpec to Jetty Http + + 484350 Allow GzipHandler path include/exclude to use regex + + 484397 Unavoidable NullPointerException in onMessage-Handler for + PongMessages + + 484440 Swap WebSocket PathMappings for new jetty-http PathMappings + + 484585 Avoid sending request using a connection that is idle timing out. + + 484603 HashLoginService does not stop its PropertyUserStore + + 484612 Restore WebSocket Session.close() sending 1000/Normal status code + + 484621 Client hangs till timeout when Authentication.authenticate() throws + exception. + + 484622 Improve handling of Direct and Mapped buffers for static content + + 484624 Disable CachingWebAppClassLoader + + 484657 Support HSTS rfc6797 + + 484683 FastCGI request idle timeout is handled incorrectly. + + 484718 Review idle timeout handling. + + 484801 Avoid non-cached memory mapped files + + 484818 Expose interesting HTTP/2 attributes and operations via JMX. + + 484822 Jetty ThreadMonitor memory leak + + 484861 Improve FlowControlStrategy stall handling. + + 484876 Make simpler to customize the FlowControlStrategy. + + 484878 Make BufferingFlowControlStrategy.bufferRatio configurable via JMX. + jetty-9.3.6.v20151106 - 06 November 2015 + 419966 Add ContentProvider that submits multipart/form-data. + 472675 No main manifest attribute, in jetty-runner regression diff --git a/jetty-distribution/src/main/resources/bin/jetty.sh b/jetty-distribution/src/main/resources/bin/jetty.sh index 21c2c979f4..9dd1a49773 100755 --- a/jetty-distribution/src/main/resources/bin/jetty.sh +++ b/jetty-distribution/src/main/resources/bin/jetty.sh @@ -527,6 +527,7 @@ case "$ACTION" in restart) JETTY_SH=$0 + > "$JETTY_STATE" if [ ! -f $JETTY_SH ]; then if [ ! -f $JETTY_HOME/bin/jetty.sh ]; then echo "$JETTY_HOME/bin/jetty.sh does not exist." diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/AttributeNormalizer.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/AttributeNormalizer.java new file mode 100644 index 0000000000..8494386324 --- /dev/null +++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/AttributeNormalizer.java @@ -0,0 +1,157 @@ +// +// ======================================================================== +// Copyright (c) 1995-2016 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.quickstart; + +import java.io.File; +import java.net.URI; +import java.net.URL; +import java.nio.file.Path; + +import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.resource.Resource; + +/** + * Normalize Attribute to String. + * <p>Replaces and expands: + * <ul> + * <li>${WAR}</li> + * <li>${jetty.base}</li> + * <li>${jetty.home}</li> + * <li>${user.home}</li> + * <li>${user.dir}</li> + * </ul> + */ +public class AttributeNormalizer +{ + private static final Logger LOG = Log.getLogger(AttributeNormalizer.class); + private final Path _warPath; + private final Path _jettyBasePath; + private final Path _jettyHomePath; + private final Path _userHomePath; + private final Path _userDirPath; + + + public AttributeNormalizer(Resource baseResource) + { + try + { + _warPath=baseResource==null?null:baseResource.getFile().toPath(); + _jettyBasePath=systemPath("jetty.base"); + _jettyHomePath=systemPath("jetty.home"); + _userHomePath=systemPath("user.home"); + _userDirPath=systemPath("user.dir"); + } + catch(Exception e) + { + throw new IllegalArgumentException(e); + } + } + + private static Path systemPath(String property) throws Exception + { + String p=System.getProperty(property); + if (p!=null) + return new File(p).getAbsoluteFile().getCanonicalFile().toPath(); + return null; + } + + public String normalize(Object o) + { + try + { + // Find a URI + URI uri=null; + if (o instanceof URI) + uri=(URI)o; + else if (o instanceof URL) + uri = ((URL)o).toURI(); + else if (o instanceof File) + uri = ((File)o).toURI(); + else + { + String s=o.toString(); + uri=new URI(s); + if (uri.getScheme()==null) + return s; + } + + if ("jar".equalsIgnoreCase(uri.getScheme())) + { + String raw = uri.getRawSchemeSpecificPart(); + int bang=raw.indexOf("!/"); + String normal=normalize(raw.substring(0,bang)); + String suffix=raw.substring(bang); + return "jar:"+normal+suffix; + } + else if ("file".equalsIgnoreCase(uri.getScheme())) + { + return "file:"+normalizePath(new File(uri).toPath()); + } + + } + catch(Exception e) + { + LOG.warn(e); + } + return String.valueOf(o); + } + + public String normalizePath(Path path) + { + if (_warPath!=null && path.startsWith(_warPath)) + return URIUtil.addPaths("${WAR}",_warPath.relativize(path).toString()); + if (_jettyBasePath!=null && path.startsWith(_jettyBasePath)) + return URIUtil.addPaths("${jetty.base}",_jettyBasePath.relativize(path).toString()); + if (_jettyHomePath!=null && path.startsWith(_jettyHomePath)) + return URIUtil.addPaths("${jetty.home}",_jettyHomePath.relativize(path).toString()); + if (_userHomePath!=null && path.startsWith(_userHomePath)) + return URIUtil.addPaths("${user.home}",_userHomePath.relativize(path).toString()); + if (_userDirPath!=null && path.startsWith(_userDirPath)) + return URIUtil.addPaths("${user.dir}",_userDirPath.relativize(path).toString()); + + return path.toString(); + } + + + public String expand(String s) + { + int i=s.indexOf("${"); + if (i<0) + return s; + int e=s.indexOf('}',i+3); + String prop=s.substring(i+2,e); + switch(prop) + { + case "WAR": + return s.substring(0,i)+_warPath+expand(s.substring(e+1)); + case "jetty.base": + return s.substring(0,i)+_jettyBasePath+expand(s.substring(e+1)); + case "jetty.home": + return s.substring(0,i)+_jettyHomePath+expand(s.substring(e+1)); + case "user.home": + return s.substring(0,i)+_userHomePath+expand(s.substring(e+1)); + case "user.dir": + return s.substring(0,i)+_userDirPath+expand(s.substring(e+1)); + default: + return s; + } + } +} diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java index 5db988d893..34c401222a 100644 --- a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java +++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java @@ -22,6 +22,9 @@ package org.eclipse.jetty.quickstart; import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.EventListener; @@ -55,6 +58,7 @@ import org.eclipse.jetty.servlet.ServletMapping; import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.webapp.MetaData; import org.eclipse.jetty.webapp.MetaData.OriginInfo; @@ -128,16 +132,16 @@ public class QuickStartDescriptorGenerator // Set some special context parameters // The location of the war file on disk - String resourceBase = _webApp.getBaseResource().getFile().getCanonicalFile().getAbsoluteFile().toURI().toString(); + AttributeNormalizer normalizer = new AttributeNormalizer(_webApp.getBaseResource()); // The library order addContextParamFromAttribute(out,ServletContext.ORDERED_LIBS); //the servlet container initializers addContextParamFromAttribute(out,AnnotationConfiguration.CONTAINER_INITIALIZERS); //the tlds discovered - addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_TLDS,resourceBase); + addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_TLDS,normalizer); //the META-INF/resources discovered - addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_RESOURCES,resourceBase); + addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_RESOURCES,normalizer); // init params @@ -515,7 +519,27 @@ public class QuickStartDescriptorGenerator */ private void addContextParamFromAttribute(XmlAppendable out, String attribute) throws IOException { - addContextParamFromAttribute(out,attribute,null); + Object o = _webApp.getAttribute(attribute); + if (o == null) + return; + + Collection<?> c = (o instanceof Collection)? (Collection<?>)o:Collections.singletonList(o); + StringBuilder v=new StringBuilder(); + for (Object i:c) + { + if (i!=null) + { + if (v.length()>0) + v.append(",\n "); + else + v.append("\n "); + QuotedStringTokenizer.quote(v,i.toString()); + } + } + out.openTag("context-param") + .tag("param-name",attribute) + .tagCDATA("param-value",v.toString()) + .closeTag(); } /** @@ -526,7 +550,7 @@ public class QuickStartDescriptorGenerator * @param resourceBase * @throws IOException */ - private void addContextParamFromAttribute(XmlAppendable out, String attribute, String resourceBase) throws IOException + private void addContextParamFromAttribute(XmlAppendable out, String attribute, AttributeNormalizer normalizer) throws IOException { Object o = _webApp.getAttribute(attribute); if (o == null) @@ -542,16 +566,14 @@ public class QuickStartDescriptorGenerator v.append(",\n "); else v.append("\n "); - if (resourceBase==null) - QuotedStringTokenizer.quote(v,i.toString()); - else - QuotedStringTokenizer.quote(v,i.toString().replace(resourceBase,"${WAR}/")); + QuotedStringTokenizer.quote(v,normalizer.normalize(i)); } } out.openTag("context-param") .tag("param-name",attribute) .tagCDATA("param-value",v.toString()) - .closeTag(); + .closeTag(); + } /** diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorProcessor.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorProcessor.java index 924b0dd5f9..35d41ea17a 100644 --- a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorProcessor.java +++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorProcessor.java @@ -99,6 +99,7 @@ public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor values.add(value); } + AttributeNormalizer normalizer = new AttributeNormalizer(context.getBaseResource()); // handle values switch(name) { @@ -125,15 +126,14 @@ public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor case MetaInfConfiguration.METAINF_TLDS: { List<Object> tlds = new ArrayList<>(); - String war=context.getBaseResource().getURI().toString(); Object o=context.getAttribute(MetaInfConfiguration.METAINF_TLDS); if (o instanceof Collection<?>) tlds.addAll((Collection<?>)o); for (String i : values) { - Resource r = Resource.newResource(i.replace("${WAR}/",war)); + Resource r = Resource.newResource(normalizer.expand(i)); if (r.exists()) - tlds.add(r.getURL()); + tlds.add(r.getURI().toURL()); else throw new IllegalArgumentException("TLD not found: "+r); } @@ -145,10 +145,9 @@ public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor case MetaInfConfiguration.METAINF_RESOURCES: { - String war=context.getBaseResource().getURI().toString(); for (String i : values) { - Resource r = Resource.newResource(i.replace("${WAR}/",war)); + Resource r = Resource.newResource(normalizer.expand(i)); if (r.exists()) visitMetaInfResource(context,r); else diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java index 9dad91dbfc..cc7eb05f58 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java @@ -184,12 +184,11 @@ public class SecureRequestCustomizer implements HttpConfiguration.Customizer /** - * <p> * Customizes the request attributes for general secure settings. * The default impl calls {@link Request#setSecure(boolean)} with true * and sets a response header if the Strict-Transport-Security options * are set. - * </p> + * @param request the request being customized */ protected void customizeSecure(Request request) { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java index 186c094eb0..e94736ee26 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java @@ -47,7 +47,7 @@ import org.eclipse.jetty.util.log.Logger; /** ContextHandlerCollection. * * This {@link org.eclipse.jetty.server.handler.HandlerCollection} is creates a - * {@link org.eclipse.jetty.http.PathMap} to it's contained handlers based + * Map of contexts to it's contained handlers based * on the context path and virtual hosts of any contained {@link org.eclipse.jetty.server.handler.ContextHandler}s. * The contexts do not need to be directly contained, only children of the contained handlers. * Multiple contexts may have the same context path and they are called in order until one diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java index f353e7f09a..2d23ff564b 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java @@ -27,6 +27,7 @@ import java.net.Socket; import java.nio.charset.StandardCharsets; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -36,6 +37,7 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.Test; @@ -58,8 +60,8 @@ public class SSLCloseTest server.addConnector(connector); server.setHandler(new WriteHandler()); server.start(); - - SSLContext ctx=SSLContext.getInstance("SSLv3"); + + SSLContext ctx=SSLContext.getInstance("TLSv1.2"); ctx.init(null,SslContextFactory.TRUST_ALL_CERTS,new java.security.SecureRandom()); int port=connector.getLocalPort(); 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 9b76d0e702..a010774b15 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 @@ -189,7 +189,7 @@ public class SSLEngineTest Socket[] client=new Socket[numConns]; - SSLContext ctx=SSLContext.getInstance("SSLv3"); + SSLContext ctx=SSLContext.getInstance("TLSv1.2"); ctx.init(null,SslContextFactory.TRUST_ALL_CERTS,new java.security.SecureRandom()); int port=connector.getLocalPort(); diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java b/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java index 8e9b6b8b4c..55877cd245 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java @@ -250,14 +250,10 @@ public class SslContextFactory extends AbstractLifeCycle setTrustAll(trustAll); addExcludeProtocols("SSL", "SSLv2", "SSLv2Hello", "SSLv3"); setExcludeCipherSuites( - "SSL_RSA_WITH_DES_CBC_SHA", - "SSL_DHE_RSA_WITH_DES_CBC_SHA", + "^.*_RSA_.*_(MD5|SHA|SHA1)$", "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"); -} + } /** * Construct an instance of SslContextFactory diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/FileSystemResourceTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/resource/FileSystemResourceTest.java index 25418ee060..392524c962 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/FileSystemResourceTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/resource/FileSystemResourceTest.java @@ -222,7 +222,7 @@ public class FileSystemResourceTest @Test public void testAddPath() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Path subdir = dir.resolve("sub"); FS.ensureDirExists(subdir.toFile()); @@ -240,7 +240,7 @@ public class FileSystemResourceTest @Test public void testAddRootPath() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Path subdir = dir.resolve("sub"); Files.createDirectories(subdir); @@ -288,7 +288,7 @@ public class FileSystemResourceTest @Test public void testIsContainedIn() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path foo = dir.resolve("foo"); Files.createFile(foo); @@ -303,7 +303,7 @@ public class FileSystemResourceTest @Test public void testIsDirectory() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path foo = dir.resolve("foo"); Files.createFile(foo); @@ -324,7 +324,7 @@ public class FileSystemResourceTest @Test public void testLastModified() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); File file = testdir.getFile("foo"); file.createNewFile(); @@ -340,7 +340,7 @@ public class FileSystemResourceTest @Test public void testLastModified_NotExists() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); try (Resource base = newResource(dir.toFile())) { @@ -352,7 +352,7 @@ public class FileSystemResourceTest @Test public void testLength() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path file = dir.resolve("foo"); @@ -375,7 +375,7 @@ public class FileSystemResourceTest @Test public void testLength_NotExists() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); try (Resource base = newResource(dir.toFile())) @@ -388,7 +388,7 @@ public class FileSystemResourceTest @Test public void testDelete() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path file = dir.resolve("foo"); Files.createFile(file); @@ -408,7 +408,7 @@ public class FileSystemResourceTest @Test public void testDelete_NotExists() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); try (Resource base = newResource(dir.toFile())) @@ -426,7 +426,7 @@ public class FileSystemResourceTest @Test public void testName() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); String expected = dir.toAbsolutePath().toString(); @@ -440,7 +440,7 @@ public class FileSystemResourceTest @Test public void testInputStream() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path file = dir.resolve("foo"); @@ -466,7 +466,7 @@ public class FileSystemResourceTest @Test public void testReadableByteChannel() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path file = dir.resolve("foo"); @@ -495,7 +495,7 @@ public class FileSystemResourceTest @Test public void testGetURI() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path file = dir.resolve("foo"); @@ -514,7 +514,7 @@ public class FileSystemResourceTest @Test public void testGetURL() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path file = dir.resolve("foo"); @@ -532,7 +532,7 @@ public class FileSystemResourceTest @Test public void testList() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Files.createFile(dir.resolve("foo")); @@ -561,7 +561,7 @@ public class FileSystemResourceTest @Test public void testSymlink() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Path foo = dir.resolve("foo"); Path bar = dir.resolve("bar"); @@ -601,7 +601,7 @@ public class FileSystemResourceTest @Test public void testNonExistantSymlink() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path foo = dir.resolve("foo"); @@ -644,7 +644,7 @@ public class FileSystemResourceTest @Test public void testCaseInsensitiveAlias() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path path = dir.resolve("file"); Files.createFile(path); @@ -681,7 +681,7 @@ public class FileSystemResourceTest @Test public void testCase8dot3Alias() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path path = dir.resolve("TextFile.Long.txt"); @@ -718,7 +718,7 @@ public class FileSystemResourceTest @Test public void testNTFSFileStreamAlias() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path path = dir.resolve("testfile"); @@ -761,7 +761,7 @@ public class FileSystemResourceTest @Test public void testNTFSFileDataStreamAlias() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path path = dir.resolve("testfile"); @@ -806,7 +806,7 @@ public class FileSystemResourceTest @Test public void testNTFSFileEncodedDataStreamAlias() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path path = dir.resolve("testfile"); @@ -843,7 +843,7 @@ public class FileSystemResourceTest @Test public void testSemicolon() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); try { @@ -868,7 +868,7 @@ public class FileSystemResourceTest @Test public void testSingleQuote() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); try @@ -894,7 +894,7 @@ public class FileSystemResourceTest @Test public void testSingleBackTick() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); try @@ -923,7 +923,7 @@ public class FileSystemResourceTest @Test public void testBrackets() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); try @@ -949,7 +949,7 @@ public class FileSystemResourceTest @Test public void testBraces() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); try @@ -978,7 +978,7 @@ public class FileSystemResourceTest @Test public void testCaret() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); try @@ -1007,7 +1007,7 @@ public class FileSystemResourceTest @Test public void testPipe() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); try @@ -1040,13 +1040,13 @@ public class FileSystemResourceTest @Test public void testExist_Normal() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path path = dir.resolve("a.jsp"); Files.createFile(path); - URI ref = testdir.getDir().toURI().resolve("a.jsp"); + URI ref = testdir.getPath().toUri().resolve("a.jsp"); try (Resource fileres = newResource(ref)) { assertThat("Resource: " + fileres,fileres.exists(),is(true)); @@ -1056,7 +1056,7 @@ public class FileSystemResourceTest @Test public void testSingleQuoteInFileName() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path fooA = dir.resolve("foo's.txt"); @@ -1121,7 +1121,7 @@ public class FileSystemResourceTest @Test public void testExist_BadURINull() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path path = dir.resolve("a.jsp"); @@ -1130,7 +1130,7 @@ public class FileSystemResourceTest try { // request with null at end - URI uri = testdir.getDir().toURI().resolve("a.jsp%00"); + URI uri = testdir.getPath().toUri().resolve("a.jsp%00"); assertThat("Null URI",uri,notNullValue()); Resource r = newResource(uri); @@ -1147,7 +1147,7 @@ public class FileSystemResourceTest @Test public void testExist_BadURINullX() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path path = dir.resolve("a.jsp"); @@ -1156,7 +1156,7 @@ public class FileSystemResourceTest try { // request with null and x at end - URI uri = testdir.getDir().toURI().resolve("a.jsp%00x"); + URI uri = testdir.getPath().toUri().resolve("a.jsp%00x"); assertThat("NullX URI",uri,notNullValue()); Resource r = newResource(uri); @@ -1173,7 +1173,7 @@ public class FileSystemResourceTest @Test public void testEncoding() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Files.createDirectories(dir); Path specials = dir.resolve("a file with,spe#ials"); @@ -1192,7 +1192,7 @@ public class FileSystemResourceTest @Test public void testUtf8Dir() throws Exception { - Path dir = testdir.getDir().toPath().normalize().toRealPath(); + Path dir = testdir.getPath().normalize().toRealPath(); Path utf8Dir = dir.resolve("bãm"); Files.createDirectories(utf8Dir); @@ -1209,4 +1209,6 @@ public class FileSystemResourceTest assertThat("Alias: " + r,r,hasNoAlias()); } } + + } diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java index 0ca664436f..a5e65c0251 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java @@ -29,6 +29,7 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; import java.io.InputStream; import java.security.KeyStore; +import java.util.Arrays; import javax.net.ssl.SSLEngine; @@ -57,6 +58,20 @@ public class SslContextFactoryTest } @Test + public void testSLOTH() throws Exception + { + cf.setKeyStorePassword("storepwd"); + cf.setKeyManagerPassword("keypwd"); + + cf.start(); + + System.err.println(Arrays.asList(cf.getSelectedProtocols())); + for (String cipher : cf.getSelectedCipherSuites()) + System.err.println(cipher); + + } + + @Test public void testNoTsFileKs() throws Exception { cf.setKeyStorePassword("storepwd"); diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java index 13c30b7f95..87e4e76fc2 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java @@ -53,8 +53,6 @@ import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.WebSocketClient; import org.eclipse.jetty.websocket.client.io.UpgradeListener; -import org.eclipse.jetty.websocket.common.SessionFactory; -import org.eclipse.jetty.websocket.common.SessionListener; import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope; import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; @@ -73,7 +71,7 @@ import org.eclipse.jetty.websocket.jsr356.metadata.EndpointMetadata; * <p> * This should be specific to a JVM if run in a standalone mode. or specific to a WebAppContext if running on the Jetty server. */ -public class ClientContainer extends ContainerLifeCycle implements WebSocketContainer, WebSocketContainerScope, SessionListener +public class ClientContainer extends ContainerLifeCycle implements WebSocketContainer, WebSocketContainerScope { private static final Logger LOG = Log.getLogger(ClientContainer.class); @@ -105,8 +103,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont this.scopeDelegate = scope; client = new WebSocketClient(scope, new SslContextFactory(trustAll)); client.setEventDriverFactory(new JsrEventDriverFactory(client.getPolicy())); - SessionFactory sessionFactory = new JsrSessionFactory(this,this,client); - client.setSessionFactory(sessionFactory); + client.setSessionFactory(new JsrSessionFactory(this)); addBean(client); this.endpointClientMetadataCache = new ConcurrentHashMap<>(); diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSession.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSession.java index bb44774b1b..82db0bd93b 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSession.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSession.java @@ -44,7 +44,6 @@ import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.common.LogicalConnection; -import org.eclipse.jetty.websocket.common.SessionListener; import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.events.EventDriver; import org.eclipse.jetty.websocket.jsr356.endpoints.AbstractJsrEventDriver; @@ -74,9 +73,9 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess private JsrAsyncRemote asyncRemote; private JsrBasicRemote basicRemote; - public JsrSession(ClientContainer container, String id, URI requestURI, EventDriver websocket, LogicalConnection connection, SessionListener... sessionListeners) + public JsrSession(ClientContainer container, String id, URI requestURI, EventDriver websocket, LogicalConnection connection) { - super(container, requestURI, websocket, connection, sessionListeners); + super(container, requestURI, websocket, connection); if (!(websocket instanceof AbstractJsrEventDriver)) { throw new IllegalArgumentException("Cannot use, not a JSR WebSocket: " + websocket); diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSessionFactory.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSessionFactory.java index f17734d722..15cde46ebb 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSessionFactory.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSessionFactory.java @@ -19,36 +19,32 @@ package org.eclipse.jetty.websocket.jsr356; import java.net.URI; -import java.util.concurrent.atomic.AtomicLong; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.common.LogicalConnection; import org.eclipse.jetty.websocket.common.SessionFactory; -import org.eclipse.jetty.websocket.common.SessionListener; import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.events.EventDriver; import org.eclipse.jetty.websocket.jsr356.endpoints.AbstractJsrEventDriver; public class JsrSessionFactory implements SessionFactory { - private AtomicLong idgen = new AtomicLong(0); + private static final Logger LOG = Log.getLogger(JsrSessionFactory.class); private final ClientContainer container; - private final SessionListener[] listeners; - public JsrSessionFactory(ClientContainer container, SessionListener... sessionListeners) + public JsrSessionFactory(ClientContainer container) { + if(LOG.isDebugEnabled()) { + LOG.debug("Container: {}", container); + } this.container = container; - this.listeners = sessionListeners; } @Override public WebSocketSession createSession(URI requestURI, EventDriver websocket, LogicalConnection connection) { - return new JsrSession(container,getNextId(),requestURI,websocket,connection,listeners); - } - - public String getNextId() - { - return String.format("websocket-%d",idgen.incrementAndGet()); + return new JsrSession(container,connection.getId(),requestURI,websocket,connection); } @Override diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java index 2128e8ec64..8d114c37e0 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java @@ -30,6 +30,7 @@ import javax.websocket.server.ServerEndpointConfig; import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.events.EventDriverFactory; import org.eclipse.jetty.websocket.jsr356.ClientContainer; import org.eclipse.jetty.websocket.jsr356.JsrSessionFactory; @@ -56,7 +57,7 @@ public class ServerContainer extends ClientContainer implements javax.websocket. EventDriverFactory eventDriverFactory = this.webSocketServerFactory.getEventDriverFactory(); eventDriverFactory.addImplementation(new JsrServerEndpointImpl()); eventDriverFactory.addImplementation(new JsrServerExtendsEndpointImpl()); - this.webSocketServerFactory.addSessionFactory(new JsrSessionFactory(this,this)); + this.webSocketServerFactory.addSessionFactory(new JsrSessionFactory(this)); addBean(webSocketServerFactory); } @@ -240,4 +241,16 @@ public class ServerContainer extends ClientContainer implements javax.websocket. // incoming streaming buffer size webSocketServerFactory.getPolicy().setMaxTextMessageBufferSize(max); } + + @Override + public void onSessionClosed(WebSocketSession session) + { + webSocketServerFactory.onSessionClosed(session); + } + + @Override + public void onSessionOpened(WebSocketSession session) + { + webSocketServerFactory.onSessionOpened(session); + } } diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/SessionTrackingTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/SessionTrackingTest.java new file mode 100644 index 0000000000..22733ea606 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/SessionTrackingTest.java @@ -0,0 +1,183 @@ +// +// ======================================================================== +// Copyright (c) 1995-2016 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.jsr356.server; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.net.URI; +import java.util.Collection; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.websocket.CloseReason; +import javax.websocket.Endpoint; +import javax.websocket.EndpointConfig; +import javax.websocket.OnMessage; +import javax.websocket.Session; +import javax.websocket.server.ServerEndpoint; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.websocket.common.WebSocketSession; +import org.eclipse.jetty.websocket.jsr356.ClientContainer; +import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer; +import org.eclipse.jetty.websocket.server.WebSocketServerFactory; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class SessionTrackingTest +{ + public static class ClientSocket extends Endpoint + { + public Session session; + public CountDownLatch openLatch = new CountDownLatch(1); + public CountDownLatch closeLatch = new CountDownLatch(1); + + @Override + public void onOpen(Session session, EndpointConfig config) + { + this.session = session; + openLatch.countDown(); + } + + @Override + public void onClose(Session session, CloseReason closeReason) + { + closeLatch.countDown(); + } + + public void waitForOpen(long timeout, TimeUnit unit) throws InterruptedException + { + assertThat("ClientSocket opened",openLatch.await(timeout,unit),is(true)); + } + + public void waitForClose(long timeout, TimeUnit unit) throws InterruptedException + { + assertThat("ClientSocket opened",closeLatch.await(timeout,unit),is(true)); + } + } + + @ServerEndpoint("/test") + public static class EchoSocket + { + @OnMessage + public String echo(String msg) + { + return msg; + } + } + + private static Server server; + private static WebSocketServerFactory wsServerFactory; + private static URI serverURI; + + @BeforeClass + public static void startServer() throws Exception + { + Server server = new Server(); + ServerConnector serverConnector = new ServerConnector(server); + serverConnector.setPort(0); + server.addConnector(serverConnector); + ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS); + servletContextHandler.setContextPath("/"); + server.setHandler(servletContextHandler); + + ServerContainer serverContainer = WebSocketServerContainerInitializer.configureContext(servletContextHandler); + serverContainer.addEndpoint(EchoSocket.class); + + wsServerFactory = serverContainer.getBean(WebSocketServerFactory.class); + + server.start(); + + String host = serverConnector.getHost(); + if (StringUtil.isBlank(host)) + { + host = "localhost"; + } + serverURI = new URI("ws://" + host + ":" + serverConnector.getLocalPort()); + } + + @AfterClass + public static void stopServer() throws Exception + { + if (server == null) + { + return; + } + + server.stop(); + } + + @Test + public void testAddRemoveSessions() throws Exception + { + // Create Client + ClientContainer clientContainer = new ClientContainer(); + try + { + clientContainer.start(); + + // Establish connections + ClientSocket cli1 = new ClientSocket(); + clientContainer.connectToServer(cli1,serverURI.resolve("/test")); + cli1.waitForOpen(1,TimeUnit.SECONDS); + + // Assert open connections + assertServerOpenConnectionCount(1); + + // Establish new connection + ClientSocket cli2 = new ClientSocket(); + clientContainer.connectToServer(cli2,serverURI.resolve("/test")); + cli2.waitForOpen(1,TimeUnit.SECONDS); + + // Assert open connections + assertServerOpenConnectionCount(2); + + // Establish close both connections + cli1.session.close(); + cli2.session.close(); + + cli1.waitForClose(1,TimeUnit.SECONDS); + cli2.waitForClose(1,TimeUnit.SECONDS); + + // Assert open connections + assertServerOpenConnectionCount(0); + } + finally + { + clientContainer.stop(); + } + } + + private void assertServerOpenConnectionCount(int expectedCount) + { + Collection<WebSocketSession> sessions = wsServerFactory.getBeans(WebSocketSession.class); + int openCount = 0; + for (WebSocketSession session : sessions) + { + assertThat("Session.isopen: " + session,session.isOpen(),is(true)); + openCount++; + } + assertThat("Open Session Count",openCount,is(expectedCount)); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/resources/jetty-logging.properties b/jetty-websocket/javax-websocket-server-impl/src/test/resources/jetty-logging.properties index c5a50f6239..9681d9168b 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/resources/jetty-logging.properties +++ b/jetty-websocket/javax-websocket-server-impl/src/test/resources/jetty-logging.properties @@ -6,6 +6,9 @@ org.eclipse.jetty.LEVEL=WARN # org.eclipse.jetty.websocket.LEVEL=WARN # org.eclipse.jetty.websocket.common.io.LEVEL=DEBUG +org.eclipse.jetty.websocket.common.WebSocketSession.LEVEL=DEBUG +org.eclipse.jetty.websocket.jsr356.LEVEL=DEBUG + ### Show state changes on BrowserDebugTool # -- LEAVE THIS AT DEBUG LEVEL -- org.eclipse.jetty.websocket.jsr356.server.browser.LEVEL=DEBUG diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java index bdd37a2009..b552d300ed 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java @@ -53,7 +53,6 @@ import org.eclipse.jetty.websocket.client.io.UpgradeListener; import org.eclipse.jetty.websocket.client.masks.Masker; import org.eclipse.jetty.websocket.client.masks.RandomMasker; import org.eclipse.jetty.websocket.common.SessionFactory; -import org.eclipse.jetty.websocket.common.SessionListener; import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.WebSocketSessionFactory; import org.eclipse.jetty.websocket.common.events.EventDriver; @@ -64,7 +63,7 @@ import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; /** * WebSocketClient provides a means of establishing connections to remote websocket endpoints. */ -public class WebSocketClient extends ContainerLifeCycle implements SessionListener, WebSocketContainerScope +public class WebSocketClient extends ContainerLifeCycle implements WebSocketContainerScope { private static final Logger LOG = Log.getLogger(WebSocketClient.class); diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java index 4eda6fd797..944d6efd55 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java @@ -22,7 +22,6 @@ import java.net.InetSocketAddress; import java.util.concurrent.Executor; import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.SuspendToken; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; @@ -36,7 +35,7 @@ public interface LogicalConnection extends OutgoingFrames, SuspendToken * <p> * Basic usage: results in an non-blocking async write, then connection close. * - * @see StatusCode + * @see org.eclipse.jetty.websocket.api.StatusCode * @see #close(int, String) */ public void close(); @@ -50,7 +49,7 @@ public interface LogicalConnection extends OutgoingFrames, SuspendToken * the status code * @param reason * the (optional) reason. (can be null for no reason) - * @see StatusCode + * @see org.eclipse.jetty.websocket.api.StatusCode */ public void close(int statusCode, String reason); @@ -155,4 +154,10 @@ public interface LogicalConnection extends OutgoingFrames, SuspendToken * @return the suspend token */ SuspendToken suspend(); + + /** + * Get Unique ID for the Connection + * @return the unique ID for the connection + */ + public String getId(); } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/SessionListener.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/SessionListener.java deleted file mode 100644 index c62facef7c..0000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/SessionListener.java +++ /dev/null @@ -1,31 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2016 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.common; - -/** - * Basic listener interface for Session open/close. - * <p> - * Used primarily for tracking open sessions. - */ -public interface SessionListener -{ - public void onSessionOpened(WebSocketSession session); - - public void onSessionClosed(WebSocketSession session); -} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java index 33356b2f61..e32a52cb91 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java @@ -67,7 +67,6 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Web private final URI requestURI; private final LogicalConnection connection; private final EventDriver websocket; - private final SessionListener[] sessionListeners; private final Executor executor; private ClassLoader classLoader; private ExtensionFactory extensionFactory; @@ -80,7 +79,7 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Web private UpgradeRequest upgradeRequest; private UpgradeResponse upgradeResponse; - public WebSocketSession(WebSocketContainerScope containerScope, URI requestURI, EventDriver websocket, LogicalConnection connection, SessionListener... sessionListeners) + public WebSocketSession(WebSocketContainerScope containerScope, URI requestURI, EventDriver websocket, LogicalConnection connection) { Objects.requireNonNull(containerScope,"Container Scope cannot be null"); Objects.requireNonNull(requestURI,"Request URI cannot be null"); @@ -90,11 +89,11 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Web this.requestURI = requestURI; this.websocket = websocket; this.connection = connection; - this.sessionListeners = sessionListeners; this.executor = connection.getExecutor(); this.outgoingHandler = connection; this.incomingHandler = websocket; this.connection.getIOState().addListener(this); + this.policy = containerScope.getPolicy(); addBean(this.connection); addBean(this.websocket); @@ -435,36 +434,28 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Web CloseInfo close = ioState.getCloseInfo(); // confirmed close of local endpoint notifyClose(close.getStatusCode(),close.getReason()); - - // notify session listeners - for (SessionListener listener : sessionListeners) + try + { + if (LOG.isDebugEnabled()) + LOG.debug("{}.onSessionClosed()",containerScope.getClass().getSimpleName()); + containerScope.onSessionClosed(this); + } + catch (Throwable t) { - try - { - if (LOG.isDebugEnabled()) - LOG.debug("{}.onSessionClosed()",listener.getClass().getSimpleName()); - listener.onSessionClosed(this); - } - catch (Throwable t) - { - LOG.ignore(t); - } + LOG.ignore(t); } break; case CONNECTED: // notify session listeners - for (SessionListener listener : sessionListeners) + try + { + if (LOG.isDebugEnabled()) + LOG.debug("{}.onSessionOpened()",containerScope.getClass().getSimpleName()); + containerScope.onSessionOpened(this); + } + catch (Throwable t) { - try - { - if (LOG.isDebugEnabled()) - LOG.debug("{}.onSessionOpen()", listener.getClass().getSimpleName()); - listener.onSessionOpened(this); - } - catch (Throwable t) - { - LOG.ignore(t); - } + LOG.ignore(t); } break; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSessionFactory.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSessionFactory.java index 8494a26507..e46a231325 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSessionFactory.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSessionFactory.java @@ -31,26 +31,10 @@ import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; public class WebSocketSessionFactory implements SessionFactory { private final WebSocketContainerScope containerScope; - private final SessionListener[] listeners; - public WebSocketSessionFactory(WebSocketContainerScope containerScope, SessionListener... sessionListeners) + public WebSocketSessionFactory(WebSocketContainerScope containerScope) { this.containerScope = containerScope; - if ((sessionListeners != null) && (sessionListeners.length > 0)) - { - this.listeners = sessionListeners; - } - else - { - if (this.containerScope instanceof SessionListener) - { - this.listeners = new SessionListener[] { (SessionListener)containerScope }; - } - else - { - this.listeners = new SessionListener[0]; - } - } } @Override @@ -62,6 +46,6 @@ public class WebSocketSessionFactory implements SessionFactory @Override public WebSocketSession createSession(URI requestURI, EventDriver websocket, LogicalConnection connection) { - return new WebSocketSession(containerScope, requestURI,websocket,connection,listeners); + return new WebSocketSession(containerScope, requestURI,websocket,connection); } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java index a3a0ed3e97..027e8e65d9 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java @@ -214,6 +214,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp private final WebSocketPolicy policy; private final AtomicBoolean suspendToken; private final FrameFlusher flusher; + private final String id; private List<ExtensionConfig> extensions; private boolean isFilling; private ByteBuffer prefillBuffer; @@ -224,6 +225,11 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp public AbstractWebSocketConnection(EndPoint endp, Executor executor, Scheduler scheduler, WebSocketPolicy policy, ByteBufferPool bufferPool) { super(endp,executor); + this.id = String.format("%s:%d->%s:%d", + endp.getLocalAddress().getAddress().getHostAddress(), + endp.getLocalAddress().getPort(), + endp.getRemoteAddress().getAddress().getHostAddress(), + endp.getRemoteAddress().getPort()); this.policy = policy; this.bufferPool = bufferPool; this.generator = new Generator(policy,bufferPool); @@ -347,6 +353,12 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp { return generator; } + + @Override + public String getId() + { + return id; + } @Override public long getIdleTimeout() @@ -747,6 +759,43 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp return String.format("%s@%X{endp=%s,ios=%s,f=%s,g=%s,p=%s}",getClass().getSimpleName(),hashCode(),getEndPoint(),ioState,flusher,generator,parser); } + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + + EndPoint endp = getEndPoint(); + if(endp != null) + { + result = prime * result + endp.getLocalAddress().hashCode(); + result = prime * result + endp.getRemoteAddress().hashCode(); + } + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AbstractWebSocketConnection other = (AbstractWebSocketConnection)obj; + EndPoint endp = getEndPoint(); + EndPoint otherEndp = other.getEndPoint(); + if (endp == null) + { + if (otherEndp != null) + return false; + } + else if (!endp.equals(otherEndp)) + return false; + return true; + } + /** * Extra bytes from the initial HTTP upgrade that need to * be processed by the websocket parser before starting diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/scopes/SimpleContainerScope.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/scopes/SimpleContainerScope.java index a68574c47f..0e8e0dd74d 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/scopes/SimpleContainerScope.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/scopes/SimpleContainerScope.java @@ -27,6 +27,7 @@ import org.eclipse.jetty.util.component.ContainerLifeCycle; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.common.WebSocketSession; public class SimpleContainerScope extends ContainerLifeCycle implements WebSocketContainerScope { @@ -105,4 +106,14 @@ public class SimpleContainerScope extends ContainerLifeCycle implements WebSocke { this.sslContextFactory = sslContextFactory; } + + @Override + public void onSessionOpened(WebSocketSession session) + { + } + + @Override + public void onSessionClosed(WebSocketSession session) + { + } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/scopes/WebSocketContainerScope.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/scopes/WebSocketContainerScope.java index 0717cfc871..aacaf85ab2 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/scopes/WebSocketContainerScope.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/scopes/WebSocketContainerScope.java @@ -24,6 +24,7 @@ import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.util.DecoratedObjectFactory; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.common.WebSocketSession; /** * Defined Scope for a WebSocketContainer. @@ -64,4 +65,19 @@ public interface WebSocketContainerScope * @return the SslContextFactory in use by the container (can be null if no SSL context is defined) */ public SslContextFactory getSslContextFactory(); + + /** + * A Session has been opened + * + * @param session the session that was opened + */ + public void onSessionOpened(WebSocketSession session); + + /** + * A Session has been closed + * + * @param session the session that was closed + */ + public void onSessionClosed(WebSocketSession session); + } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java index 71b8e3d7ff..9c067f5913 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java @@ -108,6 +108,12 @@ public class LocalWebSocketConnection implements LogicalConnection, IncomingFram } @Override + public String getId() + { + return this.id; + } + + @Override public long getIdleTimeout() { return 0; diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/DummyConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/DummyConnection.java index a5a1ba6c21..b0ea466241 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/DummyConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/DummyConnection.java @@ -71,6 +71,12 @@ public class DummyConnection implements LogicalConnection } @Override + public String getId() + { + return "dummy"; + } + + @Override public long getIdleTimeout() { return 0; diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java index c8f9ef4bc0..baebd44b8d 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java @@ -39,7 +39,7 @@ public class WebSocketServerConnection extends AbstractWebSocketConnection imple endp.setIdleTimeout(policy.getIdleTimeout()); } } - + @Override public InetSocketAddress getLocalAddress() { diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java index ec2dd3ab34..e30b4cac5d 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java @@ -58,7 +58,6 @@ import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; import org.eclipse.jetty.websocket.api.util.QuoteUtil; import org.eclipse.jetty.websocket.common.LogicalConnection; import org.eclipse.jetty.websocket.common.SessionFactory; -import org.eclipse.jetty.websocket.common.SessionListener; import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.WebSocketSessionFactory; import org.eclipse.jetty.websocket.common.events.EventDriver; @@ -75,7 +74,7 @@ import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; /** * Factory to create WebSocket connections */ -public class WebSocketServerFactory extends ContainerLifeCycle implements WebSocketCreator, WebSocketContainerScope, WebSocketServletFactory, SessionListener +public class WebSocketServerFactory extends ContainerLifeCycle implements WebSocketCreator, WebSocketContainerScope, WebSocketServletFactory { private static final Logger LOG = Log.getLogger(WebSocketServerFactory.class); diff --git a/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/AttributeNormalizerTest.java b/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/AttributeNormalizerTest.java new file mode 100644 index 0000000000..8121d63e8e --- /dev/null +++ b/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/AttributeNormalizerTest.java @@ -0,0 +1,204 @@ + // +// ======================================================================== +// Copyright (c) 1995-2016 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.quickstart; + +import static org.junit.Assert.assertEquals; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jetty.util.resource.Resource; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class AttributeNormalizerTest +{ + @Parameters(name="{0} = {1}") + public static List<String[]> data() + { + String[][] tests = { + { "WAR", "/opt/jetty-distro/demo.base/webapps/root" }, + { "jetty.home", "/opt/jetty-distro" }, + { "jetty.base", "/opt/jetty-distro/demo.base" }, + { "user.home", "/home/user" }, + { "user.dir", "/etc/init.d" }, + }; + + return Arrays.asList(tests); + } + + private static String origJettyBase; + private static String origJettyHome; + private static String origUserHome; + private static String origUserDir; + + @BeforeClass + public static void initProperties() + { + origJettyBase = System.getProperty("jetty.base"); + origJettyHome = System.getProperty("jetty.home"); + origUserHome = System.getProperty("user.home"); + origUserDir = System.getProperty("user.dir"); + + System.setProperty("jetty.home","/opt/jetty-distro"); + System.setProperty("jetty.base","/opt/jetty-distro/demo.base"); + System.setProperty("user.home","/home/user"); + System.setProperty("user.dir","/etc/init.d"); + } + + @AfterClass + public static void restoreProperties() + { + if(origJettyBase != null) System.setProperty("jetty.base",origJettyBase); + if(origJettyHome != null) System.setProperty("jetty.home",origJettyHome); + if(origUserHome != null) System.setProperty("user.home",origUserHome); + if(origUserDir != null) System.setProperty("user.dir",origUserDir); + } + + @Parameter(0) + public String key; + + @Parameter(1) + public String path; + + private AttributeNormalizer normalizer; + + public AttributeNormalizerTest() throws MalformedURLException + { + normalizer = new AttributeNormalizer(Resource.newResource("/opt/jetty-distro/demo.base/webapps/root")); + } + + @Test + public void testEqual() + { + assertEquals("file:${" + key + "}",normalizer.normalize("file:" + path)); + } + + @Test + public void testEqualsSlash() + { + assertEquals("file:${" + key + "}",normalizer.normalize("file:" + path + "/")); + } + + @Test + public void testEqualsSlashFile() + { + assertEquals("file:${" + key + "}/file",normalizer.normalize("file:" + path + "/file")); + } + + @Test + public void testURIEquals() throws URISyntaxException + { + assertEquals("file:${" + key + "}",normalizer.normalize(new URI("file:" + path))); + } + + @Test + public void testURIEqualsSlash() throws URISyntaxException + { + assertEquals("file:${" + key + "}",normalizer.normalize(new URI("file:" + path + "/"))); + } + + @Test + public void testURIEqualsSlashFile() throws URISyntaxException + { + assertEquals("file:${" + key + "}/file",normalizer.normalize(new URI("file:" + path + "/file"))); + } + + @Test + public void testURLEquals() throws MalformedURLException + { + assertEquals("file:${" + key + "}",normalizer.normalize(new URL("file:" + path))); + } + + @Test + public void testURLEqualsSlash() throws MalformedURLException + { + assertEquals("file:${" + key + "}",normalizer.normalize(new URL("file:" + path + "/"))); + } + + @Test + public void testURLEqualsSlashFile() throws MalformedURLException + { + assertEquals("file:${" + key + "}/file",normalizer.normalize(new URL("file:" + path + "/file"))); + } + + @Test + public void testJarFileEquals_BangFile() + { + assertEquals("jar:file:${" + key + "}!/file",normalizer.normalize("jar:file:" + path + "!/file")); + } + + @Test + public void testJarFileEquals_SlashBangFile() + { + assertEquals("jar:file:${" + key + "}!/file",normalizer.normalize("jar:file:" + path + "/!/file")); + } + + @Test + public void testJarFileEquals_FileBangFile() + { + assertEquals("jar:file:${" + key + "}/file!/file",normalizer.normalize("jar:file:" + path + "/file!/file")); + } + + @Test + public void testJarFileEquals_URIBangFile() throws URISyntaxException + { + assertEquals("jar:file:${" + key + "}!/file",normalizer.normalize(new URI("jar:file:" + path + "!/file"))); + } + + @Test + public void testJarFileEquals_URISlashBangFile() throws URISyntaxException + { + assertEquals("jar:file:${" + key + "}!/file",normalizer.normalize(new URI("jar:file:" + path + "/!/file"))); + } + + @Test + public void testJarFileEquals_URIFileBangFile() throws URISyntaxException + { + assertEquals("jar:file:${" + key + "}/file!/file",normalizer.normalize(new URI("jar:file:" + path + "/file!/file"))); + } + + @Test + public void testJarFileEquals_URLBangFile() throws MalformedURLException + { + assertEquals("jar:file:${" + key + "}!/file",normalizer.normalize(new URL("jar:file:" + path + "!/file"))); + } + + @Test + public void testJarFileEquals_URLSlashBangFile() throws MalformedURLException + { + assertEquals("jar:file:${" + key + "}!/file",normalizer.normalize(new URL("jar:file:" + path + "/!/file"))); + } + + @Test + public void testJarFileEquals_URLFileBangFile() throws MalformedURLException + { + assertEquals("jar:file:${" + key + "}/file!/file",normalizer.normalize(new URL("jar:file:" + path + "/file!/file"))); + } +} diff --git a/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartTest.java b/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartTest.java index 61b853ba35..5ce9c56894 100644 --- a/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartTest.java +++ b/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartTest.java @@ -160,7 +160,7 @@ public class QuickStartTest if (contextXml != null) { // System.err.println("Applying "+contextXml); - XmlConfiguration xmlConfiguration = new XmlConfiguration(contextXml.getURL()); + XmlConfiguration xmlConfiguration = new XmlConfiguration(contextXml.getURI().toURL()); xmlConfiguration.configure(webapp); } |