Merge remote-tracking branch 'origin/jetty-9.3.x'

This commit is contained in:
Greg Wilkins 2016-01-14 11:00:06 +11:00
commit c5cbc64e77
32 changed files with 844 additions and 172 deletions

View File

@ -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

View File

@ -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."

View File

@ -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;
}
}
}

View File

@ -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();
}
/**

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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();

View File

@ -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();

View File

@ -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

View File

@ -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());
}
}
}

View File

@ -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;
@ -56,6 +57,20 @@ public class SslContextFactoryTest
cf = new SslContextFactory();
}
@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
{

View File

@ -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<>();

View File

@ -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);

View File

@ -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

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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

View File

@ -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);

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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
{
try
{
if (LOG.isDebugEnabled())
LOG.debug("{}.onSessionClosed()",listener.getClass().getSimpleName());
listener.onSessionClosed(this);
}
catch (Throwable t)
{
LOG.ignore(t);
}
if (LOG.isDebugEnabled())
LOG.debug("{}.onSessionClosed()",containerScope.getClass().getSimpleName());
containerScope.onSessionClosed(this);
}
catch (Throwable t)
{
LOG.ignore(t);
}
break;
case CONNECTED:
// notify session listeners
for (SessionListener listener : sessionListeners)
try
{
try
{
if (LOG.isDebugEnabled())
LOG.debug("{}.onSessionOpen()", listener.getClass().getSimpleName());
listener.onSessionOpened(this);
}
catch (Throwable t)
{
LOG.ignore(t);
}
if (LOG.isDebugEnabled())
LOG.debug("{}.onSessionOpened()",containerScope.getClass().getSimpleName());
containerScope.onSessionOpened(this);
}
catch (Throwable t)
{
LOG.ignore(t);
}
break;
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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)
{
}
}

View File

@ -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);
}

View File

@ -107,6 +107,12 @@ public class LocalWebSocketConnection implements LogicalConnection, IncomingFram
return this.bufferPool;
}
@Override
public String getId()
{
return this.id;
}
@Override
public long getIdleTimeout()
{

View File

@ -70,6 +70,12 @@ public class DummyConnection implements LogicalConnection
return null;
}
@Override
public String getId()
{
return "dummy";
}
@Override
public long getIdleTimeout()
{

View File

@ -39,7 +39,7 @@ public class WebSocketServerConnection extends AbstractWebSocketConnection imple
endp.setIdleTimeout(policy.getIdleTimeout());
}
}
@Override
public InetSocketAddress getLocalAddress()
{

View File

@ -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);

View File

@ -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")));
}
}

View File

@ -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);
}