Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Bartel2016-02-01 10:57:35 -0500
committerJan Bartel2016-02-01 10:57:35 -0500
commit599696bfc50a5865cdf7da6ae6c14066c037606d (patch)
treeb943ac8c51354b5bf9a903cdf1bdb61ce60236ef
parent4f9abc279b9c35abcba59ec87a7563caa2d96b6f (diff)
parent56c0bc768ca577ea6a110ffd423d3152ebe50201 (diff)
downloadorg.eclipse.jetty.project-599696bfc50a5865cdf7da6ae6c14066c037606d.tar.gz
org.eclipse.jetty.project-599696bfc50a5865cdf7da6ae6c14066c037606d.tar.xz
org.eclipse.jetty.project-599696bfc50a5865cdf7da6ae6c14066c037606d.zip
Merge branch 'master' into session-refactor
-rw-r--r--VERSION.txt72
-rw-r--r--jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-1.8.0_71.mod8
-rw-r--r--jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-1.8.0_72.mod8
-rw-r--r--jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java49
-rw-r--r--jetty-distribution/pom.xml2
-rwxr-xr-xjetty-distribution/src/main/resources/bin/jetty.sh1
-rw-r--r--jetty-gcloud/jetty-gcloud-session-manager/pom.xml (renamed from jetty-gcloud/gcloud-session-manager/pom.xml)2
-rw-r--r--jetty-gcloud/jetty-gcloud-session-manager/src/main/config/etc/jetty-gcloud-sessions.xml (renamed from jetty-gcloud/gcloud-session-manager/src/main/config/etc/jetty-gcloud-sessions.xml)0
-rw-r--r--jetty-gcloud/jetty-gcloud-session-manager/src/main/config/modules/gcloud-sessions.mod (renamed from jetty-gcloud/gcloud-session-manager/src/main/config/modules/gcloud-sessions.mod)2
-rw-r--r--jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudConfiguration.java (renamed from jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudConfiguration.java)0
-rw-r--r--jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionIdManager.java (renamed from jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionIdManager.java)0
-rw-r--r--jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionManager.java (renamed from jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionManager.java)0
-rw-r--r--jetty-gcloud/jetty-gcloud-session-manager/src/test/java/org/eclipse/jetty/gcloud/session/GCloudSessionTester.java (renamed from jetty-gcloud/gcloud-session-manager/src/test/java/org/eclipse/jetty/gcloud/session/GCloudSessionTester.java)0
-rw-r--r--jetty-gcloud/pom.xml2
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathMappings.java189
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpec.java20
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpecGroup.java22
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpecSet.java162
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/ServletPathSpec.java8
-rw-r--r--jetty-http/src/test/java/org/eclipse/jetty/http/pathmap/PathMappingsTest.java10
-rw-r--r--jetty-osgi/test-jetty-osgi/pom.xml6
-rw-r--r--jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/AttributeNormalizer.java157
-rw-r--r--jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java42
-rw-r--r--jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorProcessor.java9
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java3
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java24
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java14
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java6
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java2
-rw-r--r--jetty-start/src/test/resources/dist-home/modules/alpn-impl/alpn-1.8.0_71.mod8
-rw-r--r--jetty-start/src/test/resources/dist-home/modules/alpn-impl/alpn-1.8.0_72.mod8
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java8
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/resource/FileSystemResourceTest.java80
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java15
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java7
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSession.java5
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSessionFactory.java20
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java15
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/SessionTrackingTest.java183
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/browser/JsrBrowserDebugTool.java8
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/resources/jetty-logging.properties3
-rw-r--r--jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java3
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/LogicalConnection.java11
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/SessionListener.java31
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java45
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSessionFactory.java20
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java10
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtension.java2
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java49
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/scopes/SimpleContainerScope.java11
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/scopes/WebSocketContainerScope.java16
-rw-r--r--jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java6
-rw-r--r--jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/DummyConnection.java6
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java2
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java25
-rw-r--r--pom.xml24
-rw-r--r--tests/test-quickstart/pom.xml1
-rw-r--r--tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/AttributeNormalizerTest.java204
-rw-r--r--tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartTest.java2
-rw-r--r--tests/test-sessions/test-gcloud-sessions/pom.xml2
61 files changed, 1245 insertions, 407 deletions
diff --git a/VERSION.txt b/VERSION.txt
index 57dd1679c5..cad370f8dd 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1,5 +1,77 @@
jetty-9.4.0-SNAPSHOT
+jetty-9.3.7.v20160115 - 15 January 2016
+ + 471171 Support SYNC_FLUSH in GzipHandler
+ + 485469 permessage-deflate extension causes protocol error in Firefox/Chrome
+ + 485714 Update SSL configuration to mitigate SLOTH vulnerability
+ + 485884 WebAppContext defaults should be same for xml or war deployment
+ + 485969 WebSocket upgrade response should honor HttpConfiguration server
+ version settings
+
+jetty-9.3.7.RC1 - 13 January 2016
+ + 481986 Dead JSR 356 Server Session still being tracked after
+ Session/Connection closure
+ + 484616 Outdated version of javaee_web_services_client_1_2.xsd
+ + 485031 two PathWatcher threads running after automatically restarting webapp
+ + 485063 After stopping JettyWebAppContext, it still contains reference to old
+ WebAppClassLoader via ServerContainer bean
+ + 485064 HashSessionManager leaks ScheduledExecutorScheduler with reference to
+ un-deployed webapp
+ + 485376 Multiple charset attributes in Content-Type
+ + 485535 jetty.sh results in FAILED when running service restart
+ + 485663 NullPointerException in WebSocketSession during upgrade with DEBUG
+ logging
+ + 485712 Quickstart web.xml is absolute
+
+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-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-1.8.0_71.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-1.8.0_71.mod
new file mode 100644
index 0000000000..3628757cbf
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-1.8.0_71.mod
@@ -0,0 +1,8 @@
+[name]
+protonego-boot
+
+[files]
+http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.7.v20160121/alpn-boot-8.1.7.v20160121.jar|lib/alpn/alpn-boot-8.1.7.v20160121.jar
+
+[exec]
+-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.7.v20160121.jar
diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-1.8.0_72.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-1.8.0_72.mod
new file mode 100644
index 0000000000..3628757cbf
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-1.8.0_72.mod
@@ -0,0 +1,8 @@
+[name]
+protonego-boot
+
+[files]
+http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.7.v20160121/alpn-boot-8.1.7.v20160121.jar|lib/alpn/alpn-boot-8.1.7.v20160121.jar
+
+[exec]
+-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.7.v20160121.jar
diff --git a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java
index 7b7303d317..fdebfd668c 100644
--- a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java
+++ b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java
@@ -245,6 +245,28 @@ public class WebAppProvider extends ScanningAppProvider
}
/* ------------------------------------------------------------ */
+ protected void initializeWebAppContextDefaults(WebAppContext webapp)
+ {
+ if (_defaultsDescriptor != null)
+ webapp.setDefaultsDescriptor(_defaultsDescriptor);
+ webapp.setExtractWAR(_extractWars);
+ webapp.setParentLoaderPriority(_parentLoaderPriority);
+ if (_configurationClasses != null)
+ webapp.setConfigurationClasses(_configurationClasses);
+
+ if (_tempDirectory != null)
+ {
+ /* Since the Temp Dir is really a context base temp directory,
+ * Lets set the Temp Directory in a way similar to how WebInfConfiguration does it,
+ * instead of setting the WebAppContext.setTempDirectory(File).
+ * If we used .setTempDirectory(File) all webapps will wind up in the
+ * same temp / work directory, overwriting each others work.
+ */
+ webapp.setAttribute(WebAppContext.BASETEMPDIR, _tempDirectory);
+ }
+ }
+
+ /* ------------------------------------------------------------ */
@Override
public ContextHandler createContextHandler(final App app) throws Exception
{
@@ -267,9 +289,7 @@ public class WebAppProvider extends ScanningAppProvider
if (context instanceof WebAppContext)
{
WebAppContext webapp = (WebAppContext)context;
- webapp.setParentLoaderPriority(_parentLoaderPriority);
- if (_defaultsDescriptor != null)
- webapp.setDefaultsDescriptor(_defaultsDescriptor);
+ initializeWebAppContextDefaults(webapp);
}
}
};
@@ -327,31 +347,10 @@ public class WebAppProvider extends ScanningAppProvider
context = "/" + context;
}
-
webAppContext.setContextPath(context);
webAppContext.setWar(file.getAbsolutePath());
- if (_defaultsDescriptor != null)
- {
- webAppContext.setDefaultsDescriptor(_defaultsDescriptor);
- }
- webAppContext.setExtractWAR(_extractWars);
- webAppContext.setParentLoaderPriority(_parentLoaderPriority);
- if (_configurationClasses != null)
- {
- webAppContext.setConfigurationClasses(_configurationClasses);
- }
+ initializeWebAppContextDefaults(webAppContext);
- if (_tempDirectory != null)
- {
- /* Since the Temp Dir is really a context base temp directory,
- * Lets set the Temp Directory in a way similar to how WebInfConfiguration does it,
- * instead of setting the
- * WebAppContext.setTempDirectory(File).
- * If we used .setTempDirectory(File) all webapps will wind up in the
- * same temp / work directory, overwriting each others work.
- */
- webAppContext.setAttribute(WebAppContext.BASETEMPDIR, _tempDirectory);
- }
return webAppContext;
}
diff --git a/jetty-distribution/pom.xml b/jetty-distribution/pom.xml
index 9878feb1ce..f68e7294c9 100644
--- a/jetty-distribution/pom.xml
+++ b/jetty-distribution/pom.xml
@@ -785,7 +785,7 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty.gcloud</groupId>
- <artifactId>gcloud-session-manager</artifactId>
+ <artifactId>jetty-gcloud-session-manager</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
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-gcloud/gcloud-session-manager/pom.xml b/jetty-gcloud/jetty-gcloud-session-manager/pom.xml
index 5110e61e4d..3953a5a9c3 100644
--- a/jetty-gcloud/gcloud-session-manager/pom.xml
+++ b/jetty-gcloud/jetty-gcloud-session-manager/pom.xml
@@ -7,7 +7,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>gcloud-session-manager</artifactId>
+ <artifactId>jetty-gcloud-session-manager</artifactId>
<name>Jetty :: GCloud :: Session Manager</name>
<dependencies>
diff --git a/jetty-gcloud/gcloud-session-manager/src/main/config/etc/jetty-gcloud-sessions.xml b/jetty-gcloud/jetty-gcloud-session-manager/src/main/config/etc/jetty-gcloud-sessions.xml
index b1b9a844db..b1b9a844db 100644
--- a/jetty-gcloud/gcloud-session-manager/src/main/config/etc/jetty-gcloud-sessions.xml
+++ b/jetty-gcloud/jetty-gcloud-session-manager/src/main/config/etc/jetty-gcloud-sessions.xml
diff --git a/jetty-gcloud/gcloud-session-manager/src/main/config/modules/gcloud-sessions.mod b/jetty-gcloud/jetty-gcloud-session-manager/src/main/config/modules/gcloud-sessions.mod
index 3a6aaef03a..6bd5e67538 100644
--- a/jetty-gcloud/gcloud-session-manager/src/main/config/modules/gcloud-sessions.mod
+++ b/jetty-gcloud/jetty-gcloud-session-manager/src/main/config/modules/gcloud-sessions.mod
@@ -40,7 +40,7 @@ maven://com.google.api-client/google-api-client/1.15.0-rc|lib/gcloud/google-api-
maven://com.google.apis/google-api-services-datastore/v1beta2-rev23-1.19.0|lib/gcloud/google-api-services-datastore-v1beta2-rev23-1.19.0.jar
[lib]
-lib/gcloud-session-manager-${jetty.version}.jar
+lib/jetty-gcloud-session-manager-${jetty.version}.jar
lib/gcloud/*.jar
[xml]
diff --git a/jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudConfiguration.java b/jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudConfiguration.java
index 9dc103581b..9dc103581b 100644
--- a/jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudConfiguration.java
+++ b/jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudConfiguration.java
diff --git a/jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionIdManager.java b/jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionIdManager.java
index 2f8da7af1d..2f8da7af1d 100644
--- a/jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionIdManager.java
+++ b/jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionIdManager.java
diff --git a/jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionManager.java b/jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionManager.java
index dd50b9412e..dd50b9412e 100644
--- a/jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionManager.java
+++ b/jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionManager.java
diff --git a/jetty-gcloud/gcloud-session-manager/src/test/java/org/eclipse/jetty/gcloud/session/GCloudSessionTester.java b/jetty-gcloud/jetty-gcloud-session-manager/src/test/java/org/eclipse/jetty/gcloud/session/GCloudSessionTester.java
index ac58dd4b4c..ac58dd4b4c 100644
--- a/jetty-gcloud/gcloud-session-manager/src/test/java/org/eclipse/jetty/gcloud/session/GCloudSessionTester.java
+++ b/jetty-gcloud/jetty-gcloud-session-manager/src/test/java/org/eclipse/jetty/gcloud/session/GCloudSessionTester.java
diff --git a/jetty-gcloud/pom.xml b/jetty-gcloud/pom.xml
index 75d9bad29d..3d571b8a56 100644
--- a/jetty-gcloud/pom.xml
+++ b/jetty-gcloud/pom.xml
@@ -17,7 +17,7 @@
</properties>
<modules>
- <module>gcloud-session-manager</module>
+ <module>jetty-gcloud-session-manager</module>
</modules>
</project>
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathMappings.java b/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathMappings.java
index d1c36cfbd6..c6500f3cf5 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathMappings.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathMappings.java
@@ -20,10 +20,13 @@ package org.eclipse.jetty.http.pathmap;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import org.eclipse.jetty.util.ArrayTernaryTrie;
+import org.eclipse.jetty.util.Trie;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
@@ -42,10 +45,12 @@ import org.eclipse.jetty.util.log.Logger;
public class PathMappings<E> implements Iterable<MappedResource<E>>, Dumpable
{
private static final Logger LOG = Log.getLogger(PathMappings.class);
- private List<MappedResource<E>> mappings = new ArrayList<MappedResource<E>>();
- private MappedResource<E> defaultResource = null;
- private MappedResource<E> rootResource = null;
-
+ private final Set<MappedResource<E>> _mappings = new TreeSet<>();
+
+ private Trie<MappedResource<E>> _exactMap=new ArrayTernaryTrie<>(false);
+ private Trie<MappedResource<E>> _prefixMap=new ArrayTernaryTrie<>(false);
+ private Trie<MappedResource<E>> _suffixMap=new ArrayTernaryTrie<>(false);
+
@Override
public String dump()
{
@@ -55,18 +60,25 @@ public class PathMappings<E> implements Iterable<MappedResource<E>>, Dumpable
@Override
public void dump(Appendable out, String indent) throws IOException
{
- ContainerLifeCycle.dump(out,indent,mappings);
+ ContainerLifeCycle.dump(out,indent,_mappings);
}
@ManagedAttribute(value = "mappings", readonly = true)
public List<MappedResource<E>> getMappings()
{
- return mappings;
+ return new ArrayList<>(_mappings);
}
+ public int size()
+ {
+ return _mappings.size();
+ }
+
public void reset()
{
- mappings.clear();
+ _mappings.clear();
+ _prefixMap.clear();
+ _suffixMap.clear();
}
/**
@@ -77,22 +89,19 @@ public class PathMappings<E> implements Iterable<MappedResource<E>>, Dumpable
*/
public List<MappedResource<E>> getMatches(String path)
{
- boolean matchRoot = "/".equals(path);
+ boolean isRootPath = "/".equals(path);
List<MappedResource<E>> ret = new ArrayList<>();
- int len = mappings.size();
- for (int i = 0; i < len; i++)
+ for (MappedResource<E> mr :_mappings)
{
- MappedResource<E> mr = mappings.get(i);
-
switch (mr.getPathSpec().group)
{
case ROOT:
- if (matchRoot)
+ if (isRootPath)
ret.add(mr);
break;
case DEFAULT:
- if (matchRoot || mr.getPathSpec().matches(path))
+ if (isRootPath || mr.getPathSpec().matches(path))
ret.add(mr);
break;
default:
@@ -106,54 +115,160 @@ public class PathMappings<E> implements Iterable<MappedResource<E>>, Dumpable
public MappedResource<E> getMatch(String path)
{
- if (path.equals("/") && rootResource != null)
- {
- return rootResource;
- }
+ PathSpecGroup last_group=null;
- int len = mappings.size();
- for (int i = 0; i < len; i++)
+ // Search all the mappings
+ for (MappedResource<E> mr : _mappings)
{
- MappedResource<E> mr = mappings.get(i);
- if (mr.getPathSpec().matches(path))
+ PathSpecGroup group=mr.getPathSpec().getGroup();
+ if (group!=last_group)
{
- return mr;
+ // New group in list, so let's look for an optimization
+ switch(group)
+ {
+ case EXACT:
+ {
+ int i= path.length();
+ final Trie<MappedResource<E>> exact_map=_exactMap;
+ while(i>=0)
+ {
+ MappedResource<E> candidate=exact_map.getBest(path,0,i);
+ if (candidate==null)
+ break;
+ if (candidate.getPathSpec().matches(path))
+ return candidate;
+ i=candidate.getPathSpec().getPrefix().length()-1;
+ }
+ break;
+ }
+
+ case PREFIX_GLOB:
+ {
+ int i= path.length();
+ final Trie<MappedResource<E>> prefix_map=_prefixMap;
+ while(i>=0)
+ {
+ MappedResource<E> candidate=prefix_map.getBest(path,0,i);
+ if (candidate==null)
+ break;
+ if (candidate.getPathSpec().matches(path))
+ return candidate;
+ i=candidate.getPathSpec().getPrefix().length()-1;
+ }
+ break;
+ }
+
+ case SUFFIX_GLOB:
+ {
+ int i=0;
+ final Trie<MappedResource<E>> suffix_map=_suffixMap;
+ while ((i=path.indexOf('.',i+1))>0)
+ {
+ MappedResource<E> candidate=suffix_map.get(path,i+1,path.length()-i-1);
+ if (candidate!=null && candidate.getPathSpec().matches(path))
+ return candidate;
+ }
+ break;
+ }
+
+ default:
+ }
}
+
+ if (mr.getPathSpec().matches(path))
+ return mr;
+
+ last_group=group;
}
- return defaultResource;
+
+ return null;
}
@Override
public Iterator<MappedResource<E>> iterator()
{
- return mappings.iterator();
+ return _mappings.iterator();
}
- @SuppressWarnings("incomplete-switch")
- public void put(PathSpec pathSpec, E resource)
+ public static PathSpec asPathSpec(String pathSpecString)
+ {
+ if ((pathSpecString == null) || (pathSpecString.length() < 1))
+ {
+ throw new RuntimeException("Path Spec String must start with '^', '/', or '*.': got [" + pathSpecString + "]");
+ }
+ return pathSpecString.charAt(0) == '^' ? new RegexPathSpec(pathSpecString):new ServletPathSpec(pathSpecString);
+ }
+
+ public boolean put(String pathSpecString, E resource)
+ {
+ return put(asPathSpec(pathSpecString),resource);
+ }
+
+ public boolean put(PathSpec pathSpec, E resource)
{
MappedResource<E> entry = new MappedResource<>(pathSpec,resource);
switch (pathSpec.group)
{
- case DEFAULT:
- defaultResource = entry;
+ case EXACT:
+ String exact = pathSpec.getPrefix();
+ while (exact!=null && !_exactMap.put(exact,entry))
+ _exactMap=new ArrayTernaryTrie<>((ArrayTernaryTrie<MappedResource<E>>)_exactMap,1.5);
+ break;
+ case PREFIX_GLOB:
+ String prefix = pathSpec.getPrefix();
+ while (prefix!=null && !_prefixMap.put(prefix,entry))
+ _prefixMap=new ArrayTernaryTrie<>((ArrayTernaryTrie<MappedResource<E>>)_prefixMap,1.5);
break;
- case ROOT:
- rootResource = entry;
+ case SUFFIX_GLOB:
+ String suffix = pathSpec.getSuffix();
+ while (suffix!=null && !_suffixMap.put(suffix,entry))
+ _suffixMap=new ArrayTernaryTrie<>((ArrayTernaryTrie<MappedResource<E>>)_prefixMap,1.5);
break;
+ default:
}
- // TODO: add warning when replacing an existing pathspec?
+ boolean added =_mappings.add(entry);
+ if (LOG.isDebugEnabled())
+ LOG.debug("{} {} to {}",added?"Added":"Ignored",entry,this);
+ return added;
+ }
+
+ @SuppressWarnings("incomplete-switch")
+ public boolean remove(PathSpec pathSpec)
+ {
+ switch (pathSpec.group)
+ {
+ case EXACT:
+ _exactMap.remove(pathSpec.getPrefix());
+ break;
+ case PREFIX_GLOB:
+ _prefixMap.remove(pathSpec.getPrefix());
+ break;
+ case SUFFIX_GLOB:
+ _suffixMap.remove(pathSpec.getSuffix());
+ break;
+ }
- mappings.add(entry);
+ Iterator<MappedResource<E>> iter = _mappings.iterator();
+ boolean removed=false;
+ while (iter.hasNext())
+ {
+ if (iter.next().getPathSpec().equals(pathSpec))
+ {
+ removed=true;
+ iter.remove();
+ break;
+ }
+ }
if (LOG.isDebugEnabled())
- LOG.debug("Added {} to {}",entry,this);
- Collections.sort(mappings);
+ LOG.debug("{} {} to {}",removed?"Removed":"Ignored",pathSpec,this);
+ return removed;
}
@Override
public String toString()
{
- return String.format("%s[size=%d]",this.getClass().getSimpleName(),mappings.size());
+ return String.format("%s[size=%d]",this.getClass().getSimpleName(),_mappings.size());
}
+
}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpec.java b/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpec.java
index a2b8ea56cf..8a1f82b7bb 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpec.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpec.java
@@ -27,6 +27,8 @@ public abstract class PathSpec implements Comparable<PathSpec>
protected PathSpecGroup group;
protected int pathDepth;
protected int specLength;
+ protected String prefix;
+ protected String suffix;
@Override
public int compareTo(PathSpec other)
@@ -125,6 +127,24 @@ public abstract class PathSpec implements Comparable<PathSpec>
}
/**
+ * A simple prefix match for the pathspec or null
+ * @return A simple prefix match for the pathspec or null
+ */
+ public String getPrefix()
+ {
+ return prefix;
+ }
+
+ /**
+ * A simple suffix match for the pathspec or null
+ * @return A simple suffix match for the pathspec or null
+ */
+ public String getSuffix()
+ {
+ return suffix;
+ }
+
+ /**
* Get the relative path.
*
* @param base
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpecGroup.java b/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpecGroup.java
index f9d96ced22..e03a035de1 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpecGroup.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpecGroup.java
@@ -35,6 +35,17 @@ public enum PathSpecGroup
// NOTE: Order of enums determines order of Groups.
/**
+ * The root spec for accessing the Root behavior.
+ *
+ * <pre>
+ * "" - servlet spec (Root Servlet)
+ * null - servlet spec (Root Servlet)
+ * </pre>
+ *
+ * Note: there is no known uri-template spec variant of this kind of path spec
+ */
+ ROOT,
+ /**
* For exactly defined path specs, no glob.
*/
EXACT,
@@ -75,17 +86,6 @@ public enum PathSpecGroup
*/
SUFFIX_GLOB,
/**
- * The root spec for accessing the Root behavior.
- *
- * <pre>
- * "" - servlet spec (Root Servlet)
- * null - servlet spec (Root Servlet)
- * </pre>
- *
- * Note: there is no known uri-template spec variant of this kind of path spec
- */
- ROOT,
- /**
* The default spec for accessing the Default path behavior.
*
* <pre>
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpecSet.java b/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpecSet.java
index d80b9a5b9c..b898cf50ff 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpecSet.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathSpecSet.java
@@ -18,12 +18,8 @@
package org.eclipse.jetty.http.pathmap;
-import java.util.ArrayList;
-import java.util.Collection;
+import java.util.AbstractSet;
import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
import java.util.function.Predicate;
/**
@@ -31,54 +27,16 @@ import java.util.function.Predicate;
* <p>
* Used by {@link org.eclipse.jetty.util.IncludeExclude} logic
*/
-public class PathSpecSet implements Set<String>, Predicate<String>
+public class PathSpecSet extends AbstractSet<String> implements Predicate<String>
{
- private final Set<PathSpec> specs = new TreeSet<>();
+ private final PathMappings<Boolean> specs = new PathMappings<>();
@Override
public boolean test(String s)
{
- for (PathSpec spec : specs)
- {
- if (spec.matches(s))
- {
- return true;
- }
- }
- return false;
+ return specs.getMatch(s)!=null;
}
- @Override
- public boolean isEmpty()
- {
- return specs.isEmpty();
- }
-
- @Override
- public Iterator<String> iterator()
- {
- return new Iterator<String>()
- {
- private Iterator<PathSpec> iter = specs.iterator();
-
- @Override
- public boolean hasNext()
- {
- return iter.hasNext();
- }
-
- @Override
- public String next()
- {
- PathSpec spec = iter.next();
- if (spec == null)
- {
- return null;
- }
- return spec.getDeclaration();
- }
- };
- }
@Override
public int size()
@@ -86,20 +44,6 @@ public class PathSpecSet implements Set<String>, Predicate<String>
return specs.size();
}
- @Override
- public boolean contains(Object o)
- {
- if (o instanceof PathSpec)
- {
- return specs.contains(o);
- }
- if (o instanceof String)
- {
- return specs.contains(toPathSpec((String)o));
- }
- return false;
- }
-
private PathSpec asPathSpec(Object o)
{
if (o == null)
@@ -112,48 +56,15 @@ public class PathSpecSet implements Set<String>, Predicate<String>
}
if (o instanceof String)
{
- return toPathSpec((String)o);
- }
- return toPathSpec(o.toString());
- }
-
- private PathSpec toPathSpec(String rawSpec)
- {
- if ((rawSpec == null) || (rawSpec.length() < 1))
- {
- throw new RuntimeException("Path Spec String must start with '^', '/', or '*.': got [" + rawSpec + "]");
- }
- if (rawSpec.charAt(0) == '^')
- {
- return new RegexPathSpec(rawSpec);
- }
- else
- {
- return new ServletPathSpec(rawSpec);
- }
- }
-
- @Override
- public Object[] toArray()
- {
- return toArray(new String[specs.size()]);
- }
-
- @Override
- public <T> T[] toArray(T[] a)
- {
- int i = 0;
- for (PathSpec spec : specs)
- {
- a[i++] = (T)spec.getDeclaration();
+ return PathMappings.asPathSpec((String)o);
}
- return a;
+ return PathMappings.asPathSpec(o.toString());
}
@Override
- public boolean add(String e)
+ public boolean add(String s)
{
- return specs.add(toPathSpec(e));
+ return specs.put(PathMappings.asPathSpec(s),Boolean.TRUE);
}
@Override
@@ -163,54 +74,29 @@ public class PathSpecSet implements Set<String>, Predicate<String>
}
@Override
- public boolean containsAll(Collection<?> coll)
+ public void clear()
{
- for (Object o : coll)
- {
- if (!specs.contains(asPathSpec(o)))
- return false;
- }
- return true;
+ specs.reset();
}
- @Override
- public boolean addAll(Collection<? extends String> coll)
- {
- boolean ret = false;
-
- for (String s : coll)
- {
- ret |= add(s);
- }
-
- return ret;
- }
@Override
- public boolean retainAll(Collection<?> coll)
- {
- List<PathSpec> collSpecs = new ArrayList<>();
- for (Object o : coll)
- {
- collSpecs.add(asPathSpec(o));
- }
- return specs.retainAll(collSpecs);
- }
-
- @Override
- public boolean removeAll(Collection<?> coll)
+ public Iterator<String> iterator()
{
- List<PathSpec> collSpecs = new ArrayList<>();
- for (Object o : coll)
+ final Iterator<MappedResource<Boolean>> iterator = specs.iterator();
+ return new Iterator<String>()
{
- collSpecs.add(asPathSpec(o));
- }
- return specs.removeAll(collSpecs);
- }
+ @Override
+ public boolean hasNext()
+ {
+ return iterator.hasNext();
+ }
- @Override
- public void clear()
- {
- specs.clear();
+ @Override
+ public String next()
+ {
+ return iterator.next().getPathSpec().getDeclaration();
+ }
+ };
}
}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/ServletPathSpec.java b/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/ServletPathSpec.java
index 4563305659..9f0732e5ef 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/ServletPathSpec.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/ServletPathSpec.java
@@ -54,15 +54,18 @@ public class ServletPathSpec extends PathSpec
if ((servletPathSpec.charAt(0) == '/') && (specLength > 1) && (lastChar == '*'))
{
this.group = PathSpecGroup.PREFIX_GLOB;
+ this.prefix = servletPathSpec.substring(0,specLength-2);
}
// suffix based
else if (servletPathSpec.charAt(0) == '*')
{
this.group = PathSpecGroup.SUFFIX_GLOB;
+ this.suffix = servletPathSpec.substring(2,specLength);
}
else
{
this.group = PathSpecGroup.EXACT;
+ this.prefix = servletPathSpec;
}
for (int i = 0; i < specLength; i++)
@@ -109,6 +112,11 @@ public class ServletPathSpec extends PathSpec
{
throw new IllegalArgumentException("Servlet Spec 12.2 violation: glob '*' can only exist at end of prefix based matches: bad spec \""+ servletPathSpec +"\"");
}
+
+ if (idx<1 || servletPathSpec.charAt(idx-1)!='/')
+ {
+ throw new IllegalArgumentException("Servlet Spec 12.2 violation: suffix glob '*' can only exist after '/': bad spec \""+ servletPathSpec +"\"");
+ }
}
else if (servletPathSpec.startsWith("*."))
{
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/pathmap/PathMappingsTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/pathmap/PathMappingsTest.java
index f3f2ef2240..7b1c864d8e 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/pathmap/PathMappingsTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/pathmap/PathMappingsTest.java
@@ -278,4 +278,14 @@ public class PathMappingsTest
assertEquals("suffix",p.getMatch("/foo/something.txt").getResource());
assertEquals("prefix",p.getMatch("/dump/gzip/something.txt").getResource());
}
+
+ @Test
+ public void testBadPathSpecs()
+ {
+ try{new ServletPathSpec("*");Assert.fail();}catch(IllegalArgumentException e){}
+ try{new ServletPathSpec("/foo/*/bar");Assert.fail();}catch(IllegalArgumentException e){}
+ try{new ServletPathSpec("/foo*");Assert.fail();}catch(IllegalArgumentException e){}
+ try{new ServletPathSpec("*/foo");Assert.fail();}catch(IllegalArgumentException e){}
+ try{new ServletPathSpec("*.foo/*");Assert.fail();}catch(IllegalArgumentException e){}
+ }
}
diff --git a/jetty-osgi/test-jetty-osgi/pom.xml b/jetty-osgi/test-jetty-osgi/pom.xml
index 132bc64bc7..4b574b01a8 100644
--- a/jetty-osgi/test-jetty-osgi/pom.xml
+++ b/jetty-osgi/test-jetty-osgi/pom.xml
@@ -317,12 +317,6 @@
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.mortbay.jetty.alpn</groupId>
- <artifactId>alpn-boot</artifactId>
- <version>${alpn.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-alpn</artifactId>
<version>${project.version}</version>
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/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java
index 6f9666e302..ec1d477453 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java
@@ -68,6 +68,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
private int _minGzipSize=DEFAULT_MIN_GZIP_SIZE;
private int _compressionLevel=Deflater.DEFAULT_COMPRESSION;
private boolean _checkGzExists = true;
+ private boolean _syncFlush = false;
// non-static, as other GzipHandler instances may have different configurations
private final ThreadLocal<Deflater> _deflater = new ThreadLocal<Deflater>();
@@ -195,6 +196,27 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
/* ------------------------------------------------------------ */
/**
+ * @return True if {@link Deflater#SYNC_FLUSH} is used, else {@link Deflater#NO_FLUSH}
+ */
+ public boolean isSyncFlush()
+ {
+ return _syncFlush;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * <p>Set the {@link Deflater} flush mode to use. {@link Deflater#SYNC_FLUSH}
+ * should be used if the application wishes to stream the data, but this may
+ * hurt compression performance.
+ * @param syncFlush True if {@link Deflater#SYNC_FLUSH} is used, else {@link Deflater#NO_FLUSH}
+ */
+ public void setSyncFlush(boolean syncFlush)
+ {
+ _syncFlush = syncFlush;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
* Add included mime types. Inclusion takes precedence over
* exclusion.
* @param types The mime types to include (without charset or other parameters)
@@ -465,7 +487,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
}
// install interceptor and handle
- out.setInterceptor(new GzipHttpOutputInterceptor(this,_vary,baseRequest.getHttpChannel(),out.getInterceptor()));
+ out.setInterceptor(new GzipHttpOutputInterceptor(this,_vary,baseRequest.getHttpChannel(),out.getInterceptor(),_syncFlush));
if (_handler!=null)
_handler.handle(target,baseRequest, request, response);
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java
index c7fc799cce..f717c2656a 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java
@@ -56,27 +56,29 @@ public class GzipHttpOutputInterceptor implements HttpOutput.Interceptor
private final HttpChannel _channel;
private final HttpField _vary;
private final int _bufferSize;
+ private final boolean _syncFlush;
private Deflater _deflater;
private ByteBuffer _buffer;
- public GzipHttpOutputInterceptor(GzipFactory factory, HttpChannel channel, HttpOutput.Interceptor next)
+ public GzipHttpOutputInterceptor(GzipFactory factory, HttpChannel channel, HttpOutput.Interceptor next,boolean syncFlush)
{
- this(factory,VARY_ACCEPT_ENCODING_USER_AGENT,channel.getHttpConfiguration().getOutputBufferSize(),channel,next);
+ this(factory,VARY_ACCEPT_ENCODING_USER_AGENT,channel.getHttpConfiguration().getOutputBufferSize(),channel,next,syncFlush);
}
- public GzipHttpOutputInterceptor(GzipFactory factory, HttpField vary, HttpChannel channel, HttpOutput.Interceptor next)
+ public GzipHttpOutputInterceptor(GzipFactory factory, HttpField vary, HttpChannel channel, HttpOutput.Interceptor next,boolean syncFlush)
{
- this(factory,vary,channel.getHttpConfiguration().getOutputBufferSize(),channel,next);
+ this(factory,vary,channel.getHttpConfiguration().getOutputBufferSize(),channel,next,syncFlush);
}
- public GzipHttpOutputInterceptor(GzipFactory factory, HttpField vary, int bufferSize, HttpChannel channel, HttpOutput.Interceptor next)
+ public GzipHttpOutputInterceptor(GzipFactory factory, HttpField vary, int bufferSize, HttpChannel channel, HttpOutput.Interceptor next,boolean syncFlush)
{
_factory=factory;
_channel=channel;
_interceptor=next;
_vary=vary;
_bufferSize=bufferSize;
+ _syncFlush=syncFlush;
}
public HttpOutput.Interceptor getNextInterceptor()
@@ -353,7 +355,7 @@ public class GzipHttpOutputInterceptor implements HttpOutput.Interceptor
int len=_buffer.capacity()-_buffer.limit() - (_last?8:0);
if (len>0)
{
- int produced=_deflater.deflate(_buffer.array(),off,len,Deflater.NO_FLUSH);
+ int produced=_deflater.deflate(_buffer.array(),off,len,_syncFlush?Deflater.SYNC_FLUSH:Deflater.NO_FLUSH);
_buffer.limit(_buffer.limit()+produced);
}
boolean finished=_deflater.finished();
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-start/src/test/resources/dist-home/modules/alpn-impl/alpn-1.8.0_71.mod b/jetty-start/src/test/resources/dist-home/modules/alpn-impl/alpn-1.8.0_71.mod
new file mode 100644
index 0000000000..3628757cbf
--- /dev/null
+++ b/jetty-start/src/test/resources/dist-home/modules/alpn-impl/alpn-1.8.0_71.mod
@@ -0,0 +1,8 @@
+[name]
+protonego-boot
+
+[files]
+http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.7.v20160121/alpn-boot-8.1.7.v20160121.jar|lib/alpn/alpn-boot-8.1.7.v20160121.jar
+
+[exec]
+-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.7.v20160121.jar
diff --git a/jetty-start/src/test/resources/dist-home/modules/alpn-impl/alpn-1.8.0_72.mod b/jetty-start/src/test/resources/dist-home/modules/alpn-impl/alpn-1.8.0_72.mod
new file mode 100644
index 0000000000..3628757cbf
--- /dev/null
+++ b/jetty-start/src/test/resources/dist-home/modules/alpn-impl/alpn-1.8.0_72.mod
@@ -0,0 +1,8 @@
+[name]
+protonego-boot
+
+[files]
+http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.7.v20160121/alpn-boot-8.1.7.v20160121.jar|lib/alpn/alpn-boot-8.1.7.v20160121.jar
+
+[exec]
+-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.7.v20160121.jar
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/java/org/eclipse/jetty/websocket/jsr356/server/browser/JsrBrowserDebugTool.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/browser/JsrBrowserDebugTool.java
index 691a41a757..ce8d230bbb 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/browser/JsrBrowserDebugTool.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/browser/JsrBrowserDebugTool.java
@@ -21,6 +21,8 @@ package org.eclipse.jetty.websocket.jsr356.server.browser;
import javax.servlet.ServletException;
import javax.websocket.DeploymentException;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
@@ -79,7 +81,11 @@ public class JsrBrowserDebugTool
private void setupServer(int port) throws DeploymentException, ServletException
{
server = new Server();
- ServerConnector connector = new ServerConnector(server);
+
+ HttpConfiguration httpConf = new HttpConfiguration();
+ httpConf.setSendServerVersion(true);
+
+ ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(httpConf));
connector.setPort(port);
server.addConnector(connector);
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/extensions/compress/CompressExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java
index 6fc9b538fc..ac32ad6d72 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java
@@ -407,12 +407,13 @@ public abstract class CompressExtension extends AbstractExtension
{
Frame frame = entry.frame;
BatchMode batchMode = entry.batchMode;
- if (OpCode.isControlFrame(frame.getOpCode()) || !frame.hasPayload())
+ if (OpCode.isControlFrame(frame.getOpCode()))
{
+ // Do not deflate control frames
nextOutgoingFrame(frame,this,batchMode);
return;
}
-
+
compress(entry,true);
}
@@ -434,7 +435,7 @@ public abstract class CompressExtension extends AbstractExtension
// no input supplied
needsCompress = false;
}
-
+
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] output = new byte[outputLength];
@@ -486,7 +487,8 @@ public abstract class CompressExtension extends AbstractExtension
}
else if (fin)
{
- // Special case: 8.2.3.6. Generating an Empty Fragment Manually
+ // Special case: 7.2.3.6. Generating an Empty Fragment Manually
+ // https://tools.ietf.org/html/rfc7692#section-7.2.3.6
payload = ByteBuffer.wrap(new byte[] { 0x00 });
}
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtension.java
index c307e5356b..93ea4fbcbf 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtension.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtension.java
@@ -33,7 +33,7 @@ import org.eclipse.jetty.websocket.common.OpCode;
/**
* Per Message Deflate Compression extension for WebSocket.
* <p>
- * Attempts to follow <a href="https://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-12">draft-ietf-hybi-permessage-compression-12</a>
+ * Attempts to follow <a href="https://tools.ietf.org/html/rfc7692">Compression Extensions for WebSocket</a>
*/
public class PerMessageDeflateExtension extends CompressExtension
{
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..c55f7a0a01 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
@@ -36,11 +36,15 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.MappedByteBufferPool;
+import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnection;
+import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.DecoratedObjectFactory;
@@ -58,7 +62,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 +78,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);
@@ -619,6 +622,9 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
if (LOG.isDebugEnabled())
LOG.debug("Handshake Response: {}", handshaker);
+ if (getSendServerVersion(connector))
+ response.setHeader("Server",HttpConfiguration.SERVER_VERSION);
+
// Process (version specific) handshake response
handshaker.doHandshakeResponse(request, response);
@@ -627,4 +633,19 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return true;
}
+
+ private boolean getSendServerVersion(Connector connector)
+ {
+ ConnectionFactory connFactory = connector.getConnectionFactory(HttpVersion.HTTP_1_1.asString());
+ if (connFactory == null)
+ return false;
+
+ if (connFactory instanceof HttpConnectionFactory)
+ {
+ HttpConfiguration httpConf = ((HttpConnectionFactory)connFactory).getHttpConfiguration();
+ if (httpConf != null)
+ return httpConf.getSendServerVersion();
+ }
+ return false;
+ }
}
diff --git a/pom.xml b/pom.xml
index 9457f6fb87..7a45f56fa7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1001,5 +1001,29 @@
<alpn.version>8.1.6.v20151105</alpn.version>
</properties>
</profile>
+ <profile>
+ <id>8u71</id>
+ <activation>
+ <property>
+ <name>java.version</name>
+ <value>1.8.0_71</value>
+ </property>
+ </activation>
+ <properties>
+ <alpn.version>8.1.7.v20160121</alpn.version>
+ </properties>
+ </profile>
+ <profile>
+ <id>8u72</id>
+ <activation>
+ <property>
+ <name>java.version</name>
+ <value>1.8.0_72</value>
+ </property>
+ </activation>
+ <properties>
+ <alpn.version>8.1.7.v20160121</alpn.version>
+ </properties>
+ </profile>
</profiles>
</project>
diff --git a/tests/test-quickstart/pom.xml b/tests/test-quickstart/pom.xml
index 3d65131d19..6b051ee0eb 100644
--- a/tests/test-quickstart/pom.xml
+++ b/tests/test-quickstart/pom.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
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);
}
diff --git a/tests/test-sessions/test-gcloud-sessions/pom.xml b/tests/test-sessions/test-gcloud-sessions/pom.xml
index 6ea0c976c7..d64e0cd077 100644
--- a/tests/test-sessions/test-gcloud-sessions/pom.xml
+++ b/tests/test-sessions/test-gcloud-sessions/pom.xml
@@ -54,7 +54,7 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty.gcloud</groupId>
- <artifactId>gcloud-session-manager</artifactId>
+ <artifactId>jetty-gcloud-session-manager</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>

Back to the top