Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Wilkins2013-06-17 06:29:39 +0000
committerGreg Wilkins2013-06-17 06:29:39 +0000
commit4e4ffaa54c5aad9085671c5ec35a77f865dfd3ba (patch)
treec41f5db60c1326352ae68f1b27f01f9f1bc32105
parent3ddb1d97272790dd1bd0a75c9ae9fc6515d99b95 (diff)
parent6ed36160f0d893590320403f1abb528eda0d9094 (diff)
downloadorg.eclipse.jetty.project-4e4ffaa54c5aad9085671c5ec35a77f865dfd3ba.tar.gz
org.eclipse.jetty.project-4e4ffaa54c5aad9085671c5ec35a77f865dfd3ba.tar.xz
org.eclipse.jetty.project-4e4ffaa54c5aad9085671c5ec35a77f865dfd3ba.zip
Merge remote-tracking branch 'origin/master' into servlet-3.1-api
Conflicts: jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
-rw-r--r--aggregates/jetty-all/pom.xml1
-rw-r--r--examples/async-rest/async-rest-jar/pom.xml1
-rw-r--r--examples/embedded/pom.xml1
-rw-r--r--jetty-aggregate/jetty-all-server/pom.xml212
-rw-r--r--jetty-aggregate/jetty-client/pom.xml87
-rw-r--r--jetty-aggregate/jetty-server/pom.xml97
-rw-r--r--jetty-aggregate/jetty-servlet/pom.xml96
-rw-r--r--jetty-aggregate/jetty-webapp/pom.xml103
-rw-r--r--jetty-aggregate/jetty-websocket/pom.xml91
-rw-r--r--jetty-aggregate/pom.xml44
-rw-r--r--jetty-annotations/pom.xml1
-rw-r--r--jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebAppContext.java11
-rw-r--r--jetty-client/pom.xml4
-rw-r--r--jetty-continuation/pom.xml1
-rw-r--r--jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java12
-rw-r--r--jetty-deploy/pom.xml1
-rw-r--r--jetty-distribution/pom.xml1
-rwxr-xr-xjetty-distribution/src/main/resources/bin/jetty.sh2
-rw-r--r--jetty-http-spi/pom.xml1
-rw-r--r--jetty-http/pom.xml1
-rw-r--r--jetty-io/pom.xml1
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/FillInterest.java35
-rw-r--r--jetty-jaspi/pom.xml1
-rw-r--r--jetty-jmx/pom.xml1
-rw-r--r--jetty-jndi/pom.xml1
-rw-r--r--jetty-jsp/pom.xml1
-rw-r--r--jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java13
-rw-r--r--jetty-monitor/pom.xml1
-rw-r--r--jetty-nosql/pom.xml1
-rw-r--r--jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSessionManager.java26
-rw-r--r--jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java49
-rw-r--r--jetty-osgi/jetty-osgi-boot-jsp/pom.xml1
-rw-r--r--jetty-osgi/jetty-osgi-boot-logback/pom.xml127
-rw-r--r--jetty-osgi/jetty-osgi-boot-warurl/pom.xml1
-rw-r--r--jetty-osgi/jetty-osgi-boot/pom.xml1
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java26
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/pom.xml121
-rw-r--r--jetty-osgi/jetty-osgi-httpservice/pom.xml1
-rw-r--r--jetty-osgi/jetty-osgi-servletbridge/pom.xml54
-rw-r--r--jetty-osgi/pom.xml1
-rw-r--r--jetty-osgi/test-jetty-osgi-context/pom.xml1
-rw-r--r--jetty-osgi/test-jetty-osgi-webapp/pom.xml1
-rw-r--r--jetty-osgi/test-jetty-osgi/pom.xml3
-rw-r--r--jetty-osgi/test-jetty-osgi/src/test/config/etc/webdefault.xml (renamed from jetty-osgi/jetty-osgi-boot/jettyhome/etc/webdefault.xml)0
-rw-r--r--jetty-overlay-deployer/pom.xml1
-rw-r--r--jetty-plus/pom.xml1
-rw-r--r--jetty-policy/pom.xml139
-rw-r--r--jetty-proxy/pom.xml1
-rw-r--r--jetty-rewrite/pom.xml1
-rw-r--r--jetty-runner/pom.xml2
-rw-r--r--jetty-security/pom.xml1
-rw-r--r--jetty-server/pom.xml1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java22
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java6
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java6
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Request.java81
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java21
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java60
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java4
-rw-r--r--jetty-servlet/pom.xml1
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterHolder.java8
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java13
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java2
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java72
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java14
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java39
-rw-r--r--jetty-servlets/pom.xml1
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CGI.java164
-rw-r--r--jetty-spdy/pom.xml2
-rw-r--r--jetty-spdy/spdy-client/pom.xml1
-rw-r--r--jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java2
-rw-r--r--jetty-spdy/spdy-core/pom.xml1
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java10
-rw-r--r--jetty-spdy/spdy-example-webapp/pom.xml4
-rw-r--r--jetty-spdy/spdy-http-server/src/main/config/etc/jetty-spdy.xml3
-rw-r--r--jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java15
-rw-r--r--jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java16
-rw-r--r--jetty-spdy/spdy-server/pom.xml1
-rw-r--r--jetty-start/pom.xml1
-rw-r--r--jetty-start/src/test/java/org/eclipse/jetty/start/PropertyDump.java41
-rw-r--r--jetty-start/src/test/java/org/eclipse/jetty/start/PropertyPassingTest.java245
-rw-r--r--jetty-start/src/test/resources/bogus.xml2
-rw-r--r--jetty-start/src/test/resources/property-dump-start.config8
-rw-r--r--jetty-util-ajax/pom.xml1
-rw-r--r--jetty-util/pom.xml1
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java2
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/log/StacklessLogging.java69
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java11
-rw-r--r--jetty-webapp/pom.xml1
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java1
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java14
-rw-r--r--jetty-websocket/pom.xml3
-rw-r--r--jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/UpgradeRequest.java19
-rw-r--r--jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/util/WSURI.java145
-rw-r--r--jetty-websocket/websocket-api/src/test/java/org/eclipse/jetty/websocket/api/util/WSURITest.java88
-rw-r--r--jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/UpgradeConnection.java2
-rw-r--r--jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java6
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java9
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriver.java10
-rw-r--r--jetty-websocket/websocket-server/pom.xml5
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/HandshakeRFC6455.java4
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketRequest.java240
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketResponse.java62
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketHandshake.java5
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java67
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/RequestHeadersTest.java1
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SimpleServletServer.java73
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java113
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketLoadRFC6455Test.java222
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java224
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java2
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java8
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClientConstructionTest.java5
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/CaptureSocket.java20
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/SessionSocket.java14
-rw-r--r--jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/ServletUpgradeRequest.java269
-rw-r--r--jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/ServletUpgradeResponse.java87
-rw-r--r--jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketCreator.java8
-rw-r--r--jetty-xml/pom.xml1
-rw-r--r--pom.xml29
-rw-r--r--test-continuation-jetty6/pom.xml64
-rw-r--r--test-continuation/pom.xml38
-rw-r--r--test-jetty-servlet/pom.xml24
-rw-r--r--tests/pom.xml1
-rw-r--r--tests/test-integration/pom.xml1
-rw-r--r--tests/test-loginservice/pom.xml1
-rw-r--r--tests/test-sessions/pom.xml1
-rw-r--r--tests/test-sessions/test-hash-sessions/pom.xml1
-rw-r--r--tests/test-sessions/test-jdbc-sessions/pom.xml1
-rw-r--r--tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReloadedSessionMissingClassTest.java1
-rw-r--r--tests/test-sessions/test-mongodb-sessions/pom.xml1
-rw-r--r--tests/test-sessions/test-mongodb-sessions/src/test/resources/jetty-logging.properties4
-rw-r--r--tests/test-sessions/test-sessions-common/pom.xml1
-rw-r--r--tests/test-webapps/pom.xml1
-rw-r--r--tests/test-webapps/test-jetty-webapp/pom.xml1
-rw-r--r--tests/test-webapps/test-jetty-webapp/src/main/java/com/acme/ChatServlet.java213
-rw-r--r--tests/test-webapps/test-jetty-webapp/src/main/resources/jetty-logging.properties2
-rw-r--r--tests/test-webapps/test-jetty-webapp/src/main/webapp/chat/index.html41
-rw-r--r--tests/test-webapps/test-jetty-webapp/src/test/java/org/eclipse/jetty/ChatServletTest.java93
-rw-r--r--tests/test-webapps/test-webapp-rfc2616/pom.xml1
140 files changed, 3552 insertions, 1029 deletions
diff --git a/aggregates/jetty-all/pom.xml b/aggregates/jetty-all/pom.xml
index 0ecda2131b..f7049bb157 100644
--- a/aggregates/jetty-all/pom.xml
+++ b/aggregates/jetty-all/pom.xml
@@ -9,6 +9,7 @@
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-all</artifactId>
<name>Jetty :: Aggregate :: All core Jetty</name>
+ <url>http://www.eclipse.org/jetty</url>
<build>
<sourceDirectory>${project.build.directory}/sources</sourceDirectory>
<plugins>
diff --git a/examples/async-rest/async-rest-jar/pom.xml b/examples/async-rest/async-rest-jar/pom.xml
index 0df4a96942..aeb3267ce6 100644
--- a/examples/async-rest/async-rest-jar/pom.xml
+++ b/examples/async-rest/async-rest-jar/pom.xml
@@ -9,6 +9,7 @@
<artifactId>example-async-rest-jar</artifactId>
<packaging>jar</packaging>
<name>Example Async Rest :: Jar</name>
+ <url>http://www.eclipse.org/jetty</url>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
diff --git a/examples/embedded/pom.xml b/examples/embedded/pom.xml
index 2300e30d1a..253f08278a 100644
--- a/examples/embedded/pom.xml
+++ b/examples/embedded/pom.xml
@@ -10,6 +10,7 @@
<artifactId>example-jetty-embedded</artifactId>
<name>Example :: Jetty Embedded</name>
<description>Jetty Embedded Examples</description>
+ <url>http://www.eclipse.org/jetty</url>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
diff --git a/jetty-aggregate/jetty-all-server/pom.xml b/jetty-aggregate/jetty-all-server/pom.xml
new file mode 100644
index 0000000000..9c23cae0f2
--- /dev/null
+++ b/jetty-aggregate/jetty-all-server/pom.xml
@@ -0,0 +1,212 @@
+<?xml version="1.0"?>
+<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.aggregate</groupId>
+ <artifactId>jetty-aggregate-project</artifactId>
+ <version>7.6.11-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-all-server</artifactId>
+ <name>Jetty :: Aggregate :: All Server</name>
+ <url>http://www.eclipse.org/jetty</url>
+ <properties>
+ <bundle-symbolic-name>${project.groupId}.${project.artifactId}</bundle-symbolic-name>
+ </properties>
+
+ <build>
+ <sourceDirectory>${project.build.directory}/sources</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack-dependencies</id>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <excludes>**/MANIFEST.MF,javax/**</excludes>
+ <excludeArtifactIds>javax</excludeArtifactIds>
+ <excludeGroupIds>javax,org.eclipse.jetty.orbit</excludeGroupIds>
+ <outputDirectory>${project.build.directory}/classes</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ </configuration>
+ </execution>
+ <execution>
+ <id>unpack-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <classifier>sources</classifier>
+ <includes>**/*</includes>
+ <excludes>META-INF/**</excludes>
+ <includeGroupIds>org.eclipse.jetty</includeGroupIds>
+ <excludeArtifactIds>javax</excludeArtifactIds>
+ <excludeGroupIds>javax,org.eclipse.jetty.orbit</excludeGroupIds>
+ <outputDirectory>${project.build.directory}/sources</outputDirectory>
+ <overWriteReleases>true</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <executions>
+ <execution>
+ <id>bundle-manifest</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ !org.eclipse.jetty*,
+ com.sun.org.apache.commons.logging;version="[2.1,3)";split="glassfish";resolution:=optional,
+ javax.annotation;version="1.0.0";resolution:=optional,
+ javax.servlet;version="2.5.0",
+ javax.servlet.http;version="2.5.0",
+ javax.mail;version="1.4.0";resolution:=optional,
+ javax.mail.event;version="1.4.0";resolution:=optional,
+ javax.mail.internet;version="1.4.0";resolution:=optional,
+ javax.mail.search;version="1.4.0";resolution:=optional,
+ javax.mail.util;version="1.4.0";resolution:=optional,
+ javax.transaction;version="1.1.0";resolution:=optional,
+ javax.transaction.xa;version="1.1.0";resolution:=optional,
+ org.slf4j;resolution:=optional,
+ org.slf4j.spi;resolution:=optional,
+ org.slf4j.helpers;resolution:=optional,
+ org.xml.sax,
+ org.xml.sax.helpers,
+ javax.security.cert,
+ javax.xml.parsers,
+ javax.net.ssl,
+ !org.mortbay.*,
+ org.objectweb.asm;version="3.1.0";resolution:=optional,
+ org.objectweb.asm.commons;version="3.1.0";resolution:=optional,
+ javax.security.auth.message*;resolution:=optional,
+ *
+ </Import-Package>
+ <Export-Package>org.eclipse.jetty*;version="${parsedVersion.osgiVersion}"</Export-Package>
+ <!-- disable the uses directive: jetty will accomodate pretty much any versions
+ of the packages it uses; no need to reflect some tight dependency determined at
+ compilation time. -->
+ <_nouses>true</_nouses>
+ <Bundle-RequiredExecutionEnvironment>J2SE-1.5</Bundle-RequiredExecutionEnvironment>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-deploy</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-websocket</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.servlet</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jmx</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-plus</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-ajp</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-annotations</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jaspi</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jndi</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-rewrite</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlets</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-nested</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.security.auth.message</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.mail.glassfish</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.activation</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.annotation</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/jetty-aggregate/jetty-client/pom.xml b/jetty-aggregate/jetty-client/pom.xml
new file mode 100644
index 0000000000..1fc0ab7426
--- /dev/null
+++ b/jetty-aggregate/jetty-client/pom.xml
@@ -0,0 +1,87 @@
+<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.aggregate</groupId>
+ <artifactId>jetty-aggregate-project</artifactId>
+ <version>7.6.11-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-client</artifactId>
+ <name>Jetty :: Aggregate :: HTTP Client</name>
+ <url>http://www.eclipse.org/jetty</url>
+ <build>
+ <sourceDirectory>${project.build.directory}/sources</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack-dependencies</id>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <includes>META-INF/**,org/eclipse/**</includes>
+ <excludes>**/MANIFEST.MF</excludes>
+ <outputDirectory>${project.build.directory}/classes</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ </configuration>
+ </execution>
+ <execution>
+ <id>unpack-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <classifier>sources</classifier>
+ <includes>**/*</includes>
+ <excludes>META-INF/**</excludes>
+ <includeGroupIds>org.eclipse.jetty</includeGroupIds>
+ <outputDirectory>${project.build.directory}/sources</outputDirectory>
+ <overWriteReleases>true</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>package</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <archive>
+ <manifest>
+ </manifest>
+ <manifestEntries>
+ <mode>development</mode>
+ <url>http://eclipse.org/jetty</url>
+ <Built-By>${user.name}</Built-By>
+ <package>org.eclipse.jetty</package>
+ <Bundle-License>http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/NOTICE.txt</Bundle-License>
+ <Bundle-Name>Jetty HTTP Client</Bundle-Name>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-client</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/jetty-aggregate/jetty-server/pom.xml b/jetty-aggregate/jetty-server/pom.xml
new file mode 100644
index 0000000000..7c658ed4b8
--- /dev/null
+++ b/jetty-aggregate/jetty-server/pom.xml
@@ -0,0 +1,97 @@
+<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.aggregate</groupId>
+ <artifactId>jetty-aggregate-project</artifactId>
+ <version>7.6.11-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-server</artifactId>
+ <name>Jetty :: Aggregate :: HTTP Server</name>
+ <url>http://www.eclipse.org/jetty</url>
+ <build>
+ <sourceDirectory>${project.build.directory}/sources</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack-dependencies</id>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <excludes>**/MANIFEST.MF,javax/**</excludes>
+ <excludeArtifactIds>javax</excludeArtifactIds>
+ <excludeGroupIds>javax,org.eclipse.jetty.orbit</excludeGroupIds>
+ <outputDirectory>${project.build.directory}/classes</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ </configuration>
+ </execution>
+ <execution>
+ <id>unpack-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <classifier>sources</classifier>
+ <includes>**/*</includes>
+ <excludes>META-INF/**</excludes>
+ <includeGroupIds>org.eclipse.jetty</includeGroupIds>
+ <excludeArtifactIds>javax</excludeArtifactIds>
+ <excludeGroupIds>javax,org.eclipse.jetty.orbit</excludeGroupIds>
+ <outputDirectory>${project.build.directory}/sources</outputDirectory>
+ <overWriteReleases>true</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins
+ </groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>package</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <archive>
+ <manifest>
+ </manifest>
+ <manifestEntries>
+ <mode>development</mode>
+ <url>http://eclipse.org/jetty</url>
+ <Built-By>${user.name}</Built-By>
+ <package>org.eclipse.jetty</package>
+ <Bundle-License>http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/NOTICE.txt</Bundle-License>
+ <Bundle-Name>Jetty HTTP Server</Bundle-Name>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-websocket</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/jetty-aggregate/jetty-servlet/pom.xml b/jetty-aggregate/jetty-servlet/pom.xml
new file mode 100644
index 0000000000..ad4d4b13b3
--- /dev/null
+++ b/jetty-aggregate/jetty-servlet/pom.xml
@@ -0,0 +1,96 @@
+<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.aggregate</groupId>
+ <artifactId>jetty-aggregate-project</artifactId>
+ <version>7.6.11-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-servlet</artifactId>
+ <name>Jetty :: Aggregate :: Servlet Server</name>
+ <url>http://www.eclipse.org/jetty</url>
+ <build>
+ <sourceDirectory>${project.build.directory}/sources</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack-dependencies</id>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <excludes>**/MANIFEST.MF,javax/**</excludes>
+ <excludeArtifactIds>javax</excludeArtifactIds>
+ <excludeGroupIds>javax,org.eclipse.jetty.orbit</excludeGroupIds>
+ <outputDirectory>${project.build.directory}/classes</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ </configuration>
+ </execution>
+ <execution>
+ <id>unpack-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <classifier>sources</classifier>
+ <includes>**/*</includes>
+ <excludes>META-INF/**</excludes>
+ <includeGroupIds>org.eclipse.jetty</includeGroupIds>
+ <excludeArtifactIds>javax</excludeArtifactIds>
+ <excludeGroupIds>javax,org.eclipse.jetty.orbit</excludeGroupIds>
+ <outputDirectory>${project.build.directory}/sources</outputDirectory>
+ <overWriteReleases>true</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>package</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <archive>
+ <manifest>
+ </manifest>
+ <manifestEntries>
+ <mode>development</mode>
+ <url>http://eclipse.org/jetty</url>
+ <Built-By>${user.name}</Built-By>
+ <package>org.eclipse.jetty</package>
+ <Bundle-License>http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/NOTICE.txt</Bundle-License>
+ <Bundle-Name>Jetty HTTP Server</Bundle-Name>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-websocket</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/jetty-aggregate/jetty-webapp/pom.xml b/jetty-aggregate/jetty-webapp/pom.xml
new file mode 100644
index 0000000000..3eb1748eda
--- /dev/null
+++ b/jetty-aggregate/jetty-webapp/pom.xml
@@ -0,0 +1,103 @@
+<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.aggregate</groupId>
+ <artifactId>jetty-aggregate-project</artifactId>
+ <version>7.6.11-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-webapp</artifactId>
+ <name>Jetty :: Aggregate :: WebApp Server</name>
+ <url>http://www.eclipse.org/jetty</url>
+ <build>
+ <sourceDirectory>${project.build.directory}/sources</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack-dependencies</id>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <includes>META-INF/**,org/eclipse/**,org/apache/jasper/compiler/**</includes>
+ <excludes>**/MANIFEST.MF,javax/**</excludes>
+ <excludeArtifactIds>javax</excludeArtifactIds>
+ <excludeGroupIds>javax,org.eclipse.jetty.orbit</excludeGroupIds>
+ <outputDirectory>${project.build.directory}/classes</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ </configuration>
+ </execution>
+ <execution>
+ <id>unpack-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <classifier>sources</classifier>
+ <includes>**/*</includes>
+ <excludes>META-INF/**</excludes>
+ <includeGroupIds>org.eclipse.jetty</includeGroupIds>
+ <excludeArtifactIds>javax</excludeArtifactIds>
+ <excludeGroupIds>javax,org.eclipse.jetty.orbit</excludeGroupIds>
+ <outputDirectory>${project.build.directory}/sources</outputDirectory>
+ <overWriteReleases>true</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins
+ </groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>package</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <archive>
+ <manifest>
+ </manifest>
+ <manifestEntries>
+ <mode>development</mode>
+ <url>http://eclipse.org/jetty</url>
+ <Built-By>${user.name}</Built-By>
+ <package>org.eclipse.jetty</package>
+ <Bundle-License>http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/NOTICE.txt</Bundle-License>
+ <Bundle-Name>Jetty HTTP Server</Bundle-Name>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.servlet</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.servlet</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/jetty-aggregate/jetty-websocket/pom.xml b/jetty-aggregate/jetty-websocket/pom.xml
new file mode 100644
index 0000000000..c45885c2cb
--- /dev/null
+++ b/jetty-aggregate/jetty-websocket/pom.xml
@@ -0,0 +1,91 @@
+<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.aggregate</groupId>
+ <artifactId>jetty-aggregate-project</artifactId>
+ <version>7.6.11-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-websocket</artifactId>
+ <name>Jetty :: Aggregate :: Websocket</name>
+ <url>http://www.eclipse.org/jetty</url>
+ <build>
+ <sourceDirectory>${project.build.directory}/sources</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack-dependencies</id>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <excludes>**/MANIFEST.MF,javax/**,about.html</excludes>
+ <excludeArtifactIds>javax</excludeArtifactIds>
+ <excludeGroupIds>javax,org.eclipse.jetty.orbit</excludeGroupIds>
+ <outputDirectory>${project.build.directory}/classes</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ </configuration>
+ </execution>
+ <execution>
+ <id>unpack-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <classifier>sources</classifier>
+ <includes>**/*</includes>
+ <excludes>META-INF/**</excludes>
+ <includeGroupIds>org.eclipse.jetty</includeGroupIds>
+ <excludeArtifactIds>javax</excludeArtifactIds>
+ <excludeGroupIds>javax,org.eclipse.jetty.orbit</excludeGroupIds>
+ <outputDirectory>${project.build.directory}/sources</outputDirectory>
+ <overWriteReleases>true</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins
+ </groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>package</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <archive>
+ <manifest>
+ </manifest>
+ <manifestEntries>
+ <mode>development</mode>
+ <url>http://eclipse.org/jetty</url>
+ <Built-By>${user.name}</Built-By>
+ <package>org.eclipse.jetty</package>
+ <Bundle-License>http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/NOTICE.txt</Bundle-License>
+ <Bundle-Name>Jetty HTTP Server</Bundle-Name>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-websocket</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/jetty-aggregate/pom.xml b/jetty-aggregate/pom.xml
new file mode 100644
index 0000000000..b23767e4b5
--- /dev/null
+++ b/jetty-aggregate/pom.xml
@@ -0,0 +1,44 @@
+<?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">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-project</artifactId>
+ <version>7.6.11-SNAPSHOT</version>
+ </parent>
+ <groupId>org.eclipse.jetty.aggregate</groupId>
+ <artifactId>jetty-aggregate-project</artifactId>
+ <name>Jetty :: Aggregate Project</name>
+ <url>http://www.eclipse.org/jetty</url>
+ <packaging>pom</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <configuration>
+ <!-- No Point running PMD on aggregate projects -->
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <configuration>
+ <!-- No Point running Findbugs on aggregate projects -->
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <modules>
+ <module>jetty-server</module>
+ <module>jetty-client</module>
+ <module>jetty-servlet</module>
+ <module>jetty-webapp</module>
+ <module>jetty-websocket</module>
+ <module>jetty-plus</module>
+ <module>jetty-all-server</module>
+ <module>jetty-all</module>
+ </modules>
+</project>
diff --git a/jetty-annotations/pom.xml b/jetty-annotations/pom.xml
index 41ae058ae9..c3b6cbd3b7 100644
--- a/jetty-annotations/pom.xml
+++ b/jetty-annotations/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-annotations</artifactId>
<name>Jetty :: Servlet Annotations</name>
<description>Annotation support for deploying servlets in jetty.</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.annotations</bundle-symbolic-name>
</properties>
diff --git a/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebAppContext.java b/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebAppContext.java
index 47ecd5bc0e..e00479020f 100644
--- a/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebAppContext.java
+++ b/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebAppContext.java
@@ -30,6 +30,7 @@ import java.security.CodeSource;
import java.security.PermissionCollection;
import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.EventListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -50,9 +51,12 @@ import org.eclipse.jetty.ant.utils.TaskLog;
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.Holder;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
@@ -676,6 +680,13 @@ public class AntWebAppContext extends WebAppContext
TaskLog.logWithTimestamp("Stopping web application "+this);
Thread.currentThread().sleep(500L);
super.doStop();
+ //remove all filters, servlets and listeners. They will be recreated
+ //either via application of a context xml file or web.xml or annotation or servlet api
+ setEventListeners(new EventListener[0]);
+ getServletHandler().setFilters(new FilterHolder[0]);
+ getServletHandler().setFilterMappings(new FilterMapping[0]);
+ getServletHandler().setServlets(new ServletHolder[0]);
+ getServletHandler().setServletMappings(new ServletMapping[0]);
}
catch (InterruptedException e)
{
diff --git a/jetty-client/pom.xml b/jetty-client/pom.xml
index 00b4dcfa66..8b053c9456 100644
--- a/jetty-client/pom.xml
+++ b/jetty-client/pom.xml
@@ -8,13 +8,11 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-client</artifactId>
<name>Jetty :: Asynchronous HTTP Client</name>
- <url>{$jetty.url}</url>
-
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.client</bundle-symbolic-name>
<jetty.test.policy.loc>target/test-policy</jetty.test.policy.loc>
</properties>
-
<build>
<plugins>
<plugin>
diff --git a/jetty-continuation/pom.xml b/jetty-continuation/pom.xml
index 488720a066..4683f8b89c 100644
--- a/jetty-continuation/pom.xml
+++ b/jetty-continuation/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-continuation</artifactId>
<name>Jetty :: Continuation</name>
<description>Asynchronous API</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.continuation</bundle-symbolic-name>
</properties>
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java
index 2abb8412fe..4bb548a3a1 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java
@@ -166,7 +166,17 @@ public class Servlet3Continuation implements Continuation
@Override
public boolean isSuspended()
{
- return _request.isAsyncStarted();
+ if (_request.isAsyncStarted())
+ return true;
+ try
+ {
+ return _request.getAsyncContext()!=null;
+ }
+ catch(IllegalStateException e)
+ {
+ // ignored
+ }
+ return false;
}
/* ------------------------------------------------------------ */
diff --git a/jetty-deploy/pom.xml b/jetty-deploy/pom.xml
index e69a8c57d8..abd72178d7 100644
--- a/jetty-deploy/pom.xml
+++ b/jetty-deploy/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-deploy</artifactId>
<name>Jetty :: Deployers</name>
<description>Jetty deployers</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.deploy</bundle-symbolic-name>
</properties>
diff --git a/jetty-distribution/pom.xml b/jetty-distribution/pom.xml
index 26c4399a9b..0703d88b1f 100644
--- a/jetty-distribution/pom.xml
+++ b/jetty-distribution/pom.xml
@@ -7,6 +7,7 @@
</parent>
<artifactId>jetty-distribution</artifactId>
<name>Jetty :: Distribution Assemblies</name>
+ <url>http://www.eclipse.org/jetty</url>
<packaging>pom</packaging>
<properties>
<assembly-directory>target/distribution</assembly-directory>
diff --git a/jetty-distribution/src/main/resources/bin/jetty.sh b/jetty-distribution/src/main/resources/bin/jetty.sh
index bfcb1fdabb..cbd9f24eb4 100755
--- a/jetty-distribution/src/main/resources/bin/jetty.sh
+++ b/jetty-distribution/src/main/resources/bin/jetty.sh
@@ -371,7 +371,7 @@ fi
#####################################################
if [ "$JETTY_PORT" ]
then
- JAVA_OPTIONS+=("-Djetty.port=$JETTY_PORT")
+ JETTY_ARGS+=("jetty.port=$JETTY_PORT")
fi
#####################################################
diff --git a/jetty-http-spi/pom.xml b/jetty-http-spi/pom.xml
index 7dc16201b8..42439750c0 100644
--- a/jetty-http-spi/pom.xml
+++ b/jetty-http-spi/pom.xml
@@ -7,6 +7,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http-spi</artifactId>
<name>Jetty :: Http Service Provider Interface</name>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.http.spi</bundle-symbolic-name>
</properties>
diff --git a/jetty-http/pom.xml b/jetty-http/pom.xml
index 7cff20243d..930304c271 100644
--- a/jetty-http/pom.xml
+++ b/jetty-http/pom.xml
@@ -8,6 +8,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http</artifactId>
<name>Jetty :: Http Utility</name>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.http</bundle-symbolic-name>
</properties>
diff --git a/jetty-io/pom.xml b/jetty-io/pom.xml
index cfd1fd3708..6a698a7a25 100644
--- a/jetty-io/pom.xml
+++ b/jetty-io/pom.xml
@@ -7,6 +7,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-io</artifactId>
<name>Jetty :: IO Utility</name>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.io</bundle-symbolic-name>
</properties>
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/FillInterest.java b/jetty-io/src/main/java/org/eclipse/jetty/io/FillInterest.java
index c352f006b0..6af94f59f9 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/FillInterest.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/FillInterest.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.ReadPendingException;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.util.Callback;
@@ -34,8 +35,7 @@ import org.eclipse.jetty.util.Callback;
*/
public abstract class FillInterest
{
- private final AtomicBoolean _interested = new AtomicBoolean(false);
- private volatile Callback _callback;
+ private final AtomicReference<Callback> _interested = new AtomicReference<>(null);
/* ------------------------------------------------------------ */
protected FillInterest()
@@ -52,9 +52,11 @@ public abstract class FillInterest
*/
public <C> void register(Callback callback) throws ReadPendingException
{
- if (!_interested.compareAndSet(false,true))
+ if (callback==null)
+ throw new IllegalArgumentException();
+
+ if (!_interested.compareAndSet(null,callback))
throw new ReadPendingException();
- _callback=callback;
try
{
if (needsFill())
@@ -71,12 +73,9 @@ public abstract class FillInterest
*/
public void fillable()
{
- if (_interested.compareAndSet(true,false))
- {
- Callback callback=_callback;
- _callback=null;
+ Callback callback=_interested.get();
+ if (callback!=null && _interested.compareAndSet(callback,null))
callback.succeeded();
- }
}
/* ------------------------------------------------------------ */
@@ -85,7 +84,7 @@ public abstract class FillInterest
*/
public boolean isInterested()
{
- return _interested.get();
+ return _interested.get()!=null;
}
/* ------------------------------------------------------------ */
@@ -93,30 +92,24 @@ public abstract class FillInterest
*/
public void onFail(Throwable cause)
{
- if (_interested.compareAndSet(true,false))
- {
- Callback callback=_callback;
- _callback=null;
+ Callback callback=_interested.get();
+ if (callback!=null && _interested.compareAndSet(callback,null))
callback.failed(cause);
- }
}
/* ------------------------------------------------------------ */
public void onClose()
{
- if (_interested.compareAndSet(true,false))
- {
- Callback callback=_callback;
- _callback=null;
+ Callback callback=_interested.get();
+ if (callback!=null && _interested.compareAndSet(callback,null))
callback.failed(new ClosedChannelException());
- }
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
- return String.format("FillInterest@%x{%b,%s}",hashCode(),_interested.get(),_callback);
+ return String.format("FillInterest@%x{%b,%s}",hashCode(),_interested.get(),_interested.get());
}
/* ------------------------------------------------------------ */
diff --git a/jetty-jaspi/pom.xml b/jetty-jaspi/pom.xml
index 5eea3b4b29..e65c83749f 100644
--- a/jetty-jaspi/pom.xml
+++ b/jetty-jaspi/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-jaspi</artifactId>
<name>Jetty :: JASPI Security</name>
<description>Jetty security infrastructure</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.jaspi</bundle-symbolic-name>
</properties>
diff --git a/jetty-jmx/pom.xml b/jetty-jmx/pom.xml
index 07e346abea..f048e28d18 100644
--- a/jetty-jmx/pom.xml
+++ b/jetty-jmx/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-jmx</artifactId>
<name>Jetty :: JMX Management</name>
<description>JMX management artifact for jetty.</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.jmx</bundle-symbolic-name>
</properties>
diff --git a/jetty-jndi/pom.xml b/jetty-jndi/pom.xml
index 2c155ded43..404a420b8c 100644
--- a/jetty-jndi/pom.xml
+++ b/jetty-jndi/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-jndi</artifactId>
<name>Jetty :: JNDI Naming</name>
<description>JNDI spi impl for java namespace.</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.jndi</bundle-symbolic-name>
</properties>
diff --git a/jetty-jsp/pom.xml b/jetty-jsp/pom.xml
index 0cb400d2cc..4ee8294076 100644
--- a/jetty-jsp/pom.xml
+++ b/jetty-jsp/pom.xml
@@ -7,6 +7,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jsp</artifactId>
<name>Jetty :: JSP dependencies</name>
+ <url>http://www.eclipse.org/jetty</url>
<packaging>jar</packaging>
<build>
</build>
diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java
index 83df67c4de..0489a2d875 100644
--- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java
+++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java
@@ -22,6 +22,7 @@ import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
+import java.util.EventListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -29,6 +30,10 @@ import java.util.Set;
import java.util.TreeSet;
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.FilterMapping;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -296,6 +301,14 @@ public class JettyWebAppContext extends WebAppContext
//just wait a little while to ensure no requests are still being processed
Thread.currentThread().sleep(500L);
super.doStop();
+
+ //remove all listeners, servlets and filters. This is because we will re-apply
+ //any context xml file, which means they would potentially be added multiple times.
+ setEventListeners(new EventListener[0]);
+ getServletHandler().setFilters(new FilterHolder[0]);
+ getServletHandler().setFilterMappings(new FilterMapping[0]);
+ getServletHandler().setServlets(new ServletHolder[0]);
+ getServletHandler().setServletMappings(new ServletMapping[0]);
}
@Override
diff --git a/jetty-monitor/pom.xml b/jetty-monitor/pom.xml
index e0b154ef93..c95b52a9e2 100644
--- a/jetty-monitor/pom.xml
+++ b/jetty-monitor/pom.xml
@@ -24,6 +24,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-monitor</artifactId>
<name>Jetty :: Monitoring</name>
+ <url>http://www.eclipse.org/jetty</url>
<description>Performance monitoring artifact for jetty.</description>
<properties>
<bundle-symbolic-name>${project.groupId}.monitor</bundle-symbolic-name>
diff --git a/jetty-nosql/pom.xml b/jetty-nosql/pom.xml
index 2c0ac1b8a1..02c37e707f 100644
--- a/jetty-nosql/pom.xml
+++ b/jetty-nosql/pom.xml
@@ -7,6 +7,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-nosql</artifactId>
<name>Jetty :: NoSQL Session Managers</name>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.nosql</bundle-symbolic-name>
</properties>
diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSessionManager.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSessionManager.java
index 48acc817da..d5ebdd2938 100644
--- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSessionManager.java
+++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSessionManager.java
@@ -40,6 +40,7 @@ public abstract class NoSqlSessionManager extends AbstractSessionManager impleme
private int _savePeriod=0;
private int _idlePeriod=-1;
private boolean _invalidateOnStop;
+ private boolean _preserveOnStop;
private boolean _saveAllAttributes;
/* ------------------------------------------------------------ */
@@ -104,7 +105,10 @@ public abstract class NoSqlSessionManager extends AbstractSessionManager impleme
for (NoSqlSession session : sessions)
{
session.save(false);
- removeSession(session,false);
+
+ if (!_preserveOnStop) {
+ removeSession(session,false);
+ }
}
}
else
@@ -279,6 +283,16 @@ public abstract class NoSqlSessionManager extends AbstractSessionManager impleme
/* ------------------------------------------------------------ */
/**
+ * Preserve sessions when the session manager is stopped otherwise remove them from the DB.
+ * @return the removeOnStop
+ */
+ public boolean isPreserveOnStop()
+ {
+ return _preserveOnStop;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
* Invalidate sessions when the session manager is stopped otherwise save them to the DB.
* @param invalidateOnStop the invalidateOnStop to set
*/
@@ -289,6 +303,16 @@ public abstract class NoSqlSessionManager extends AbstractSessionManager impleme
/* ------------------------------------------------------------ */
/**
+ * Preserve sessions when the session manager is stopped otherwise remove them from the DB.
+ * @param removeOnStop the removeOnStop to set
+ */
+ public void setPreserveOnStop(boolean preserveOnStop)
+ {
+ _preserveOnStop = preserveOnStop;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
* Save all attributes of a session or only update the dirty attributes.
* @return the saveAllAttributes
*/
diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java
index b078f08e90..0d1a0bb42c 100644
--- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java
+++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java
@@ -137,25 +137,25 @@ public class MongoSessionManager extends NoSqlSessionManager
BasicDBObject sets = new BasicDBObject();
BasicDBObject unsets = new BasicDBObject();
- // handle new or existing
- if (version == null)
- {
- // New session
- upsert = true;
- version = new Long(1);
- sets.put(__CREATED,session.getCreationTime());
- sets.put(__VALID,true);
- sets.put(getContextKey(__VERSION),version);
- }
- else
- {
- version = new Long(((Number)version).longValue() + 1);
- update.put("$inc",__version_1);
- }
-
// handle valid or invalid
if (session.isValid())
{
+ // handle new or existing
+ if (version == null)
+ {
+ // New session
+ upsert = true;
+ version = new Long(1);
+ sets.put(__CREATED,session.getCreationTime());
+ sets.put(__VALID,true);
+ sets.put(getContextKey(__VERSION),version);
+ }
+ else
+ {
+ version = new Long(((Number)version).longValue() + 1);
+ update.put("$inc",__version_1);
+ }
+
sets.put(__ACCESSED,session.getAccessed());
Set<String> names = session.takeDirty();
if (isSaveAllAttributes() || upsert)
@@ -253,6 +253,7 @@ public class MongoSessionManager extends NoSqlSessionManager
DBObject attrs = (DBObject)getNestedValue(o,getContextKey());
+
if (attrs != null)
{
for (String name : attrs.keySet())
@@ -286,6 +287,22 @@ public class MongoSessionManager extends NoSqlSessionManager
}
}
+ /*
+ * We are refreshing so we should update the last accessed time.
+ */
+ BasicDBObject key = new BasicDBObject(__ID,session.getClusterId());
+ BasicDBObject sets = new BasicDBObject();
+ // Form updates
+ BasicDBObject update = new BasicDBObject();
+ sets.put(__ACCESSED,System.currentTimeMillis());
+ // Do the upsert
+ if (!sets.isEmpty())
+ {
+ update.put("$set",sets);
+ }
+
+ _sessions.update(key,update,false,false);
+
session.didActivate();
return version;
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
index 805664743a..b248d220ff 100644
--- a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-osgi-boot-jsp</artifactId>
<name>Jetty :: OSGi :: Boot JSP</name>
<description>Jetty OSGi Boot JSP bundle</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.boot.jsp</bundle-symbolic-name>
</properties>
diff --git a/jetty-osgi/jetty-osgi-boot-logback/pom.xml b/jetty-osgi/jetty-osgi-boot-logback/pom.xml
new file mode 100644
index 0000000000..f1985b7e05
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot-logback/pom.xml
@@ -0,0 +1,127 @@
+<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.osgi</groupId>
+ <artifactId>jetty-osgi-project</artifactId>
+ <version>7.6.11-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-osgi-boot-logback</artifactId>
+ <name>Jetty :: OSGi :: Boot Logback</name>
+ <description>Jetty OSGi Boot Logback bundle</description>
+ <url>http://www.eclipse.org/jetty</url>
+ <properties>
+ <bundle-symbolic-name>${project.groupId}.boot.logback</bundle-symbolic-name>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty.osgi</groupId>
+ <artifactId>jetty-osgi-boot</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.osgi</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.osgi</groupId>
+ <artifactId>org.eclipse.osgi.services</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>artifact-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>test-jar</id>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <archive>
+ <manifestFile>target/classes/META-INF/MANIFEST.MF</manifestFile>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <executions>
+ <execution>
+ <id>bundle-manifest</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>org.eclipse.jetty.osgi.boot.logback;singleton:=true</Bundle-SymbolicName>
+ <Bundle-Name>Jetty-OSGi-Logback Integration</Bundle-Name>
+ <Fragment-Host>org.eclipse.jetty.osgi.boot</Fragment-Host>
+ <Import-Package>
+ch.qos.logback.access.jetty;version="[0.9,1.1)";resolution:=optional,
+ch.qos.logback.access.jetty.v7;version="[0.9,1.1)";resolution:=optional,
+ch.qos.logback.*;version="[0.9,1.1)",
+org.osgi.framework.*,
+org.slf4j.*,
+*;resolution:=optional
+ </Import-Package>
+ <Export-Package>
+!org.eclipse.jetty.osgi.boot.logback.internal.*,
+org.eclipse.jetty.osgi.boot.logback.*;version="${parsedVersion.osgiVersion}"
+ </Export-Package>
+ <_nouses>true</_nouses>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <configuration>
+ <onlyAnalyze>org.eclipse.jetty.osgi.boot.logback.*</onlyAnalyze>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+
+</project>
diff --git a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
index 79edf06ea3..a2ad1f2830 100644
--- a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
@@ -9,6 +9,7 @@
<artifactId>jetty-osgi-boot-warurl</artifactId>
<name>Jetty :: OSGi :: Boot :: Warurl</name>
<description>Jetty OSGi Boot-Warurl bundle</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.boot.warurl</bundle-symbolic-name>
</properties>
diff --git a/jetty-osgi/jetty-osgi-boot/pom.xml b/jetty-osgi/jetty-osgi-boot/pom.xml
index 3f80c17d1f..610e61ff01 100644
--- a/jetty-osgi/jetty-osgi-boot/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-osgi-boot</artifactId>
<name>Jetty :: OSGi :: Boot</name>
<description>Jetty OSGi Boot bundle</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.boot</bundle-symbolic-name>
</properties>
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java
index 03d3dcc0e3..5e3d5b6658 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java
@@ -272,8 +272,13 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
if (tmp != null)
{
File defaultWebXml = getFile (tmp, bundleInstallLocation);
- if (defaultWebXml != null && defaultWebXml.exists())
- _webApp.setDefaultsDescriptor(defaultWebXml.getAbsolutePath());
+ if (defaultWebXml != null)
+ {
+ if (defaultWebXml.exists())
+ _webApp.setDefaultsDescriptor(defaultWebXml.getAbsolutePath());
+ else
+ LOG.warn(defaultWebXml.getAbsolutePath()+" does not exist");
+ }
}
//Handle Require-TldBundle
@@ -377,6 +382,7 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
HashMap properties = new HashMap();
properties.put("Server", getDeploymentManager().getServer());
properties.put(OSGiWebappConstants.JETTY_BUNDLE_ROOT, rootResource.toString());
+ properties.put(OSGiServerConstants.JETTY_HOME, getDeploymentManager().getServer().getAttribute(OSGiServerConstants.JETTY_HOME));
xmlConfiguration.getProperties().putAll(properties);
xmlConfiguration.configure(_webApp);
}
@@ -390,11 +396,21 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
{
if (file == null)
return null;
-
- if (file.startsWith("/") || file.startsWith("file:/"))
+
+ if (file.startsWith("/") || file.startsWith("file:/")) //absolute location
return new File(file);
else
- return new File(bundleInstall, file);
+ {
+ //relative location
+ //try inside the bundle first
+ File f = new File (bundleInstall, file);
+ if (f.exists()) return f;
+ String jettyHome = (String)getDeploymentManager().getServer().getAttribute(OSGiServerConstants.JETTY_HOME);
+ if (jettyHome != null)
+ return new File(jettyHome, file);
+ }
+
+ return null;
}
}
diff --git a/jetty-osgi/jetty-osgi-equinoxtools/pom.xml b/jetty-osgi/jetty-osgi-equinoxtools/pom.xml
new file mode 100644
index 0000000000..1db3f81076
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-equinoxtools/pom.xml
@@ -0,0 +1,121 @@
+<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.osgi</groupId>
+ <artifactId>jetty-osgi-project</artifactId>
+ <version>7.6.11-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-osgi-equinoxtools</artifactId>
+ <name>Jetty :: OSGi :: Example Equinox Tools</name>
+ <description>Jetty OSGi Example Equinox Tools</description>
+ <url>http://www.eclipse.org/jetty</url>
+ <properties>
+ <bundle-symbolic-name>${project.groupId}.equinoxtools</bundle-symbolic-name>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-continuation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-websocket</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.osgi</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.osgi</groupId>
+ <artifactId>org.eclipse.osgi.services</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>process-resources</phase>
+ <configuration>
+ <tasks>
+ <copy todir="target/classes/equinoxconsole">
+ <fileset dir="equinoxconsole" />
+ </copy>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>artifact-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>test-jar</id>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <archive>
+ <manifestFile>target/classes/META-INF/MANIFEST.MF</manifestFile>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <executions>
+ <execution>
+ <id>bundle-manifest</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>org.eclipse.jetty.osgi.equinoxtools</Bundle-SymbolicName>
+ <Bundle-Name>Console</Bundle-Name>
+ <Bundle-Activator>org.eclipse.jetty.osgi.equinoxtools.WebEquinoxToolsActivator</Bundle-Activator>
+ <Export-Package>org.eclipse.jetty.osgi.equinoxtools;x-internal:=true;version="${parsedVersion.osgiVersion}",
+ org.eclipse.jetty.osgi.equinoxtools.console;x-internal:=true;version="${parsedVersion.osgiVersion}"
+ </Export-Package>
+ <_nouses>true</_nouses>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <configuration>
+ <onlyAnalyze>org.eclipse.jetty.osgi.equinoxtools.*</onlyAnalyze>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/jetty-osgi/jetty-osgi-httpservice/pom.xml b/jetty-osgi/jetty-osgi-httpservice/pom.xml
index 4e79614030..b7ec57fdb5 100644
--- a/jetty-osgi/jetty-osgi-httpservice/pom.xml
+++ b/jetty-osgi/jetty-osgi-httpservice/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-httpservice</artifactId>
<name>Jetty :: OSGi :: HttpService</name>
<description>Jetty OSGi HttpService bundle</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.httpservice</bundle-symbolic-name>
</properties>
diff --git a/jetty-osgi/jetty-osgi-servletbridge/pom.xml b/jetty-osgi/jetty-osgi-servletbridge/pom.xml
new file mode 100644
index 0000000000..4da36c2e85
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-servletbridge/pom.xml
@@ -0,0 +1,54 @@
+<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.osgi</groupId>
+ <artifactId>jetty-osgi-project</artifactId>
+ <version>7.6.5-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.eclipse.jetty.osgi</groupId>
+ <artifactId>jetty-osgi-servletbridge</artifactId>
+ <name>Jetty :: OSGi :: Servletbridge</name>
+ <description>Jetty OSGi Servletbridge webapp</description>
+ <url>http://www.eclipse.org/jetty</url>
+ <packaging>war</packaging>
+ <properties><eclipse.pde>false</eclipse.pde></properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.equinox</groupId>
+ <artifactId>org.eclipse.equinox.servletbridge</artifactId>
+ <version>1.2.0.v20100503</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.osgi</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ <version>3.6.0.v20100517</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <repositories>
+ <!-- can't find equinox servlet bridge jar on maven central.
+ uploaded it to intalio.org for now. -->
+ <repository>
+ <id>intalio-org</id>
+ <url>http://intalio.org/public/maven2</url>
+ </repository>
+ </repositories>
+
+ <build>
+ <plugins><plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-eclipse-plugin</artifactId>
+ <configuration>
+ <pde>false</pde>
+ </configuration>
+ </plugin></plugins>
+ </build>
+
+</project>
diff --git a/jetty-osgi/pom.xml b/jetty-osgi/pom.xml
index 8bdab30f01..48675f8655 100644
--- a/jetty-osgi/pom.xml
+++ b/jetty-osgi/pom.xml
@@ -8,6 +8,7 @@
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<name>Jetty :: OSGi</name>
+ <url>http://www.eclipse.org/jetty</url>
<packaging>pom</packaging>
<properties>
<osgi-version>3.6.0.v20100517</osgi-version>
diff --git a/jetty-osgi/test-jetty-osgi-context/pom.xml b/jetty-osgi/test-jetty-osgi-context/pom.xml
index 046311a2c9..5eb121f629 100644
--- a/jetty-osgi/test-jetty-osgi-context/pom.xml
+++ b/jetty-osgi/test-jetty-osgi-context/pom.xml
@@ -8,6 +8,7 @@
<artifactId>test-jetty-osgi-context</artifactId>
<name>Jetty :: OSGi :: Context</name>
<description>Test Jetty OSGi bundle with a ContextHandler</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.testcontext</bundle-symbolic-name>
</properties>
diff --git a/jetty-osgi/test-jetty-osgi-webapp/pom.xml b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
index 3ce6131a3d..da2c45ea51 100644
--- a/jetty-osgi/test-jetty-osgi-webapp/pom.xml
+++ b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
@@ -9,6 +9,7 @@
<artifactId>test-jetty-osgi-webapp</artifactId>
<name>Jetty :: OSGi :: WebApp</name>
<description>Test Jetty OSGi Webapp bundle</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.webapp</bundle-symbolic-name>
</properties>
diff --git a/jetty-osgi/test-jetty-osgi/pom.xml b/jetty-osgi/test-jetty-osgi/pom.xml
index 134d0525a7..c13513f70a 100644
--- a/jetty-osgi/test-jetty-osgi/pom.xml
+++ b/jetty-osgi/test-jetty-osgi/pom.xml
@@ -8,7 +8,8 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>test-jetty-osgi</artifactId>
<name>Jetty :: OSGi :: Test</name>
- <description>Jetty OSGi Integration tests</description>
+ <description>Jetty OSGi Integration test</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.boot.test.spdy</bundle-symbolic-name>
<jetty-orbit-url>http://download.eclipse.org/jetty/orbit/</jetty-orbit-url>
diff --git a/jetty-osgi/jetty-osgi-boot/jettyhome/etc/webdefault.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/webdefault.xml
index 366ff798c9..366ff798c9 100644
--- a/jetty-osgi/jetty-osgi-boot/jettyhome/etc/webdefault.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/webdefault.xml
diff --git a/jetty-overlay-deployer/pom.xml b/jetty-overlay-deployer/pom.xml
index 8b853167ee..53071fecb1 100644
--- a/jetty-overlay-deployer/pom.xml
+++ b/jetty-overlay-deployer/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-overlay-deployer</artifactId>
<name>Jetty :: Overlay Deployer</name>
<description>Overlayed deployer</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
</properties>
<build>
diff --git a/jetty-plus/pom.xml b/jetty-plus/pom.xml
index 7ecc32e642..84b3c81895 100644
--- a/jetty-plus/pom.xml
+++ b/jetty-plus/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-plus</artifactId>
<name>Jetty :: Plus</name>
<description>Jetty JavaEE style services</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.plus</bundle-symbolic-name>
</properties>
diff --git a/jetty-policy/pom.xml b/jetty-policy/pom.xml
new file mode 100644
index 0000000000..e9fc1e8bd9
--- /dev/null
+++ b/jetty-policy/pom.xml
@@ -0,0 +1,139 @@
+<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">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-project</artifactId>
+ <version>7.6.11-SNAPSHOT</version>
+ </parent>
+ <artifactId>jetty-policy</artifactId>
+ <name>Jetty :: Policy Tool</name>
+ <packaging>jar</packaging>
+ <url>http://www.eclipse.org/jetty</url>
+ <properties>
+ <jetty.test.policy.loc>target/test-policy</jetty.test.policy.loc>
+ <bundle-symbolic-name>${project.groupId}.policy</bundle-symbolic-name>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <executions>
+ <execution>
+ <id>generate-manifest</id>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ <configuration>
+ <instructions>
+ <Export-Package>org.eclipse.jetty.policy.*;version="${parsedVersion.osgiVersion}"</Export-Package>
+ </instructions>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <!--
+ Required for OSGI
+ -->
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>config</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack</id>
+ <phase>generate-test-resources</phase>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.eclipse.jetty.toolchain</groupId>
+ <artifactId>jetty-test-policy</artifactId>
+ <version>${jetty-test-policy-version}</version>
+ <type>jar</type>
+ <overWrite>true</overWrite>
+ <includes>**/*.keystore</includes>
+ <outputDirectory>${jetty.test.policy.loc}</outputDirectory>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ <execution>
+ <id>copy</id>
+ <phase>generate-test-resources</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.eclipse.jetty.toolchain</groupId>
+ <artifactId>jetty-test-policy</artifactId>
+ <version>${jetty-test-policy-version}</version>
+ <type>jar</type>
+ <overWrite>true</overWrite>
+ <includes>**</includes>
+ <outputDirectory>${jetty.test.policy.loc}</outputDirectory>
+ <destFileName>jetty-test-policy.jar</destFileName>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <configuration>
+ <onlyAnalyze>org.eclipse.jetty.policy.*</onlyAnalyze>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jmx</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.toolchain</groupId>
+ <artifactId>jetty-test-helper</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/jetty-proxy/pom.xml b/jetty-proxy/pom.xml
index 130b18f0e6..91efb8a05c 100644
--- a/jetty-proxy/pom.xml
+++ b/jetty-proxy/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-proxy</artifactId>
<name>Jetty :: Proxy</name>
<description>Jetty Proxy</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.proxy</bundle-symbolic-name>
</properties>
diff --git a/jetty-rewrite/pom.xml b/jetty-rewrite/pom.xml
index db7e7f622e..3d9f34a9d0 100644
--- a/jetty-rewrite/pom.xml
+++ b/jetty-rewrite/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-rewrite</artifactId>
<name>Jetty :: Rewrite Handler</name>
<description>Jetty Rewrite Handler</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.rewrite</bundle-symbolic-name>
</properties>
diff --git a/jetty-runner/pom.xml b/jetty-runner/pom.xml
index 367b2e4696..96f41be149 100644
--- a/jetty-runner/pom.xml
+++ b/jetty-runner/pom.xml
@@ -12,7 +12,7 @@
<properties>
<assembly-directory>target/distribution</assembly-directory>
</properties>
-
+ <url>http://www.eclipse.org/jetty</url>
<build>
<plugins>
<plugin>
diff --git a/jetty-security/pom.xml b/jetty-security/pom.xml
index 738cf8273c..2853c156cf 100644
--- a/jetty-security/pom.xml
+++ b/jetty-security/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-security</artifactId>
<name>Jetty :: Security</name>
<description>Jetty security infrastructure</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.security</bundle-symbolic-name>
</properties>
diff --git a/jetty-server/pom.xml b/jetty-server/pom.xml
index f4c923d6c9..d01a90db9d 100644
--- a/jetty-server/pom.xml
+++ b/jetty-server/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-server</artifactId>
<name>Jetty :: Server Core</name>
<description>The core jetty server artifact.</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.server</bundle-symbolic-name>
</properties>
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
index 03e718c3fe..1ecb6b5f1b 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
@@ -450,12 +450,21 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
LOG.ignore(e);
path = _uri.getDecodedPath(StringUtil.__ISO_8859_1);
}
+
String info = URIUtil.canonicalPath(path);
if (info == null)
{
- info = "/";
- _request.setRequestURI("");
+ if( path==null && _uri.getScheme()!=null &&_uri.getHost()!=null)
+ {
+ info = "/";
+ _request.setRequestURI("");
+ }
+ else
+ {
+ badMessage(400,null);
+ return true;
+ }
}
_request.setPathInfo(info);
_version = version == null ? HttpVersion.HTTP_0_9 : version;
@@ -680,7 +689,6 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
* @param content the content buffer to write
* @param complete whether the content is complete for the response
* @param callback Callback when complete or failed
- * @throws IOException if the write fails
*/
protected void write(ByteBuffer content, boolean complete, Callback callback)
{
@@ -706,6 +714,14 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
return getEndPoint() instanceof ChannelEndPoint;
}
+ /**
+ * If a write or similar to this channel fails this method should be called. The standard implementation
+ * of {@link #failed()} is a noop. But the different implementations of HttpChannel might want to take actions.
+ */
+ public void failed()
+ {
+ }
+
private class CommitCallback implements Callback
{
private final Callback _callback;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java
index fdc2e96632..ce884eccf4 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java
@@ -578,6 +578,12 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
_generator.setPersistent(false);
super.handleException(x);
}
+
+ @Override
+ public void failed()
+ {
+ getEndPoint().shutdownOutput();
+ }
}
private class CommitCallback extends IteratingNestedCallback
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
index 152567be74..e8927812a5 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
@@ -24,7 +24,6 @@ import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritePendingException;
import java.util.concurrent.atomic.AtomicReference;
-
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
@@ -33,6 +32,7 @@ import javax.servlet.WriteListener;
import org.eclipse.jetty.http.HttpContent;
import org.eclipse.jetty.io.EofException;
+import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.util.BlockingCallback;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
@@ -125,7 +125,7 @@ write completed - - - ASYNC READY->owp
}
catch(IOException e)
{
- _channel.getEndPoint().shutdownOutput();
+ _channel.failed();
LOG.ignore(e);
}
releaseBuffer();
@@ -149,7 +149,7 @@ write completed - - - ASYNC READY->owp
}
catch(IOException e)
{
- _channel.getEndPoint().shutdownOutput();
+ _channel.failed();
LOG.ignore(e);
}
releaseBuffer();
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
index f13df9df2c..ae3cfcd52a 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
@@ -19,6 +19,7 @@
package org.eclipse.jetty.server;
import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -73,6 +74,7 @@ import org.eclipse.jetty.server.handler.ContextHandler.Context;
import org.eclipse.jetty.server.session.AbstractSession;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
+import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.MultiPartInputStreamParser;
@@ -350,6 +352,7 @@ public class Request implements HttpServletRequest
}
}
}
+
}
if (_parameters == null)
@@ -359,6 +362,28 @@ public class Request implements HttpServletRequest
// Merge parameters (needed if parameters extracted after a forward).
_parameters.addAllValues(_baseParameters);
}
+
+ if (content_type != null && content_type.length()>0 && content_type.startsWith("multipart/form-data") && getAttribute(__MULTIPART_CONFIG_ELEMENT)!=null)
+ {
+ try
+ {
+ getParts();
+ }
+ catch (IOException e)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.warn(e);
+ else
+ LOG.warn(e.toString());
+ }
+ catch (ServletException e)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.warn(e);
+ else
+ LOG.warn(e.toString());
+ }
+ }
}
finally
{
@@ -2021,38 +2046,8 @@ public class Request implements HttpServletRequest
@Override
public Part getPart(String name) throws IOException, ServletException
{
- if (getContentType() == null || !getContentType().startsWith("multipart/form-data"))
- throw new ServletException("Content-Type != multipart/form-data");
+ getParts();
- if (_multiPartInputStream == null)
- {
- MultipartConfigElement config = (MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT);
-
- if (config == null)
- throw new IllegalStateException("No multipart config for servlet");
-
- _multiPartInputStream = new MultiPartInputStreamParser(getInputStream(),
- getContentType(),config,
- (_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
- setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream);
- setAttribute(__MULTIPART_CONTEXT, _context);
- Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
- for (Part p:parts)
- {
- MultiPartInputStreamParser.MultiPart mp = (MultiPartInputStreamParser.MultiPart)p;
- if (mp.getContentDispositionFilename() == null && mp.getFile() == null)
- {
- //Servlet Spec 3.0 pg 23, parts without filenames must be put into init params
- String charset = null;
- if (mp.getContentType() != null)
- charset = MimeTypes.getCharsetFromContentType(mp.getContentType());
-
- String content=new String(mp.getBytes(),charset==null?StringUtil.__UTF8:charset);
- getParameter(""); //cause params to be evaluated
- getParameters().add(mp.getName(), content);
- }
- }
- }
return _multiPartInputStream.getPart(name);
}
@@ -2064,6 +2059,9 @@ public class Request implements HttpServletRequest
throw new ServletException("Content-Type != multipart/form-data");
if (_multiPartInputStream == null)
+ _multiPartInputStream = (MultiPartInputStreamParser)getAttribute(__MULTIPART_INPUT_STREAM);
+
+ if (_multiPartInputStream == null)
{
MultipartConfigElement config = (MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT);
@@ -2080,19 +2078,32 @@ public class Request implements HttpServletRequest
for (Part p:parts)
{
MultiPartInputStreamParser.MultiPart mp = (MultiPartInputStreamParser.MultiPart)p;
- if (mp.getContentDispositionFilename() == null && mp.getFile() == null)
+ if (mp.getContentDispositionFilename() == null)
{
//Servlet Spec 3.0 pg 23, parts without filenames must be put into init params
String charset = null;
if (mp.getContentType() != null)
charset = MimeTypes.getCharsetFromContentType(mp.getContentType());
- String content=new String(mp.getBytes(),charset==null?StringUtil.__UTF8:charset);
- getParameter(""); //cause params to be evaluated
- getParameters().add(mp.getName(), content);
+ ByteArrayOutputStream os = null;
+ InputStream is = mp.getInputStream(); //get the bytes regardless of being in memory or in temp file
+ try
+ {
+ os = new ByteArrayOutputStream();
+ IO.copy(is, os);
+ String content=new String(os.toByteArray(),charset==null?StringUtil.__UTF8:charset);
+ getParameter(""); //cause params to be evaluated
+ getParameters().add(mp.getName(), content);
+ }
+ finally
+ {
+ IO.close(os);
+ IO.close(is);
+ }
}
}
}
+
return _multiPartInputStream.getParts();
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
index 0a0a3ae431..ad2b22f294 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
@@ -169,6 +169,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
private final List<ServletContextAttributeListener> _contextAttributeListeners=new CopyOnWriteArrayList<>();
private final List<ServletRequestListener> _requestListeners=new CopyOnWriteArrayList<>();
private final List<ServletRequestAttributeListener> _requestAttributeListeners=new CopyOnWriteArrayList<>();
+ private final List<EventListener> _durableListeners = new CopyOnWriteArrayList<>();
private Map<String, Object> _managedAttributes;
private String[] _protectedTargets;
private final CopyOnWriteArrayList<AliasCheck> _aliasChecks = new CopyOnWriteArrayList<ContextHandler.AliasCheck>();
@@ -567,6 +568,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
{
_eventListeners.add(listener);
+ if (!(isStarted() || isStarting()))
+ _durableListeners.add(listener);
+
if (listener instanceof ServletContextListener)
_contextListeners.add((ServletContextListener)listener);
@@ -623,6 +627,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
return _programmaticListeners.contains(listener);
}
+
+
/* ------------------------------------------------------------ */
/**
* @return true if this context is accepting new requests
@@ -821,6 +827,10 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
for (int i = _contextListeners.size(); i-->0;)
callContextDestroyed(_contextListeners.get(i),event);
}
+
+ //retain only durable listeners
+ setEventListeners(_durableListeners.toArray(new EventListener[_durableListeners.size()]));
+ _durableListeners.clear();
if (_errorHandler != null)
_errorHandler.stop();
@@ -1823,13 +1833,14 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
query = uriInContext.substring(q + 1);
uriInContext = uriInContext.substring(0,q);
}
- // if ((q = uriInContext.indexOf(';')) > 0)
- // uriInContext = uriInContext.substring(0,q);
String pathInContext = URIUtil.canonicalPath(URIUtil.decodePath(uriInContext));
- String uri = URIUtil.addPaths(getContextPath(),uriInContext);
- ContextHandler context = ContextHandler.this;
- return new Dispatcher(context,uri,pathInContext,query);
+ if (pathInContext!=null)
+ {
+ String uri = URIUtil.addPaths(getContextPath(),uriInContext);
+ ContextHandler context = ContextHandler.this;
+ return new Dispatcher(context,uri,pathInContext,query);
+ }
}
catch (Exception e)
{
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java
index 5869d352eb..6e7a6d5e33 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java
@@ -138,6 +138,66 @@ public class HttpConnectionTest
checkContains(response,offset,"pathInfo=/");
}
+ @Test
+ public void testBadNoPath() throws Exception
+ {
+ String response=connector.getResponses("GET http://localhost:80/../cheat HTTP/1.1\n"+
+ "Host: localhost:80\n"+
+ "\n");
+ int offset=0;
+ offset = checkContains(response,offset,"HTTP/1.1 400");
+ }
+
+ @Test
+ public void testOKPathDotDotPath() throws Exception
+ {
+ String response=connector.getResponses("GET /ooops/../path HTTP/1.0\nHost: localhost:80\n\n");
+ checkContains(response,0,"HTTP/1.1 200 OK");
+ checkContains(response,0,"pathInfo=/path");
+ }
+
+ @Test
+ public void testBadPathDotDotPath() throws Exception
+ {
+ String response=connector.getResponses("GET /ooops/../../path HTTP/1.0\nHost: localhost:80\n\n");
+ checkContains(response,0,"HTTP/1.1 400 Bad Request");
+ }
+
+ @Test
+ public void testOKPathEncodedDotDotPath() throws Exception
+ {
+ String response=connector.getResponses("GET /ooops/%2e%2e/path HTTP/1.0\nHost: localhost:80\n\n");
+ checkContains(response,0,"HTTP/1.1 200 OK");
+ checkContains(response,0,"pathInfo=/path");
+ }
+
+ @Test
+ public void testBadPathEncodedDotDotPath() throws Exception
+ {
+ String response=connector.getResponses("GET /ooops/%2e%2e/%2e%2e/path HTTP/1.0\nHost: localhost:80\n\n");
+ checkContains(response,0,"HTTP/1.1 400 Bad Request");
+ }
+
+ @Test
+ public void testBadDotDotPath() throws Exception
+ {
+ String response=connector.getResponses("GET ../path HTTP/1.0\nHost: localhost:80\n\n");
+ checkContains(response,0,"HTTP/1.1 400 Bad Request");
+ }
+
+ @Test
+ public void testBadSlashDotDotPath() throws Exception
+ {
+ String response=connector.getResponses("GET /../path HTTP/1.0\nHost: localhost:80\n\n");
+ checkContains(response,0,"HTTP/1.1 400 Bad Request");
+ }
+
+ @Test
+ public void testEncodedBadDotDotPath() throws Exception
+ {
+ String response=connector.getResponses("GET %2e%2e/path HTTP/1.0\nHost: localhost:80\n\n");
+ checkContains(response,0,"HTTP/1.1 400 Bad Request");
+ }
@Test
public void testEmpty() throws Exception
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java
index b1c9bde896..3249d964b8 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java
@@ -1094,10 +1094,12 @@ public class RequestTest
MultipartConfigElement mpce = new MultipartConfigElement(tmpDir.getAbsolutePath(),-1, -1, 2);
request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, mpce);
+ String field1 = request.getParameter("field1");
+ assertNotNull(field1);
+
Part foo = request.getPart("stuff");
assertNotNull(foo);
assertTrue(foo.getSize() > 0);
-
response.setStatus(200);
}
catch (IllegalStateException e)
diff --git a/jetty-servlet/pom.xml b/jetty-servlet/pom.xml
index fa901083d2..8328869aeb 100644
--- a/jetty-servlet/pom.xml
+++ b/jetty-servlet/pom.xml
@@ -9,6 +9,7 @@
<artifactId>jetty-servlet</artifactId>
<name>Jetty :: Servlet Handling</name>
<description>Jetty Servlet Container</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.servlet</bundle-symbolic-name>
</properties>
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterHolder.java
index e69910480a..b63e40a3c6 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterHolder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterHolder.java
@@ -53,7 +53,7 @@ public class FilterHolder extends Holder<Filter>
*/
public FilterHolder()
{
- super (Source.EMBEDDED);
+ this(Source.EMBEDDED);
}
@@ -62,7 +62,7 @@ public class FilterHolder extends Holder<Filter>
*/
public FilterHolder(Holder.Source source)
{
- super (source);
+ super(source);
}
/* ---------------------------------------------------------------- */
@@ -70,7 +70,7 @@ public class FilterHolder extends Holder<Filter>
*/
public FilterHolder(Class<? extends Filter> filter)
{
- super (Source.EMBEDDED);
+ this(Source.EMBEDDED);
setHeldClass(filter);
}
@@ -79,7 +79,7 @@ public class FilterHolder extends Holder<Filter>
*/
public FilterHolder(Filter filter)
{
- super (Source.EMBEDDED);
+ this(Source.EMBEDDED);
setFilter(filter);
}
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java
index 9c12e3ec94..a7778a974a 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java
@@ -57,7 +57,7 @@ public class Holder<T> extends AbstractLifeCycle implements Dumpable
protected String _className;
protected String _displayName;
protected boolean _extInstance;
- protected boolean _asyncSupported=true;
+ protected boolean _asyncSupported;
/* ---------------------------------------------------------------- */
protected String _name;
@@ -67,8 +67,19 @@ public class Holder<T> extends AbstractLifeCycle implements Dumpable
protected Holder(Source source)
{
_source=source;
+ switch(_source)
+ {
+ case JAVAX_API:
+ case DESCRIPTOR:
+ case ANNOTATION:
+ _asyncSupported=false;
+ break;
+ default:
+ _asyncSupported=true;
+ }
}
+ /* ------------------------------------------------------------ */
public Source getSource()
{
return _source;
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
index 4224eb66e8..5080b8f461 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
@@ -1041,8 +1041,6 @@ public class ServletContextHandler extends ContextHandler
if (!_enabled)
throw new UnsupportedOperationException();
- //TODO handle partial registrations
-
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
ServletHolder holder = handler.getServlet(servletName);
if (holder == null)
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
index 392d0a8c44..e64665840a 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
@@ -21,10 +21,12 @@ package org.eclipse.jetty.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
@@ -187,30 +189,81 @@ public class ServletHandler extends ScopedHandler
super.doStop();
// Stop filters
+ List<FilterHolder> filterHolders = new ArrayList<FilterHolder>();
+ List<FilterMapping> filterMappings = ArrayUtil.asMutableList(_filterMappings);
if (_filters!=null)
{
for (int i=_filters.length; i-->0;)
{
try { _filters[i].stop(); }catch(Exception e){LOG.warn(Log.EXCEPTION,e);}
+ if (_filters[i].getSource() != Source.EMBEDDED)
+ {
+ //remove all of the mappings that were for non-embedded filters
+ _filterNameMap.remove(_filters[i].getName());
+ //remove any mappings associated with this filter
+ ListIterator<FilterMapping> fmitor = filterMappings.listIterator();
+ while (fmitor.hasNext())
+ {
+ FilterMapping fm = fmitor.next();
+ if (fm.getFilterName().equals(_filters[i].getName()))
+ fmitor.remove();
+ }
+ }
+ else
+ filterHolders.add(_filters[i]); //only retain embedded
}
}
+
+ //Retain only filters and mappings that were added using jetty api (ie Source.EMBEDDED)
+ FilterHolder[] fhs = (FilterHolder[]) LazyList.toArray(filterHolders, FilterHolder.class);
+ updateBeans(_filters, fhs);
+ _filters = fhs;
+ FilterMapping[] fms = (FilterMapping[]) LazyList.toArray(filterMappings, FilterMapping.class);
+ updateBeans(_filterMappings, fms);
+ _filterMappings = fms;
+
+ _matchAfterIndex = (_filterMappings == null || _filterMappings.length == 0 ? -1 : _filterMappings.length-1);
+ _matchBeforeIndex = -1;
// Stop servlets
+ List<ServletHolder> servletHolders = new ArrayList<ServletHolder>(); //will be remaining servlets
+ List<ServletMapping> servletMappings = ArrayUtil.asMutableList(_servletMappings); //will be remaining mappings
if (_servlets!=null)
{
for (int i=_servlets.length; i-->0;)
{
try { _servlets[i].stop(); }catch(Exception e){LOG.warn(Log.EXCEPTION,e);}
+
+ if (_servlets[i].getSource() != Source.EMBEDDED)
+ {
+ //remove from servlet name map
+ _servletNameMap.remove(_servlets[i].getName());
+ //remove any mappings associated with this servlet
+ ListIterator<ServletMapping> smitor = servletMappings.listIterator();
+ while (smitor.hasNext())
+ {
+ ServletMapping sm = smitor.next();
+ if (sm.getServletName().equals(_servlets[i].getName()))
+ smitor.remove();
+ }
+ }
+ else
+ servletHolders.add(_servlets[i]); //only retain embedded
}
}
+ //Retain only Servlets and mappings added via jetty apis (ie Source.EMBEDDED)
+ ServletHolder[] shs = (ServletHolder[]) LazyList.toArray(servletHolders, ServletHolder.class);
+ updateBeans(_servlets, shs);
+ _servlets = shs;
+ ServletMapping[] sms = (ServletMapping[])LazyList.toArray(servletMappings, ServletMapping.class);
+ updateBeans(_servletMappings, sms);
+ _servletMappings = sms;
+
+ //will be regenerated on next start
_filterPathMappings=null;
_filterNameMappings=null;
-
_servletPathMap=null;
-
- _matchBeforeIndex=-1;
- _matchAfterIndex=-1;
}
/* ------------------------------------------------------------ */
@@ -786,7 +839,7 @@ public class ServletHandler extends ScopedHandler
*/
public ServletHolder addServletWithMapping (String className,String pathSpec)
{
- ServletHolder holder = newServletHolder(null);
+ ServletHolder holder = newServletHolder(Holder.Source.EMBEDDED);
holder.setName(className+"-"+(_servlets==null?0:_servlets.length));
holder.setClassName(className);
addServletWithMapping(holder,pathSpec);
@@ -801,7 +854,6 @@ public class ServletHandler extends ScopedHandler
{
ServletHolder holder = newServletHolder(Holder.Source.EMBEDDED);
holder.setHeldClass(servlet);
- setServlets(ArrayUtil.addToArray(getServlets(), holder, ServletHolder.class));
addServletWithMapping(holder,pathSpec);
return holder;
@@ -972,7 +1024,7 @@ public class ServletHandler extends ScopedHandler
*/
public FilterHolder addFilterWithMapping (String className,String pathSpec,int dispatches)
{
- FilterHolder holder = newFilterHolder(null);
+ FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
holder.setName(className+"-"+_filters.length);
holder.setClassName(className);
@@ -1119,7 +1171,7 @@ public class ServletHandler extends ScopedHandler
{
//programmatically defined filter mappings are prepended to mapping list in the order
//in which they were defined. In other words, insert this mapping at the tail of the
- //programmatically added filter mappings, BEFORE the first web.xml defined filter mapping.
+ //programmatically prepended filter mappings, BEFORE the first web.xml defined filter mapping.
if (_matchBeforeIndex < 0)
{
@@ -1162,14 +1214,15 @@ public class ServletHandler extends ScopedHandler
{
if (pos < 0)
throw new IllegalArgumentException("FilterMapping insertion pos < 0");
-
FilterMapping[] mappings = getFilterMappings();
+
if (mappings==null || mappings.length==0)
{
return new FilterMapping[] {mapping};
}
FilterMapping[] new_mappings = new FilterMapping[mappings.length+1];
+
if (before)
{
//copy existing filter mappings up to but not including the pos
@@ -1382,6 +1435,7 @@ public class ServletHandler extends ScopedHandler
if (holders!=null)
for (ServletHolder holder:holders)
holder.setServletHandler(this);
+
updateBeans(_servlets,holders);
_servlets=holders;
updateNameMappings();
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
index 297300199f..3a13a3f813 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
@@ -93,7 +93,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
*/
public ServletHolder()
{
- super (Source.EMBEDDED);
+ this(Source.EMBEDDED);
}
/* ---------------------------------------------------------------- */
@@ -101,7 +101,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
*/
public ServletHolder(Holder.Source creator)
{
- super (creator);
+ super(creator);
}
/* ---------------------------------------------------------------- */
@@ -109,7 +109,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
*/
public ServletHolder(Servlet servlet)
{
- super (Source.EMBEDDED);
+ this(Source.EMBEDDED);
setServlet(servlet);
}
@@ -118,7 +118,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
*/
public ServletHolder(String name, Class<? extends Servlet> servlet)
{
- super (Source.EMBEDDED);
+ this(Source.EMBEDDED);
setName(name);
setHeldClass(servlet);
}
@@ -128,7 +128,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
*/
public ServletHolder(String name, Servlet servlet)
{
- super (Source.EMBEDDED);
+ this(Source.EMBEDDED);
setName(name);
setServlet(servlet);
}
@@ -138,7 +138,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
*/
public ServletHolder(Class<? extends Servlet> servlet)
{
- super (Source.EMBEDDED);
+ this(Source.EMBEDDED);
setHeldClass(servlet);
}
@@ -665,6 +665,8 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
Servlet servlet=_servlet;
synchronized(this)
{
+ if (!isStarted())
+ throw new UnavailableException("Servlet not initialized", -1);
if (_unavailable!=0 || !_initOnStartup)
servlet=getServlet();
if (servlet==null)
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java
index 0399280eca..df2aa5f7af 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java
@@ -221,6 +221,32 @@ public class DispatcherTest
}
@Test
+ public void testServletForwardDotDot() throws Exception
+ {
+ _contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*");
+ _contextHandler.addServlet(RogerThatServlet.class, "/roger/that");
+
+ String requests="GET /context/dispatch/test?forward=/%2e%2e/roger/that HTTP/1.0\n" + "Host: localhost\n\n";
+
+ String responses = _connector.getResponses(requests);
+
+ assertThat(responses,startsWith("HTTP/1.1 404 "));
+ }
+
+ @Test
+ public void testServletForwardEncodedDotDot() throws Exception
+ {
+ _contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*");
+ _contextHandler.addServlet(RogerThatServlet.class, "/roger/that");
+
+ String requests="GET /context/dispatch/test?forward=/%252e%252e/roger/that HTTP/1.0\n" + "Host: localhost\n\n";
+
+ String responses = _connector.getResponses(requests);
+
+ assertThat(responses,startsWith("HTTP/1.1 404 "));
+ }
+
+ @Test
public void testServletInclude() throws Exception
{
_contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*");
@@ -412,7 +438,10 @@ public class DispatcherTest
else if(request.getParameter("forward")!=null)
{
dispatcher = getServletContext().getRequestDispatcher(request.getParameter("forward"));
- dispatcher.forward(new ServletRequestWrapper(request), new ServletResponseWrapper(response));
+ if (dispatcher!=null)
+ dispatcher.forward(new ServletRequestWrapper(request), new ServletResponseWrapper(response));
+ else
+ response.sendError(404);
}
}
@@ -586,10 +615,14 @@ public class DispatcherTest
assertEquals(null, request.getPathInfo());
assertEquals(null, request.getPathTranslated());
- UrlEncoded query = new UrlEncoded(request.getQueryString());
+ UrlEncoded query = new UrlEncoded();
+ query.decode(request.getQueryString());
assertThat(query.getString("do"), is("end"));
+
// Russian for "selected=Temperature"
- String russian = new UrlEncoded(query.getString("else")).encode();
+ UrlEncoded q2=new UrlEncoded();
+ q2.decode(query.getString("else"));
+ String russian = q2.encode();
assertThat(russian, is("%D0%B2%D1%8B%D0%B1%D1%80%D0%B0%D0%BD%D0%BE=%D0%A2%D0%B5%D0%BC%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D1%83%D1%80%D0%B0"));
assertThat(query.getString("test"), is("1"));
assertThat(query.containsKey("foreign"), is(true));
diff --git a/jetty-servlets/pom.xml b/jetty-servlets/pom.xml
index 6585771d9a..e8c83e752d 100644
--- a/jetty-servlets/pom.xml
+++ b/jetty-servlets/pom.xml
@@ -9,6 +9,7 @@
<artifactId>jetty-servlets</artifactId>
<name>Jetty :: Utility Servlets and Filters</name>
<description>Utility Servlets from Jetty</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.servlets</bundle-symbolic-name>
</properties>
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CGI.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CGI.java
index c7b2b4f1fb..9a34873f4e 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CGI.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CGI.java
@@ -22,6 +22,9 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
@@ -32,8 +35,11 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.StringUtil;
+import org.eclipse.jetty.util.UrlEncoded;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -222,35 +228,55 @@ public class CGI extends HttpServlet
if ((pathTranslated == null) || (pathTranslated.length() == 0))
pathTranslated = path;
+ String bodyFormEncoded = null;
+ if ((HttpMethod.POST.equals(req.getMethod()) || HttpMethod.PUT.equals(req.getMethod())) && "application/x-www-form-urlencoded".equals(req.getContentType()))
+ {
+ MultiMap<String> parameterMap = new MultiMap<String>();
+ Enumeration names = req.getParameterNames();
+ while (names.hasMoreElements())
+ {
+ String parameterName = (String)names.nextElement();
+ parameterMap.addValues(parameterName, req.getParameterValues(parameterName));
+ }
+ bodyFormEncoded = UrlEncoded.encode(parameterMap, Charset.forName(req.getCharacterEncoding()), true);
+ }
+
EnvList env = new EnvList(_env);
// these ones are from "The WWW Common Gateway Interface Version 1.1"
// look at :
// http://Web.Golux.Com/coar/cgi/draft-coar-cgi-v11-03-clean.html#6.1.1
- env.set("AUTH_TYPE",req.getAuthType());
- env.set("CONTENT_LENGTH",Integer.toString(len));
- env.set("CONTENT_TYPE",req.getContentType());
- env.set("GATEWAY_INTERFACE","CGI/1.1");
+ env.set("AUTH_TYPE", req.getAuthType());
+ if (bodyFormEncoded != null)
+ {
+ env.set("CONTENT_LENGTH", Integer.toString(bodyFormEncoded.length()));
+ }
+ else
+ {
+ env.set("CONTENT_LENGTH", Integer.toString(len));
+ }
+ env.set("CONTENT_TYPE", req.getContentType());
+ env.set("GATEWAY_INTERFACE", "CGI/1.1");
if ((pathInfo != null) && (pathInfo.length() > 0))
{
- env.set("PATH_INFO",pathInfo);
+ env.set("PATH_INFO", pathInfo);
}
- env.set("PATH_TRANSLATED",pathTranslated);
- env.set("QUERY_STRING",req.getQueryString());
- env.set("REMOTE_ADDR",req.getRemoteAddr());
- env.set("REMOTE_HOST",req.getRemoteHost());
+ env.set("PATH_TRANSLATED", pathTranslated);
+ env.set("QUERY_STRING", req.getQueryString());
+ env.set("REMOTE_ADDR", req.getRemoteAddr());
+ env.set("REMOTE_HOST", req.getRemoteHost());
// The identity information reported about the connection by a
// RFC 1413 [11] request to the remote agent, if
// available. Servers MAY choose not to support this feature, or
// not to request the data for efficiency reasons.
// "REMOTE_IDENT" => "NYI"
- env.set("REMOTE_USER",req.getRemoteUser());
- env.set("REQUEST_METHOD",req.getMethod());
- env.set("SCRIPT_NAME",scriptName);
- env.set("SCRIPT_FILENAME",scriptPath);
- env.set("SERVER_NAME",req.getServerName());
- env.set("SERVER_PORT",Integer.toString(req.getServerPort()));
- env.set("SERVER_PROTOCOL",req.getProtocol());
- env.set("SERVER_SOFTWARE",getServletContext().getServerInfo());
+ env.set("REMOTE_USER", req.getRemoteUser());
+ env.set("REQUEST_METHOD", req.getMethod());
+ env.set("SCRIPT_NAME", scriptName);
+ env.set("SCRIPT_FILENAME", scriptPath);
+ env.set("SERVER_NAME", req.getServerName());
+ env.set("SERVER_PORT", Integer.toString(req.getServerPort()));
+ env.set("SERVER_PROTOCOL", req.getProtocol());
+ env.set("SERVER_SOFTWARE", getServletContext().getServerInfo());
Enumeration enm = req.getHeaderNames();
while (enm.hasMoreElements())
@@ -261,7 +287,7 @@ public class CGI extends HttpServlet
}
// these extra ones were from printenv on www.dev.nomura.co.uk
- env.set("HTTPS",(req.isSecure()?"ON":"OFF"));
+ env.set("HTTPS", (req.isSecure()?"ON":"OFF"));
// "DOCUMENT_ROOT" => root + "/docs",
// "SERVER_URL" => "NYI - http://us0245",
// "TZ" => System.getProperty("user.timezone"),
@@ -275,31 +301,22 @@ public class CGI extends HttpServlet
if (_cmdPrefix != null)
execCmd = _cmdPrefix + " " + execCmd;
- Process p = (dir == null)?Runtime.getRuntime().exec(execCmd,env.getEnvArray()):Runtime.getRuntime().exec(execCmd,env.getEnvArray(),dir);
+ LOG.debug("Environment: " + env.getExportString());
+ LOG.debug("Command: " + execCmd);
- // hook processes input to browser's output (async)
- final InputStream inFromReq = req.getInputStream();
- final OutputStream outToCgi = p.getOutputStream();
- final int inLength = len;
+ Process p;
+ if (dir == null)
+ p = Runtime.getRuntime().exec(execCmd, env.getEnvArray());
+ else
+ p = Runtime.getRuntime().exec(execCmd, env.getEnvArray(), dir);
- IO.copyThread(p.getErrorStream(),System.err);
+ // hook processes input to browser's output (async)
+ if (bodyFormEncoded != null)
+ writeProcessInput(p, bodyFormEncoded);
+ else if (len > 0)
+ writeProcessInput(p, req.getInputStream(), len);
- new Thread(new Runnable()
- {
- public void run()
- {
- try
- {
- if (inLength > 0)
- IO.copy(inFromReq,outToCgi,inLength);
- outToCgi.close();
- }
- catch (IOException e)
- {
- LOG.ignore(e);
- }
- }
- }).start();
+ IO.copyThread(p.getErrorStream(), System.err);
// hook processes output to browser's input (sync)
// if browser closes stream, we should detect it and kill process...
@@ -376,15 +393,56 @@ public class CGI extends HttpServlet
}
catch (Exception e)
{
- LOG.ignore(e);
+ LOG.debug(e);
}
}
- os = null;
p.destroy();
// LOG.debug("CGI: terminated!");
}
}
+ private static void writeProcessInput(final Process p, final String input)
+ {
+ new Thread(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ Writer outToCgi = new OutputStreamWriter(p.getOutputStream());
+ outToCgi.write(input);
+ outToCgi.close();
+ }
+ catch (IOException e)
+ {
+ LOG.debug(e);
+ }
+ }
+ }).start();
+ }
+
+ private static void writeProcessInput(final Process p, final InputStream input, final int len)
+ {
+ if (len <= 0) return;
+
+ new Thread(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ OutputStream outToCgi = p.getOutputStream();
+ IO.copy(input, outToCgi, len);
+ outToCgi.close();
+ }
+ catch (IOException e)
+ {
+ LOG.debug(e);
+ }
+ }
+ }).start();
+ }
+
/**
* Utility method to get a line of text from the input stream.
*
@@ -393,7 +451,7 @@ public class CGI extends HttpServlet
* @return the line of text
* @throws IOException
*/
- private String getTextLineFromStream(InputStream is) throws IOException
+ private static String getTextLineFromStream(InputStream is) throws IOException
{
StringBuilder buffer = new StringBuilder();
int b;
@@ -411,16 +469,16 @@ public class CGI extends HttpServlet
*/
private static class EnvList
{
- private Map envMap;
+ private Map<String, String> envMap;
EnvList()
{
- envMap = new HashMap();
+ envMap = new HashMap<String, String>();
}
EnvList(EnvList l)
{
- envMap = new HashMap(l.envMap);
+ envMap = new HashMap<String,String>(l.envMap);
}
/**
@@ -434,7 +492,19 @@ public class CGI extends HttpServlet
/** Get representation suitable for passing to exec. */
public String[] getEnvArray()
{
- return (String[])envMap.values().toArray(new String[envMap.size()]);
+ return envMap.values().toArray(new String[envMap.size()]);
+ }
+
+ public String getExportString()
+ {
+ StringBuilder sb = new StringBuilder();
+ for (String variable : getEnvArray())
+ {
+ sb.append("export \"");
+ sb.append(variable);
+ sb.append("\"; ");
+ }
+ return sb.toString();
}
@Override
diff --git a/jetty-spdy/pom.xml b/jetty-spdy/pom.xml
index 23c671934d..3516327610 100644
--- a/jetty-spdy/pom.xml
+++ b/jetty-spdy/pom.xml
@@ -11,7 +11,7 @@
<artifactId>spdy-parent</artifactId>
<packaging>pom</packaging>
<name>Jetty :: SPDY :: Parent</name>
-
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<npn.api.version>1.1.0.v20120525</npn.api.version>
</properties>
diff --git a/jetty-spdy/spdy-client/pom.xml b/jetty-spdy/spdy-client/pom.xml
index 7cdc20c55f..05395c4b1f 100644
--- a/jetty-spdy/spdy-client/pom.xml
+++ b/jetty-spdy/spdy-client/pom.xml
@@ -14,6 +14,7 @@
<bundle-symbolic-name>${project.groupId}.client</bundle-symbolic-name>
</properties>
+ <url>http://www.eclipse.org/jetty</url>
<build>
<plugins>
<plugin>
diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java
index 2456a2228f..e2a0cba22a 100644
--- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java
+++ b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java
@@ -143,7 +143,7 @@ public class SPDYClient
protected SSLEngine newSSLEngine(SslContextFactory sslContextFactory, SocketChannel channel)
{
- String peerHost = channel.socket().getInetAddress().getHostAddress();
+ String peerHost = channel.socket().getInetAddress().getHostName();
int peerPort = channel.socket().getPort();
SSLEngine engine = sslContextFactory.newSSLEngine(peerHost, peerPort);
engine.setUseClientMode(true);
diff --git a/jetty-spdy/spdy-core/pom.xml b/jetty-spdy/spdy-core/pom.xml
index 38154ac959..3193517115 100644
--- a/jetty-spdy/spdy-core/pom.xml
+++ b/jetty-spdy/spdy-core/pom.xml
@@ -14,6 +14,7 @@
<bundle-symbolic-name>${project.groupId}.core</bundle-symbolic-name>
</properties>
+ <url>http://www.eclipse.org/jetty</url>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
index 30dc870721..067f7f7e48 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
@@ -490,9 +490,15 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
goAway(x.getSessionStatus(), 0, TimeUnit.SECONDS, new Callback.Adapter());
}
- private void onSyn(SynStreamFrame frame)
+ private void onSyn(final SynStreamFrame frame)
{
- IStream stream = createStream(frame, null, false, null);
+ IStream stream = createStream(frame, null, false, new Promise.Adapter<Stream>(){
+ @Override
+ public void failed(Throwable x)
+ {
+ LOG.debug("Received: {} but creating new Stream failed: {}", frame, x.getMessage());
+ }
+ });
if (stream != null)
processSyn(listener, stream, frame);
}
diff --git a/jetty-spdy/spdy-example-webapp/pom.xml b/jetty-spdy/spdy-example-webapp/pom.xml
index 0d5d8d5e56..3816599fd2 100644
--- a/jetty-spdy/spdy-example-webapp/pom.xml
+++ b/jetty-spdy/spdy-example-webapp/pom.xml
@@ -8,8 +8,8 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>spdy-example-webapp</artifactId>
<packaging>war</packaging>
- <name>Jetty :: SPDY :: Example Web Application</name>
-
+ <name>Jetty :: SPDY :: Jetty HTTP Web Application</name>
+ <url>http://www.eclipse.org/jetty</url>
<build>
<plugins>
<plugin>
diff --git a/jetty-spdy/spdy-http-server/src/main/config/etc/jetty-spdy.xml b/jetty-spdy/spdy-http-server/src/main/config/etc/jetty-spdy.xml
index feea74418c..b5d0a4c2fe 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/etc/jetty-spdy.xml
+++ b/jetty-spdy/spdy-http-server/src/main/config/etc/jetty-spdy.xml
@@ -103,7 +103,8 @@
<New class="org.eclipse.jetty.spdy.server.http.HTTPSPDYServerConnectionFactory">
<Arg name="version" type="int">3</Arg>
<Arg name="config"><Ref refid="sslHttpConfig" /></Arg>
- <Arg name="pushStrategy"><Ref refid="pushStrategy"/></Arg>
+ <!-- Uncomment to enable ReferrerPushStrategy -->
+ <!--<Arg name="pushStrategy"><Ref refid="pushStrategy"/></Arg>-->
</New>
</Item>
diff --git a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java
index b67bfffaa3..fc83aef1f4 100644
--- a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java
+++ b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java
@@ -23,7 +23,6 @@ import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.http.HttpField;
@@ -86,14 +85,14 @@ public class HttpTransportOverSPDY implements HttpTransport
return requestHeaders;
}
-
+
@Override
public void send(ByteBuffer responseBodyContent, boolean lastContent, Callback callback)
{
// TODO can this be more efficient?
- send(null,responseBodyContent, lastContent, callback);
+ send(null, responseBodyContent, lastContent, callback);
}
-
+
@Override
public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback)
{
@@ -306,7 +305,7 @@ public class HttpTransportOverSPDY implements HttpTransport
final Fields pushHeaders = createPushHeaders(scheme, host, pushResource);
final Fields pushRequestHeaders = createRequestHeaders(scheme, host, uri, pushResource);
- stream.push(new PushInfo(pushHeaders, false), new Promise.Adapter<Stream>()
+ stream.push(new PushInfo(pushHeaders, false), new Promise<Stream>()
{
@Override
public void succeeded(Stream pushStream)
@@ -315,6 +314,12 @@ public class HttpTransportOverSPDY implements HttpTransport
queue.offer(new PushResource(pushStream, pushRequestHeaders));
sendNextResourceData();
}
+
+ @Override
+ public void failed(Throwable x)
+ {
+ LOG.debug("Creating push stream failed.", x);
+ }
});
}
diff --git a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java
index ed0220c421..5b501fef8e 100644
--- a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java
+++ b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java
@@ -67,7 +67,6 @@ import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;
-@Ignore
public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
{
private static final Logger LOG = Log.getLogger(ReferrerPushStrategyTest.class);
@@ -260,6 +259,7 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
public void testPushResourceOrder() throws Exception
{
final CountDownLatch allExpectedPushesReceivedLatch = new CountDownLatch(4);
+ final CountDownLatch allPushDataReceivedLatch = new CountDownLatch(4);
Session pushCacheBuildSession = startClient(version, serverAddress, null);
@@ -296,12 +296,22 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
break;
}
allExpectedPushesReceivedLatch.countDown();
- return super.onPush(stream, pushInfo);
+ return new Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ if(dataInfo.isClose())
+ allPushDataReceivedLatch.countDown();
+ }
+ };
}
});
assertThat("All expected push resources have been received", allExpectedPushesReceivedLatch.await(5,
TimeUnit.SECONDS), is(true));
+ assertThat("All push data has been fully received", allPushDataReceivedLatch.await(5, TimeUnit.SECONDS),
+ is(true));
}
@Test
@@ -451,7 +461,6 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
private void sendRequest(Session session, Fields requestHeaders, final CountDownLatch pushSynHeadersValid,
final CountDownLatch pushDataLatch, final boolean resetPush) throws InterruptedException
{
- LOG.info("sendRequest. headers={},resetPush={}", requestHeaders, resetPush);
final CountDownLatch dataReceivedLatch = new CountDownLatch(1);
session.syn(new SynInfo(requestHeaders, true), new StreamFrameListener.Adapter()
{
@@ -496,7 +505,6 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
}
}, new Promise.Adapter<Stream>());
assertThat(dataReceivedLatch.await(5, TimeUnit.SECONDS), is(true));
- LOG.info("sendRequest done");
}
private void run2ndClientRequests(final boolean validateHeaders,
diff --git a/jetty-spdy/spdy-server/pom.xml b/jetty-spdy/spdy-server/pom.xml
index 5587da4ae3..a570389206 100644
--- a/jetty-spdy/spdy-server/pom.xml
+++ b/jetty-spdy/spdy-server/pom.xml
@@ -14,6 +14,7 @@
<bundle-symbolic-name>${project.groupId}.server</bundle-symbolic-name>
</properties>
+ <url>http://www.eclipse.org/jetty</url>
<build>
<plugins>
<plugin>
diff --git a/jetty-start/pom.xml b/jetty-start/pom.xml
index 93006dcfc4..9dfb9455c6 100644
--- a/jetty-start/pom.xml
+++ b/jetty-start/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-start</artifactId>
<name>Jetty :: Start</name>
<description>The start utility</description>
+ <url>http://www.eclipse.org/jetty</url>
<build>
<plugins>
<plugin>
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/PropertyDump.java b/jetty-start/src/test/java/org/eclipse/jetty/start/PropertyDump.java
new file mode 100644
index 0000000000..4928fc0e05
--- /dev/null
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/PropertyDump.java
@@ -0,0 +1,41 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.start;
+
+import java.util.Enumeration;
+import java.util.Properties;
+
+public class PropertyDump
+{
+ public static void main(String[] args)
+ {
+ Properties props = System.getProperties();
+ Enumeration<?> names = props.propertyNames();
+ while (names.hasMoreElements())
+ {
+ String name = (String)names.nextElement();
+ // only interested in "test." prefixed properties
+ if (name.startsWith("test."))
+ {
+ System.out.printf("%s=%s%n",name,props.getProperty(name));
+ }
+ }
+ System.exit(0);
+ }
+}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/PropertyPassingTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/PropertyPassingTest.java
new file mode 100644
index 0000000000..9275957109
--- /dev/null
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/PropertyPassingTest.java
@@ -0,0 +1,245 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.start;
+
+import static org.hamcrest.Matchers.*;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jetty.toolchain.test.IO;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.eclipse.jetty.toolchain.test.OS;
+import org.eclipse.jetty.toolchain.test.TestingDir;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class PropertyPassingTest
+{
+ private static class ConsoleCapture implements Runnable
+ {
+ private String mode;
+ private BufferedReader reader;
+ private StringWriter output;
+
+ public ConsoleCapture(String mode, InputStream is)
+ {
+ this.mode = mode;
+ this.reader = new BufferedReader(new InputStreamReader(is));
+ this.output = new StringWriter();
+ }
+
+ @Override
+ public void run()
+ {
+ String line;
+ try (PrintWriter out = new PrintWriter(output))
+ {
+ while ((line = reader.readLine()) != (null))
+ {
+ out.println(line);
+ }
+ }
+ catch (IOException ignore)
+ {
+ /* ignore */
+ }
+ finally
+ {
+ IO.close(reader);
+ }
+ }
+
+ public String getConsoleOutput()
+ {
+ return output.toString();
+ }
+
+ public ConsoleCapture start()
+ {
+ Thread thread = new Thread(this,"ConsoleCapture/" + mode);
+ thread.start();
+ return this;
+ }
+ }
+
+ @Rule
+ public TestingDir testingdir = new TestingDir();
+
+ @Test
+ public void testAsJvmArg() throws IOException, InterruptedException
+ {
+ File testCfg = MavenTestingUtils.getTestResourceFile("property-dump-start.config");
+ File bogusXml = MavenTestingUtils.getTestResourceFile("bogus.xml");
+
+ // Setup command line
+ List<String> commands = new ArrayList<>();
+ commands.add(getJavaBin());
+ commands.add("-cp");
+ commands.add(getClassPath());
+ // addDebug(commands);
+ commands.add("-Dtest.foo=bar"); // TESTING THIS
+ commands.add(getStartJarBin());
+ commands.add("--config=" + testCfg.getAbsolutePath());
+ commands.add(bogusXml.getAbsolutePath());
+
+ // Run command, collect output
+ String output = collectRunOutput(commands);
+
+ // Test for values
+ Assert.assertThat("output",output,containsString("foo=bar"));
+ }
+
+ @Test
+ @Ignore("not working yet")
+ public void testAsCommandLineArg() throws IOException, InterruptedException
+ {
+ File testCfg = MavenTestingUtils.getTestResourceFile("property-dump-start.config");
+ File bogusXml = MavenTestingUtils.getTestResourceFile("bogus.xml");
+
+ // Setup command line
+ List<String> commands = new ArrayList<>();
+ commands.add(getJavaBin());
+ commands.add("-cp");
+ commands.add(getClassPath());
+ // addDebug(commands);
+ commands.add(getStartJarBin());
+ commands.add("test.foo=bar"); // TESTING THIS
+ commands.add("--config=" + testCfg.getAbsolutePath());
+ commands.add(bogusXml.getAbsolutePath());
+
+ // Run command, collect output
+ String output = collectRunOutput(commands);
+
+ // Test for values
+ Assert.assertThat("output",output,containsString("foo=bar"));
+ }
+
+ @Test
+ public void testAsDashDCommandLineArg() throws IOException, InterruptedException
+ {
+ File testCfg = MavenTestingUtils.getTestResourceFile("property-dump-start.config");
+ File bogusXml = MavenTestingUtils.getTestResourceFile("bogus.xml");
+
+ // Setup command line
+ List<String> commands = new ArrayList<>();
+ commands.add(getJavaBin());
+ commands.add("-cp");
+ commands.add(getClassPath());
+ // addDebug(commands);
+ commands.add(getStartJarBin());
+ commands.add("-Dtest.foo=bar"); // TESTING THIS
+ commands.add("--config=" + testCfg.getAbsolutePath());
+ commands.add(bogusXml.getAbsolutePath());
+
+ // Run command, collect output
+ String output = collectRunOutput(commands);
+
+ // Test for values
+ Assert.assertThat("output",output,containsString("foo=bar"));
+ }
+
+ private String getClassPath()
+ {
+ StringBuilder cp = new StringBuilder();
+ String pathSep = System.getProperty("path.separator");
+ cp.append(MavenTestingUtils.getProjectDir("target/classes"));
+ cp.append(pathSep);
+ cp.append(MavenTestingUtils.getProjectDir("target/test-classes"));
+ return cp.toString();
+ }
+
+ protected void addDebug(List<String> commands)
+ {
+ commands.add("-Xdebug");
+ commands.add("-Xrunjdwp:server=y,transport=dt_socket,address=4000,suspend=y");
+ }
+
+ private String collectRunOutput(List<String> commands) throws IOException, InterruptedException
+ {
+ StringBuilder cline = new StringBuilder();
+ for (String command : commands)
+ {
+ cline.append(command).append(" ");
+ }
+ System.out.println("Command line: " + cline);
+
+ ProcessBuilder builder = new ProcessBuilder(commands);
+ Process pid = builder.start();
+
+ ConsoleCapture stdOutPump = new ConsoleCapture("STDOUT",pid.getInputStream()).start();
+ ConsoleCapture stdErrPump = new ConsoleCapture("STDERR",pid.getErrorStream()).start();
+
+ int exitCode = pid.waitFor();
+ if(exitCode != 0) {
+ System.out.printf("STDERR: [" + stdErrPump.getConsoleOutput() + "]%n");
+ System.out.printf("STDOUT: [" + stdOutPump.getConsoleOutput() + "]%n");
+ Assert.assertThat("Exit code",exitCode,is(0));
+ }
+ return stdOutPump.getConsoleOutput();
+ }
+
+ private String getStartJarBin()
+ {
+ return org.eclipse.jetty.start.Main.class.getName();
+ }
+
+ private String getJavaBin()
+ {
+ File javaHome = new File(System.getProperty("java.home"));
+ if (!javaHome.exists())
+ {
+ return null;
+ }
+
+ File javabin = findExecutable(javaHome,"bin/java");
+ if (javabin != null)
+ {
+ return javabin.getAbsolutePath();
+ }
+
+ javabin = findExecutable(javaHome,"bin/java.exe");
+ if (javabin != null)
+ {
+ return javabin.getAbsolutePath();
+ }
+
+ return "java";
+ }
+
+ private File findExecutable(File root, String path)
+ {
+ String npath = OS.separators(path);
+ File exe = new File(root,npath);
+ if (!exe.exists())
+ {
+ return null;
+ }
+ return exe;
+ }
+}
diff --git a/jetty-start/src/test/resources/bogus.xml b/jetty-start/src/test/resources/bogus.xml
new file mode 100644
index 0000000000..6660498d7f
--- /dev/null
+++ b/jetty-start/src/test/resources/bogus.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<Configure /> \ No newline at end of file
diff --git a/jetty-start/src/test/resources/property-dump-start.config b/jetty-start/src/test/resources/property-dump-start.config
new file mode 100644
index 0000000000..f38e5a426a
--- /dev/null
+++ b/jetty-start/src/test/resources/property-dump-start.config
@@ -0,0 +1,8 @@
+
+org.eclipse.jetty.start.PropertyDump.class
+
+[*]
+$(basedir)/src/test/resources
+
+[default]
+$(basedir)/src/test/resources
diff --git a/jetty-util-ajax/pom.xml b/jetty-util-ajax/pom.xml
index ac61d4a539..f566cf60a7 100644
--- a/jetty-util-ajax/pom.xml
+++ b/jetty-util-ajax/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-util-ajax</artifactId>
<name>Jetty :: Utilities :: Ajax(JSON)</name>
<description>JSON/Ajax Utility classes for Jetty</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.util.ajax</bundle-symbolic-name>
</properties>
diff --git a/jetty-util/pom.xml b/jetty-util/pom.xml
index ad39975cf1..217d9de12e 100644
--- a/jetty-util/pom.xml
+++ b/jetty-util/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-util</artifactId>
<name>Jetty :: Utilities</name>
<description>Utility classes for Jetty</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.util</bundle-symbolic-name>
</properties>
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java
index 85ee7a6327..198e9e747a 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java
@@ -84,7 +84,7 @@ import java.nio.charset.Charset;
*/
public class BufferUtil
{
- static final int TEMP_BUFFER_SIZE = 512;
+ static final int TEMP_BUFFER_SIZE = 4096;
static final byte SPACE = 0x20;
static final byte MINUS = '-';
static final byte[] DIGIT =
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/log/StacklessLogging.java b/jetty-util/src/main/java/org/eclipse/jetty/util/log/StacklessLogging.java
new file mode 100644
index 0000000000..8d7f2ebbe5
--- /dev/null
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/log/StacklessLogging.java
@@ -0,0 +1,69 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.util.log;
+
+/**
+ * A try-with-resources compatible layer for {@link StdErrLog#setHideStacks(boolean) hiding stacktraces} within the scope of the <code>try</code> block when
+ * logging with {@link StdErrLog} implementation.
+ * <p>
+ * Use of other logging implementation cause no effect when using this class
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * try (StacklessLogging scope = new StacklessLogging(EventDriver.class,Noisy.class))
+ * {
+ * doActionThatCausesStackTraces();
+ * }
+ * </pre>
+ */
+public class StacklessLogging implements AutoCloseable
+{
+ private final Class<?> clazzes[];
+
+ public StacklessLogging(Class<?>... classesToSquelch)
+ {
+ this.clazzes = classesToSquelch;
+ hideStacks(true);
+ }
+
+ @Override
+ public void close() throws Exception
+ {
+ hideStacks(false);
+ }
+
+ private void hideStacks(boolean hide)
+ {
+ for (Class<?> clazz : clazzes)
+ {
+ Logger log = Log.getLogger(clazz);
+ if (log == null)
+ {
+ // not interested in classes without loggers
+ continue;
+ }
+ if (log instanceof StdErrLog)
+ {
+ // only operate on loggers that are of type StdErrLog
+ ((StdErrLog)log).setHideStacks(hide);
+ }
+ }
+ }
+}
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java
index 6aa32877ea..0febc2423d 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java
@@ -157,9 +157,9 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo
int size = _threads.size();
if (size > 0)
{
- LOG.warn("{} threads could not be stopped", size);
-
- if ((size <= Runtime.getRuntime().availableProcessors()) || LOG.isDebugEnabled())
+ Thread.yield();
+
+ if (LOG.isDebugEnabled())
{
for (Thread unstopped : _threads)
{
@@ -171,6 +171,11 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo
LOG.warn("Couldn't stop {}{}", unstopped, dmp.toString());
}
}
+ else
+ {
+ for (Thread unstopped : _threads)
+ LOG.warn("{} Couldn't stop {}",this,unstopped);
+ }
}
synchronized (_joinLock)
diff --git a/jetty-webapp/pom.xml b/jetty-webapp/pom.xml
index cd6ff52255..77b3227207 100644
--- a/jetty-webapp/pom.xml
+++ b/jetty-webapp/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-webapp</artifactId>
<name>Jetty :: Webapp Application Support</name>
<description>Jetty web application support</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.webapp</bundle-symbolic-name>
</properties>
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
index 650c6a0873..4f37eae0d7 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
@@ -1083,6 +1083,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
}
+
/* ------------------------------------------------------------ */
/**
* @param extractWAR True if war files are extracted
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java
index aad8c963cd..776eecb132 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java
@@ -120,25 +120,13 @@ public class WebXmlConfiguration extends AbstractConfiguration
/* ------------------------------------------------------------------------------- */
@Override
public void deconfigure (WebAppContext context) throws Exception
- {
- // TODO preserve any configuration that pre-existed.
-
- ServletHandler _servletHandler = context.getServletHandler();
-
- _servletHandler.setFilters(null);
- _servletHandler.setFilterMappings(null);
- _servletHandler.setServlets(null);
- _servletHandler.setServletMappings(null);
-
- context.setEventListeners(null);
+ {
context.setWelcomeFiles(null);
if (context.getErrorHandler() instanceof ErrorPageErrorHandler)
((ErrorPageErrorHandler)
context.getErrorHandler()).setErrorPages(null);
-
// TODO remove classpaths from classloader
-
}
}
diff --git a/jetty-websocket/pom.xml b/jetty-websocket/pom.xml
index 3e85f43e80..e3f40f7e56 100644
--- a/jetty-websocket/pom.xml
+++ b/jetty-websocket/pom.xml
@@ -11,7 +11,8 @@
<artifactId>websocket-parent</artifactId>
<name>Jetty :: Websocket :: Parent</name>
<packaging>pom</packaging>
-
+ <url>http://www.eclipse.org/jetty</url>
+
<modules>
<module>websocket-common</module>
<module>websocket-api</module>
diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/UpgradeRequest.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/UpgradeRequest.java
index 07b16dae9c..e805f8614b 100644
--- a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/UpgradeRequest.java
+++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/UpgradeRequest.java
@@ -42,6 +42,7 @@ public class UpgradeRequest
private String httpVersion;
private String method;
private String host;
+ private boolean secure = false;
protected UpgradeRequest()
{
@@ -225,6 +226,11 @@ public class UpgradeRequest
return test.equalsIgnoreCase(getOrigin());
}
+ public boolean isSecure()
+ {
+ return secure;
+ }
+
public void setCookies(List<HttpCookie> cookies)
{
this.cookies = cookies;
@@ -261,6 +267,19 @@ public class UpgradeRequest
public void setRequestURI(URI uri)
{
this.requestURI = uri;
+ String scheme = uri.getScheme();
+ if ("ws".equalsIgnoreCase(scheme))
+ {
+ secure = false;
+ }
+ else if ("wss".equalsIgnoreCase(scheme))
+ {
+ secure = true;
+ }
+ else
+ {
+ throw new IllegalArgumentException("URI scheme must be 'ws' or 'wss'");
+ }
this.host = this.requestURI.getHost();
this.parameters.clear();
}
diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/util/WSURI.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/util/WSURI.java
new file mode 100644
index 0000000000..27073cc98b
--- /dev/null
+++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/util/WSURI.java
@@ -0,0 +1,145 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.websocket.api.util;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Objects;
+
+/**
+ * Utility methods for converting a {@link URI} between a HTTP(S) and WS(S) URI.
+ */
+public final class WSURI
+{
+ /**
+ * Convert to HTTP <code>http</code> or <code>https</code> scheme URIs.
+ * <p>
+ * Converting <code>ws</code> and <code>wss</code> URIs to their HTTP equivalent
+ *
+ * @param inputUri
+ * the input URI
+ * @return the HTTP scheme URI for the input URI.
+ * @throws URISyntaxException
+ * if unable to convert the input URI
+ */
+ public static URI toHttp(final URI inputUri) throws URISyntaxException
+ {
+ Objects.requireNonNull(inputUri,"Input URI must not be null");
+ String wsScheme = inputUri.getScheme();
+ String httpScheme = null;
+ if ("http".equalsIgnoreCase(wsScheme) || "https".equalsIgnoreCase(wsScheme))
+ {
+ // leave alone
+ httpScheme = wsScheme;
+ }
+ else if ("ws".equalsIgnoreCase(wsScheme))
+ {
+ // convert to http
+ httpScheme = "http";
+ }
+ else if ("wss".equalsIgnoreCase(wsScheme))
+ {
+ // convert to https
+ httpScheme = "https";
+ }
+ else
+ {
+ throw new URISyntaxException(inputUri.toString(),"Unrecognized WebSocket scheme");
+ }
+
+ return new URI(httpScheme,inputUri.getUserInfo(),inputUri.getHost(),inputUri.getPort(),inputUri.getPath(),inputUri.getQuery(),inputUri.getFragment());
+ }
+
+ /**
+ * Convert to WebSocket <code>ws</code> or <code>wss</code> scheme URIs
+ * <p>
+ * Converting <code>http</code> and <code>https</code> URIs to their WebSocket equivalent
+ *
+ * @param inputUrl
+ * the input URI
+ * @return the WebSocket scheme URI for the input URI.
+ * @throws URISyntaxException
+ * if unable to convert the input URI
+ */
+ public static URI toWebsocket(CharSequence inputUrl) throws URISyntaxException
+ {
+ return toWebsocket(new URI(inputUrl.toString()));
+ }
+
+ /**
+ * Convert to WebSocket <code>ws</code> or <code>wss</code> scheme URIs
+ * <p>
+ * Converting <code>http</code> and <code>https</code> URIs to their WebSocket equivalent
+ *
+ * @param inputUrl
+ * the input URI
+ * @param query
+ * the optional query string
+ * @return the WebSocket scheme URI for the input URI.
+ * @throws URISyntaxException
+ * if unable to convert the input URI
+ */
+ public static URI toWebsocket(CharSequence inputUrl, String query) throws URISyntaxException
+ {
+ if (query == null)
+ {
+ return toWebsocket(new URI(inputUrl.toString()));
+ }
+ return toWebsocket(new URI(inputUrl.toString() + '?' + query));
+ }
+
+ /**
+ * Convert to WebSocket <code>ws</code> or <code>wss</code> scheme URIs
+ *
+ * <p>
+ * Converting <code>http</code> and <code>https</code> URIs to their WebSocket equivalent
+ *
+ * @param inputUri
+ * the input URI
+ * @return the WebSocket scheme URI for the input URI.
+ * @throws URISyntaxException
+ * if unable to convert the input URI
+ */
+ public static URI toWebsocket(final URI inputUri) throws URISyntaxException
+ {
+ Objects.requireNonNull(inputUri,"Input URI must not be null");
+ String httpScheme = inputUri.getScheme();
+ String wsScheme = null;
+ if ("ws".equalsIgnoreCase(httpScheme) || "wss".equalsIgnoreCase(httpScheme))
+ {
+ // keep as-is
+ wsScheme = httpScheme;
+ }
+ else if ("http".equalsIgnoreCase(httpScheme))
+ {
+ // convert to ws
+ wsScheme = "ws";
+ }
+ else if ("https".equalsIgnoreCase(httpScheme))
+ {
+ // convert to wss
+ wsScheme = "wss";
+ }
+ else
+ {
+ throw new URISyntaxException(inputUri.toString(),"Unrecognized HTTP scheme");
+ }
+ return new URI(wsScheme,inputUri.getUserInfo(),inputUri.getHost(),inputUri.getPort(),inputUri.getPath(),inputUri.getQuery(),inputUri.getFragment());
+ }
+}
diff --git a/jetty-websocket/websocket-api/src/test/java/org/eclipse/jetty/websocket/api/util/WSURITest.java b/jetty-websocket/websocket-api/src/test/java/org/eclipse/jetty/websocket/api/util/WSURITest.java
new file mode 100644
index 0000000000..a4aac8ea61
--- /dev/null
+++ b/jetty-websocket/websocket-api/src/test/java/org/eclipse/jetty/websocket/api/util/WSURITest.java
@@ -0,0 +1,88 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.websocket.api.util;
+
+import static org.hamcrest.Matchers.*;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class WSURITest
+{
+ private void assertURI(URI actual, URI expected)
+ {
+ Assert.assertThat(actual.toASCIIString(),is(expected.toASCIIString()));
+ }
+
+ @Test
+ public void testHttpsToHttps() throws URISyntaxException
+ {
+ assertURI(WSURI.toHttp(URI.create("https://localhost/")),URI.create("https://localhost/"));
+ }
+
+ @Test
+ public void testHttpsToWss() throws URISyntaxException
+ {
+ assertURI(WSURI.toWebsocket(URI.create("https://localhost/")),URI.create("wss://localhost/"));
+ }
+
+ @Test
+ public void testHttpToHttp() throws URISyntaxException
+ {
+ assertURI(WSURI.toHttp(URI.create("http://localhost/")),URI.create("http://localhost/"));
+ }
+
+ @Test
+ public void testHttpToWs() throws URISyntaxException
+ {
+ assertURI(WSURI.toWebsocket(URI.create("http://localhost/")),URI.create("ws://localhost/"));
+ assertURI(WSURI.toWebsocket(URI.create("http://localhost:8080/deeper/")),URI.create("ws://localhost:8080/deeper/"));
+ assertURI(WSURI.toWebsocket("http://localhost/"),URI.create("ws://localhost/"));
+ assertURI(WSURI.toWebsocket("http://localhost/",null),URI.create("ws://localhost/"));
+ assertURI(WSURI.toWebsocket("http://localhost/","a=b"),URI.create("ws://localhost/?a=b"));
+ }
+
+ @Test
+ public void testWssToHttps() throws URISyntaxException
+ {
+ assertURI(WSURI.toHttp(URI.create("wss://localhost/")),URI.create("https://localhost/"));
+ }
+
+ @Test
+ public void testWssToWss() throws URISyntaxException
+ {
+ assertURI(WSURI.toWebsocket(URI.create("wss://localhost/")),URI.create("wss://localhost/"));
+ }
+
+ @Test
+ public void testWsToHttp() throws URISyntaxException
+ {
+ assertURI(WSURI.toHttp(URI.create("ws://localhost/")),URI.create("http://localhost/"));
+ }
+
+ @Test
+ public void testWsToWs() throws URISyntaxException
+ {
+ assertURI(WSURI.toWebsocket(URI.create("ws://localhost/")),URI.create("ws://localhost/"));
+ }
+
+}
diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/UpgradeConnection.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/UpgradeConnection.java
index c24a17b6f9..ca5a9fe2f2 100644
--- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/UpgradeConnection.java
+++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/UpgradeConnection.java
@@ -140,7 +140,7 @@ public class UpgradeConnection extends AbstractConnection
public void onOpen()
{
super.onOpen();
- // TODO: handle timeout
+ // TODO: handle timeout?
getExecutor().execute(new SendUpgradeRequest());
}
diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java
index e3f1669a54..b17008a7f6 100644
--- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java
+++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.concurrent.Executor;
+
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.io.ByteBufferPool;
@@ -87,7 +88,6 @@ public class WebSocketClientSelectorManager extends SelectorManager
Connection connection = newUpgradeConnection(channel,sslEndPoint,connectPromise);
sslEndPoint.setIdleTimeout(connectPromise.getClient().getMaxIdleTimeout());
sslEndPoint.setConnection(connection);
- connectionOpened(connection);
return sslConnection;
}
else
@@ -104,7 +104,7 @@ public class WebSocketClientSelectorManager extends SelectorManager
}
catch (IOException e)
{
- LOG.debug(e);
+ LOG.ignore(e);
connectPromise.failed(e);
// rethrow
throw e;
@@ -120,7 +120,7 @@ public class WebSocketClientSelectorManager extends SelectorManager
public SSLEngine newSSLEngine(SslContextFactory sslContextFactory, SocketChannel channel)
{
- String peerHost = channel.socket().getInetAddress().getHostAddress();
+ String peerHost = channel.socket().getInetAddress().getHostName();
int peerPort = channel.socket().getPort();
SSLEngine engine = sslContextFactory.newSSLEngine(peerHost,peerPort);
engine.setUseClientMode(true);
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 7ca103d5b2..282c05f026 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
@@ -245,11 +245,14 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
@Override
public RemoteEndpoint getRemote()
{
- if (!isOpen())
+ ConnectionState state = connection.getIOState().getConnectionState();
+
+ if ((state == ConnectionState.OPEN) || (state == ConnectionState.CONNECTED))
{
- throw new WebSocketException("Session has not been opened yet");
+ return remote;
}
- return remote;
+
+ throw new WebSocketException("RemoteEndpoint unavailable, current state [" + state + "], expecting [OPEN or CONNECTED]");
}
@Override
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriver.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriver.java
index d217937d47..5461df4188 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriver.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriver.java
@@ -163,7 +163,14 @@ public abstract class EventDriver implements IncomingFrames
{
LOG.debug("openSession({})",session);
this.session = session;
- this.onConnect();
+ try
+ {
+ this.onConnect();
+ }
+ catch (Throwable t)
+ {
+ unhandled(t);
+ }
}
protected void terminateConnection(int statusCode, String rawreason)
@@ -177,6 +184,7 @@ public abstract class EventDriver implements IncomingFrames
private void unhandled(Throwable t)
{
LOG.warn("Unhandled Error (closing connection)",t);
+ onError(t);
// Unhandled Error, close the connection.
switch (policy.getBehavior())
diff --git a/jetty-websocket/websocket-server/pom.xml b/jetty-websocket/websocket-server/pom.xml
index 6f9243bd78..6471390004 100644
--- a/jetty-websocket/websocket-server/pom.xml
+++ b/jetty-websocket/websocket-server/pom.xml
@@ -39,6 +39,11 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
+ <artifactId>websocket-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-servlet</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/HandshakeRFC6455.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/HandshakeRFC6455.java
index bd177d78cf..aee3a73aa1 100644
--- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/HandshakeRFC6455.java
+++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/HandshakeRFC6455.java
@@ -24,6 +24,8 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.common.AcceptHash;
+import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
+import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
/**
* WebSocket Handshake for <a href="https://tools.ietf.org/html/rfc6455">RFC 6455</a>.
@@ -34,7 +36,7 @@ public class HandshakeRFC6455 implements WebSocketHandshake
public static final int VERSION = 13;
@Override
- public void doHandshakeResponse(ServletWebSocketRequest request, ServletWebSocketResponse response) throws IOException
+ public void doHandshakeResponse(ServletUpgradeRequest request, ServletUpgradeResponse response) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketRequest.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketRequest.java
index e274c963ee..00f3b6265d 100644
--- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketRequest.java
+++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketRequest.java
@@ -18,242 +18,20 @@
package org.eclipse.jetty.websocket.server;
-import java.net.HttpCookie;
-import java.net.InetSocketAddress;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import java.net.URISyntaxException;
-import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
-import org.eclipse.jetty.websocket.api.UpgradeRequest;
-import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
-import org.eclipse.jetty.websocket.api.util.QuoteUtil;
+import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
-public class ServletWebSocketRequest extends UpgradeRequest
+/**
+ * @deprecated use {@link org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest} instead
+ */
+@Deprecated
+public class ServletWebSocketRequest extends ServletUpgradeRequest
{
- private HttpServletRequest req;
-
- public ServletWebSocketRequest(HttpServletRequest request)
- {
- super(request.getRequestURI());
- this.req = request;
-
- // Copy Request Line Details
- setMethod(request.getMethod());
- setHttpVersion(request.getProtocol());
-
- // Copy parameters
- super.setParameterMap(request.getParameterMap());
-
- // Copy Cookies
- Cookie rcookies[] = request.getCookies();
- if (rcookies != null)
- {
- List<HttpCookie> cookies = new ArrayList<>();
- for (Cookie rcookie : rcookies)
- {
- HttpCookie hcookie = new HttpCookie(rcookie.getName(),rcookie.getValue());
- // no point handling domain/path/expires/secure/httponly on client request cookies
- cookies.add(hcookie);
- }
- super.setCookies(cookies);
- }
-
- // Copy Headers
- Enumeration<String> headerNames = request.getHeaderNames();
- while (headerNames.hasMoreElements())
- {
- String name = headerNames.nextElement();
- Enumeration<String> valuesEnum = request.getHeaders(name);
- List<String> values = new ArrayList<>();
- while (valuesEnum.hasMoreElements())
- {
- values.add(valuesEnum.nextElement());
- }
- setHeader(name,values);
- }
-
- // Parse Sub Protocols
- Enumeration<String> protocols = request.getHeaders("Sec-WebSocket-Protocol");
- List<String> subProtocols = new ArrayList<>();
- String protocol = null;
- while ((protocol == null) && (protocols != null) && protocols.hasMoreElements())
- {
- String candidate = protocols.nextElement();
- for (String p : parseProtocols(candidate))
- {
- subProtocols.add(p);
- }
- }
- setSubProtocols(subProtocols);
-
- // Parse Extension Configurations
- Enumeration<String> e = request.getHeaders("Sec-WebSocket-Extensions");
- while (e.hasMoreElements())
- {
- Iterator<String> extTokenIter = QuoteUtil.splitAt(e.nextElement(),",");
- while (extTokenIter.hasNext())
- {
- String extToken = extTokenIter.next();
- ExtensionConfig config = ExtensionConfig.parse(extToken);
- addExtensions(config);
- }
- }
- }
-
- /**
- * Equivalent to {@link HttpServletRequest#getLocalAddr()}
- *
- * @return the local address
- */
- public String getLocalAddress()
- {
- return req.getLocalAddr();
- }
-
- /**
- * Equivalent to {@link HttpServletRequest#getLocalName()}
- *
- * @return the local host name
- */
- public String getLocalHostName()
- {
- return req.getLocalName();
- }
-
- /**
- * Equivalent to {@link HttpServletRequest#getLocalPort()}
- *
- * @return the local port
- */
- public int getLocalPort()
- {
- return req.getLocalPort();
- }
-
- /**
- * Return a {@link InetSocketAddress} for the local socket.
- * <p>
- * Warning: this can cause a DNS lookup
- *
- * @return the local socket address
- */
- public InetSocketAddress getLocalSocketAddress()
- {
- return new InetSocketAddress(req.getLocalAddr(),req.getLocalPort());
- }
-
- public Principal getPrincipal()
- {
- return req.getUserPrincipal();
- }
-
- /**
- * Equivalent to {@link HttpServletRequest#getRemoteAddr()}
- *
- * @return the remote address
- */
- public String getRemoteAddress()
- {
- return req.getRemoteAddr();
- }
-
- /**
- * Equivalent to {@link HttpServletRequest#getRemoteHost()}
- *
- * @return the remote host name
- */
- public String getRemoteHostName()
- {
- return req.getRemoteHost();
- }
-
- /**
- * Equivalent to {@link HttpServletRequest#getRemotePort()}
- *
- * @return the remote port
- */
- public int getRemotePort()
- {
- return req.getRemotePort();
- }
-
- /**
- * Return a {@link InetSocketAddress} for the remote socket.
- * <p>
- * Warning: this can cause a DNS lookup
- *
- * @return the remote socket address
- */
- public InetSocketAddress getRemoteSocketAddress()
- {
- return new InetSocketAddress(req.getRemoteAddr(),req.getRemotePort());
- }
-
- public Map<String, Object> getServletAttributes()
- {
- Map<String, Object> attributes = new HashMap<String, Object>();
-
- for (String name : Collections.list(req.getAttributeNames()))
- {
- attributes.put(name,req.getAttribute(name));
- }
-
- return attributes;
- }
-
- public Map<String, List<String>> getServletParameters()
- {
- Map<String, List<String>> parameters = new HashMap<String, List<String>>();
-
- for (String name : Collections.list(req.getParameterNames()))
- {
- parameters.put(name,Collections.unmodifiableList(Arrays.asList(req.getParameterValues(name))));
- }
-
- return parameters;
- }
-
- /**
- * Return the HttpSession if it exists.
- * <p>
- * Note: this is equivalent to {@link HttpServletRequest#getSession()} and will not create a new HttpSession.
- */
- @Override
- public Object getSession()
- {
- return this.req.getSession(false);
- }
-
- protected String[] parseProtocols(String protocol)
- {
- if (protocol == null)
- {
- return new String[]
- { null };
- }
- protocol = protocol.trim();
- if ((protocol == null) || (protocol.length() == 0))
- {
- return new String[]
- { null };
- }
- String[] passed = protocol.split("\\s*,\\s*");
- String[] protocols = new String[passed.length + 1];
- System.arraycopy(passed,0,protocols,0,passed.length);
- return protocols;
- }
-
- public void setServletAttribute(String name, Object o)
+ public ServletWebSocketRequest(HttpServletRequest request) throws URISyntaxException
{
- this.req.setAttribute(name,o);
+ super(request);
}
}
diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketResponse.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketResponse.java
index 0bf797ed0f..609c810d50 100644
--- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketResponse.java
+++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/ServletWebSocketResponse.java
@@ -18,66 +18,18 @@
package org.eclipse.jetty.websocket.server;
-import java.io.IOException;
-
import javax.servlet.http.HttpServletResponse;
-import org.eclipse.jetty.websocket.api.UpgradeResponse;
+import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
-public class ServletWebSocketResponse extends UpgradeResponse
+/**
+ * @deprecated use {@link org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse} instead
+ */
+@Deprecated
+public class ServletWebSocketResponse extends ServletUpgradeResponse
{
- private HttpServletResponse resp;
-
public ServletWebSocketResponse(HttpServletResponse resp)
{
- super();
- this.resp = resp;
- }
-
- @Override
- public void addHeader(String name, String value)
- {
- this.resp.addHeader(name,value);
- }
-
- @Override
- public int getStatusCode()
- {
- return this.resp.getStatus();
- }
-
- @Override
- public String getStatusReason()
- {
- throw new UnsupportedOperationException("Server cannot get Status Reason Message");
- }
-
- public boolean isCommitted()
- {
- return this.resp.isCommitted();
- }
-
- public void sendError(int statusCode, String message) throws IOException
- {
- setSuccess(false);
- this.resp.sendError(statusCode,message);
- }
-
- @Override
- public void sendForbidden(String message) throws IOException
- {
- setSuccess(false);
- resp.sendError(HttpServletResponse.SC_FORBIDDEN,message);
- }
-
- @Override
- public void setHeader(String name, String value)
- {
- this.resp.setHeader(name,value);
- }
-
- public void setStatus(int status)
- {
- this.resp.setStatus(status);
+ super(resp);
}
}
diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketHandshake.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketHandshake.java
index b41ab7f55f..e7f6fb6abe 100644
--- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketHandshake.java
+++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketHandshake.java
@@ -20,6 +20,9 @@ package org.eclipse.jetty.websocket.server;
import java.io.IOException;
+import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
+import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
+
public interface WebSocketHandshake
{
/**
@@ -29,5 +32,5 @@ public interface WebSocketHandshake
* @param response
* @param acceptedSubProtocol
*/
- public void doHandshakeResponse(ServletWebSocketRequest request, ServletWebSocketResponse response) throws IOException;
+ public void doHandshakeResponse(ServletUpgradeRequest request, ServletUpgradeResponse response) throws IOException;
}
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 edffd2f172..badda0c084 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
@@ -19,6 +19,7 @@
package org.eclipse.jetty.websocket.server;
import java.io.IOException;
+import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -27,6 +28,7 @@ import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -51,6 +53,8 @@ import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
import org.eclipse.jetty.websocket.common.extensions.ExtensionStack;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
+import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
+import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@@ -134,38 +138,45 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
@Override
public boolean acceptWebSocket(HttpServletRequest request, HttpServletResponse response) throws IOException
{
- ServletWebSocketRequest sockreq = new ServletWebSocketRequest(request);
- ServletWebSocketResponse sockresp = new ServletWebSocketResponse(response);
+ try
+ {
+ ServletUpgradeRequest sockreq = new ServletUpgradeRequest(request);
+ ServletUpgradeResponse sockresp = new ServletUpgradeResponse(response);
- WebSocketCreator creator = getCreator();
+ WebSocketCreator creator = getCreator();
- UpgradeContext context = getActiveUpgradeContext();
- if (context == null)
- {
- context = new UpgradeContext();
- setActiveUpgradeContext(context);
- }
- context.setRequest(sockreq);
- context.setResponse(sockresp);
+ UpgradeContext context = getActiveUpgradeContext();
+ if (context == null)
+ {
+ context = new UpgradeContext();
+ setActiveUpgradeContext(context);
+ }
+ context.setRequest(sockreq);
+ context.setResponse(sockresp);
- Object websocketPojo = creator.createWebSocket(sockreq,sockresp);
+ Object websocketPojo = creator.createWebSocket(sockreq,sockresp);
- // Handle response forbidden (and similar paths)
- if (sockresp.isCommitted())
- {
- return false;
- }
+ // Handle response forbidden (and similar paths)
+ if (sockresp.isCommitted())
+ {
+ return false;
+ }
- if (websocketPojo == null)
+ if (websocketPojo == null)
+ {
+ // no creation, sorry
+ response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
+ return false;
+ }
+
+ // Send the upgrade
+ EventDriver driver = eventDriverFactory.wrap(websocketPojo);
+ return upgrade(sockreq,sockresp,driver);
+ }
+ catch (URISyntaxException e)
{
- // no creation, sorry
- response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
- return false;
+ throw new IOException("Unable to accept websocket due to mangled URI",e);
}
-
- // Send the upgrade
- EventDriver driver = eventDriverFactory.wrap(websocketPojo);
- return upgrade(sockreq,sockresp,driver);
}
@Override
@@ -307,7 +318,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
/*
* (non-Javadoc)
- *
+ *
* @see org.eclipse.jetty.websocket.server.WebSocketServletFactory#register(java.lang.Class)
*/
@Override
@@ -348,7 +359,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
* <p>
* This method will not normally return, but will instead throw a UpgradeConnectionException, to exit HTTP handling and initiate WebSocket handling of the
* connection.
- *
+ *
* @param request
* The request to upgrade
* @param response
@@ -357,7 +368,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
* The websocket handler implementation to use
* @throws IOException
*/
- public boolean upgrade(ServletWebSocketRequest request, ServletWebSocketResponse response, EventDriver driver) throws IOException
+ public boolean upgrade(ServletUpgradeRequest request, ServletUpgradeResponse response, EventDriver driver) throws IOException
{
if (!"websocket".equalsIgnoreCase(request.getHeader("Upgrade")))
{
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/RequestHeadersTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/RequestHeadersTest.java
index 49866d30ff..b28d79f7f6 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/RequestHeadersTest.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/RequestHeadersTest.java
@@ -57,6 +57,7 @@ public class RequestHeadersTest
return lastRequest;
}
+ @SuppressWarnings("unused")
public UpgradeResponse getLastResponse()
{
return lastResponse;
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SimpleServletServer.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SimpleServletServer.java
index ea9fe44d3a..5304e5f41f 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SimpleServletServer.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SimpleServletServer.java
@@ -19,35 +19,95 @@
package org.eclipse.jetty.websocket.server;
import java.net.URI;
+
import javax.servlet.http.HttpServlet;
-import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
public class SimpleServletServer
{
+ private static final Logger LOG = Log.getLogger(SimpleServletServer.class);
private Server server;
private ServerConnector connector;
private URI serverUri;
private HttpServlet servlet;
+ private boolean ssl = false;
+ private SslContextFactory sslContextFactory;
public SimpleServletServer(HttpServlet servlet)
{
this.servlet = servlet;
}
+ public void enableSsl(boolean ssl)
+ {
+ this.ssl = ssl;
+ }
+
public URI getServerUri()
{
return serverUri;
}
+ public SslContextFactory getSslContextFactory()
+ {
+ return sslContextFactory;
+ }
+
+ public boolean isSslEnabled()
+ {
+ return ssl;
+ }
+
public void start() throws Exception
{
// Configure Server
server = new Server();
- connector = new ServerConnector(server);
+ if (ssl)
+ {
+ // HTTP Configuration
+ HttpConfiguration http_config = new HttpConfiguration();
+ http_config.setSecureScheme("https");
+ http_config.setSecurePort(0);
+ http_config.setOutputBufferSize(32768);
+ http_config.setRequestHeaderSize(8192);
+ http_config.setResponseHeaderSize(8192);
+ http_config.setSendServerVersion(true);
+ http_config.setSendDateHeader(false);
+
+ sslContextFactory = new SslContextFactory();
+ sslContextFactory.setKeyStorePath(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath());
+ sslContextFactory.setKeyStorePassword("storepwd");
+ sslContextFactory.setKeyManagerPassword("keypwd");
+ sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA","SSL_DHE_RSA_WITH_DES_CBC_SHA","SSL_DHE_DSS_WITH_DES_CBC_SHA",
+ "SSL_RSA_EXPORT_WITH_RC4_40_MD5","SSL_RSA_EXPORT_WITH_DES40_CBC_SHA","SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
+
+ // SSL HTTP Configuration
+ HttpConfiguration https_config = new HttpConfiguration(http_config);
+ https_config.addCustomizer(new SecureRequestCustomizer());
+
+ // SSL Connector
+ connector = new ServerConnector(server,new SslConnectionFactory(sslContextFactory,"http/1.1"),new HttpConnectionFactory(https_config));
+ connector.setPort(0);
+ }
+ else
+ {
+ // Basic HTTP connector
+ connector = new ServerConnector(server);
+ connector.setPort(0);
+ }
server.addConnector(connector);
ServletContextHandler context = new ServletContextHandler();
@@ -60,13 +120,20 @@ public class SimpleServletServer
// Start Server
server.start();
+ // Establish the Server URI
String host = connector.getHost();
if (host == null)
{
host = "localhost";
}
int port = connector.getLocalPort();
- serverUri = new URI(String.format("ws://%s:%d/",host,port));
+ serverUri = new URI(String.format("%s://%s:%d/",ssl?"wss":"ws",host,port));
+
+ // Some debugging
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug(server.dump());
+ }
}
public void stop()
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java
index 00c001bcd2..aafdea8946 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java
@@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.log.StacklessLogging;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
@@ -36,6 +37,7 @@ import org.eclipse.jetty.websocket.api.WebSocketAdapter;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
+import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.server.blockhead.BlockheadClient;
import org.eclipse.jetty.websocket.server.helper.IncomingFramesCapture;
import org.eclipse.jetty.websocket.server.helper.RFCSocket;
@@ -52,6 +54,30 @@ import org.junit.Test;
*/
public class WebSocketCloseTest
{
+ static class AbstractCloseSocket extends WebSocketAdapter
+ {
+ public CountDownLatch closeLatch = new CountDownLatch(1);
+ public String closeReason = null;
+ public int closeStatusCode = -1;
+ public List<Throwable> errors = new ArrayList<>();
+
+ @Override
+ public void onWebSocketClose(int statusCode, String reason)
+ {
+ LOG.debug("onWebSocketClose({}, {})",statusCode,reason);
+ this.closeStatusCode = statusCode;
+ this.closeReason = reason;
+ closeLatch.countDown();
+ }
+
+ @Override
+ public void onWebSocketError(Throwable cause)
+ {
+ errors.add(cause);
+ }
+
+ }
+
@SuppressWarnings("serial")
public static class CloseServlet extends WebSocketServlet implements WebSocketCreator
{
@@ -66,28 +92,25 @@ public class WebSocketCloseTest
{
if (req.hasSubProtocol("fastclose"))
{
- fastcloseSocket = new FastCloseSocket();
- return fastcloseSocket;
+ closeSocket = new FastCloseSocket();
+ return closeSocket;
+ }
+
+ if (req.hasSubProtocol("fastfail"))
+ {
+ closeSocket = new FastFailSocket();
+ return closeSocket;
}
return new RFCSocket();
}
}
- public static class FastCloseSocket extends WebSocketAdapter
+ /**
+ * On Connect, close socket
+ */
+ public static class FastCloseSocket extends AbstractCloseSocket
{
- public CountDownLatch closeLatch = new CountDownLatch(1);
- public String closeReason = null;
- public int closeStatusCode = -1;
- public List<Throwable> errors = new ArrayList<>();
-
- @Override
- public void onWebSocketClose(int statusCode, String reason)
- {
- LOG.debug("onWebSocketClose({}, {})",statusCode,reason);
- this.closeStatusCode = statusCode;
- this.closeReason = reason;
- closeLatch.countDown();
- }
+ private static final Logger LOG = Log.getLogger(WebSocketCloseTest.FastCloseSocket.class);
@Override
public void onWebSocketConnect(Session sess)
@@ -102,6 +125,21 @@ public class WebSocketCloseTest
e.printStackTrace(System.err);
}
}
+ }
+
+ /**
+ * On Connect, throw unhandled exception
+ */
+ public static class FastFailSocket extends AbstractCloseSocket
+ {
+ private static final Logger LOG = Log.getLogger(WebSocketCloseTest.FastFailSocket.class);
+
+ @Override
+ public void onWebSocketConnect(Session sess)
+ {
+ LOG.debug("onWebSocketConnect({})",sess);
+ throw new RuntimeException("Intentional FastFail");
+ }
@Override
public void onWebSocketError(Throwable cause)
@@ -111,8 +149,9 @@ public class WebSocketCloseTest
}
private static final Logger LOG = Log.getLogger(WebSocketCloseTest.class);
+
private static SimpleServletServer server;
- private static FastCloseSocket fastcloseSocket;
+ private static AbstractCloseSocket closeSocket;
@BeforeClass
public static void startServer() throws Exception
@@ -150,8 +189,44 @@ public class WebSocketCloseTest
client.write(close.asFrame()); // respond with close
- Assert.assertThat("Fast Close Latch",fastcloseSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true));
- Assert.assertThat("Fast Close.statusCode",fastcloseSocket.closeStatusCode,is(StatusCode.NORMAL));
+ Assert.assertThat("Fast Close Latch",closeSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true));
+ Assert.assertThat("Fast Close.statusCode",closeSocket.closeStatusCode,is(StatusCode.NORMAL));
+ }
+ finally
+ {
+ client.close();
+ }
+ }
+
+ /**
+ * Test fast fail (bug #410537)
+ */
+ @Test
+ public void testFastFail() throws Exception
+ {
+ BlockheadClient client = new BlockheadClient(server.getServerUri());
+ client.setProtocols("fastfail");
+ client.setTimeout(TimeUnit.SECONDS,1);
+ try
+ {
+ try (StacklessLogging scope = new StacklessLogging(EventDriver.class))
+ {
+ client.connect();
+ client.sendStandardRequest();
+ client.expectUpgradeResponse();
+
+ IncomingFramesCapture capture = client.readFrames(1,TimeUnit.SECONDS,1);
+ WebSocketFrame frame = capture.getFrames().poll();
+ Assert.assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.CLOSE));
+ CloseInfo close = new CloseInfo(frame);
+ Assert.assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.SERVER_ERROR));
+
+ client.write(close.asFrame()); // respond with close
+
+ Assert.assertThat("Fast Fail Latch",closeSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true));
+ Assert.assertThat("Fast Fail.statusCode",closeSocket.closeStatusCode,is(StatusCode.SERVER_ERROR));
+ Assert.assertThat("Fast Fail.errors",closeSocket.errors.size(),is(1));
+ }
}
finally
{
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketLoadRFC6455Test.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketLoadRFC6455Test.java
deleted file mode 100644
index fec70b0b2d..0000000000
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketLoadRFC6455Test.java
+++ /dev/null
@@ -1,222 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.server;
-
-import static org.junit.Assert.*;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.lang.management.ManagementFactory;
-import java.net.Socket;
-import java.nio.ByteBuffer;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jetty.io.ByteBufferPool;
-import org.eclipse.jetty.io.EndPoint;
-import org.eclipse.jetty.io.MappedByteBufferPool;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.handler.DefaultHandler;
-import org.eclipse.jetty.util.thread.QueuedThreadPool;
-import org.eclipse.jetty.websocket.api.WebSocketBehavior;
-import org.eclipse.jetty.websocket.api.WebSocketException;
-import org.eclipse.jetty.websocket.api.WebSocketPolicy;
-import org.eclipse.jetty.websocket.api.extensions.Frame;
-import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
-import org.eclipse.jetty.websocket.common.Generator;
-import org.eclipse.jetty.websocket.common.Parser;
-import org.eclipse.jetty.websocket.common.WebSocketFrame;
-import org.eclipse.jetty.websocket.server.examples.MyEchoSocket;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-
-public class WebSocketLoadRFC6455Test
-{
- private class WebSocketClient implements Runnable
- {
- private final Socket socket;
- private final BufferedWriter output;
- private final BufferedReader input;
- private final int iterations;
- private final CountDownLatch latch;
- private/* final */EndPoint _endp;
- private final Generator _generator;
- private final Parser _parser;
- private final IncomingFrames _handler = new IncomingFrames()
- {
- @Override
- public void incomingError(WebSocketException e)
- {
- }
-
- @Override
- public void incomingFrame(Frame frame)
- {
- }
- };
- private volatile ByteBuffer _response;
-
- public WebSocketClient(String host, int port, int readTimeout, CountDownLatch latch, int iterations) throws IOException
- {
- this.latch = latch;
- socket = new Socket(host,port);
- socket.setSoTimeout(readTimeout);
- output = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"ISO-8859-1"));
- input = new BufferedReader(new InputStreamReader(socket.getInputStream(),"ISO-8859-1"));
- this.iterations = iterations;
-
- WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT);
-
- // _endp=new SocketEndPoint(socket);
- ByteBufferPool bufferPool = new MappedByteBufferPool();
- _generator = new Generator(policy,bufferPool);
- _parser = new Parser(policy,bufferPool);
-
- }
-
- public void close() throws IOException
- {
- socket.close();
- }
-
- private void open() throws IOException
- {
- output.write("GET /chat HTTP/1.1\r\n" + "Host: server.example.com\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n"
- + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Origin: http://example.com\r\n"
- + "Sec-WebSocket-Protocol: onConnect\r\n" + "Sec-WebSocket-Version: 7\r\n" + "\r\n");
- output.flush();
-
- String responseLine = input.readLine();
- assertTrue(responseLine.startsWith("HTTP/1.1 101 Switching Protocols"));
- // Read until we find an empty line, which signals the end of the http response
- String line;
- while ((line = input.readLine()) != null)
- {
- if (line.length() == 0)
- {
- break;
- }
- }
- }
-
- @Override
- public void run()
- {
- try
- {
- String message = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
- for (int i = 0; i < iterations; ++i)
- {
- WebSocketFrame txt = WebSocketFrame.text(message);
- ByteBuffer buf = _generator.generate(txt);
-
- // TODO: Send it
- // TODO: Receive response
-
- Assert.assertEquals(message,_response.toString());
- latch.countDown();
- }
- }
- catch (Throwable x)
- {
- throw new RuntimeException(x);
- }
- }
- }
-
- private static Server _server;
-
- private static ServerConnector _connector;
-
- @BeforeClass
- public static void startServer() throws Exception
- {
- QueuedThreadPool threadPool = new QueuedThreadPool(200);
- threadPool.setStopTimeout(1000);
- _server = new Server(threadPool);
- _server.manage(threadPool);
-
- _connector = new ServerConnector(_server);
- _server.addConnector(_connector);
-
- WebSocketHandler wsHandler = new WebSocketHandler.Simple(MyEchoSocket.class);
- wsHandler.setHandler(new DefaultHandler());
- _server.setHandler(wsHandler);
-
- _server.start();
- }
-
- @AfterClass
- public static void stopServer() throws Exception
- {
- _server.stop();
- _server.join();
- }
-
- @Test
- @Ignore("Not yet converted to new jetty-9 structure")
- public void testLoad() throws Exception
- {
- int count = 50;
- int iterations = 100;
-
- ExecutorService threadPool = Executors.newCachedThreadPool();
- try
- {
- CountDownLatch latch = new CountDownLatch(count * iterations);
- WebSocketClient[] clients = new WebSocketClient[count];
- for (int i = 0; i < clients.length; ++i)
- {
- clients[i] = new WebSocketClient("localhost",_connector.getLocalPort(),1000,latch,iterations);
- clients[i].open();
- }
-
- // long start = System.nanoTime();
- for (WebSocketClient client : clients)
- {
- threadPool.execute(client);
- }
-
- int parallelism = ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors();
- long maxTimePerIteration = 5;
- assertTrue(latch.await(iterations * ((count / parallelism) + 1) * maxTimePerIteration,TimeUnit.MILLISECONDS));
- // long end = System.nanoTime();
- // System.err.println("Elapsed: " + TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
-
- for (WebSocketClient client : clients)
- {
- client.close();
- }
- }
- finally
- {
- threadPool.shutdown();
- assertTrue(threadPool.awaitTermination(2,TimeUnit.SECONDS));
- }
- }
-}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java
index 56218c50d9..4297ca1bc8 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java
@@ -18,155 +18,145 @@
package org.eclipse.jetty.websocket.server;
-import java.util.Arrays;
-import java.util.concurrent.CountDownLatch;
+import static org.hamcrest.Matchers.*;
+
+import java.net.URI;
+import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.toolchain.test.EventQueue;
import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.WebSocketAdapter;
-import org.eclipse.jetty.websocket.server.examples.MyEchoSocket;
-import org.junit.After;
+import org.eclipse.jetty.websocket.client.WebSocketClient;
+import org.eclipse.jetty.websocket.server.helper.CaptureSocket;
+import org.eclipse.jetty.websocket.server.helper.SessionServlet;
+import org.junit.AfterClass;
import org.junit.Assert;
-import org.junit.Ignore;
+import org.junit.BeforeClass;
import org.junit.Test;
public class WebSocketOverSSLTest
{
- private Server _server;
- private int _port;
- private QueuedThreadPool _threadPool;
+ private static SimpleServletServer server;
+
+ @BeforeClass
+ public static void startServer() throws Exception
+ {
+ server = new SimpleServletServer(new SessionServlet());
+ server.enableSsl(true);
+ server.start();
+ }
- private Session _session;
+ @AfterClass
+ public static void stopServer()
+ {
+ server.stop();
+ }
- @After
- public void destroy() throws Exception
+ /**
+ * Test the requirement of issuing socket and receiving echo response
+ */
+ @Test
+ public void testEcho() throws Exception
{
- if (_session != null)
+ Assert.assertThat("server scheme",server.getServerUri().getScheme(),is("wss"));
+ WebSocketClient client = new WebSocketClient(server.getSslContextFactory());
+ try
{
- _session.close();
- }
+ client.start();
- // if (_wsFactory != null)
- // _wsFactory.stop();
+ CaptureSocket clientSocket = new CaptureSocket();
+ Future<Session> fut = client.connect(clientSocket,server.getServerUri());
- if (_threadPool != null)
- {
- _threadPool.stop();
- }
+ // wait for connect
+ Session session = fut.get(1,TimeUnit.SECONDS);
+
+ // Generate text frame
+ String msg = "this is an echo ... cho ... ho ... o";
+ session.getRemote().sendString(msg);
+
+ // Read frame (hopefully text frame)
+ clientSocket.messages.awaitEventCount(1,500,TimeUnit.MILLISECONDS);
+ EventQueue<String> captured = clientSocket.messages;
+ Assert.assertThat("Text Message",captured.poll(),is(msg));
- if (_server != null)
+ // Shutdown the socket
+ clientSocket.close();
+ }
+ finally
{
- _server.stop();
- _server.join();
+ client.stop();
}
}
- private void startClient(final Object webSocket) throws Exception
+ /**
+ * Test that server session reports as secure
+ */
+ @Test
+ public void testServerSessionIsSecure() throws Exception
{
- Assert.assertTrue(_server.isStarted());
+ Assert.assertThat("server scheme",server.getServerUri().getScheme(),is("wss"));
+ WebSocketClient client = new WebSocketClient(server.getSslContextFactory());
+ try
+ {
+ client.start();
- _threadPool = new QueuedThreadPool();
- _threadPool.setName("wsc-" + _threadPool.getName());
- _threadPool.start();
+ CaptureSocket clientSocket = new CaptureSocket();
+ Future<Session> fut = client.connect(clientSocket,server.getServerUri());
- // _wsFactory = new WebSocketClientFactory(_threadPool, new ZeroMasker());
- // SslContextFactory cf = _wsFactory.getSslContextFactory();
- // cf.setKeyStorePath(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath());
- // cf.setKeyStorePassword("storepwd");
- // cf.setKeyManagerPassword("keypwd");
- // _wsFactory.start();
+ // wait for connect
+ Session session = fut.get(3,TimeUnit.SECONDS);
- // WebSocketClient client = new WebSocketClient(_wsFactory);
- // _connection = client.open(new URI("wss://localhost:" + _port), webSocket).get(5, TimeUnit.SECONDS);
- }
+ // Generate text frame
+ session.getRemote().sendString("session.isSecure");
- private void startServer(final Object websocket) throws Exception
- {
- SslContextFactory sslContextFactory = new SslContextFactory();
- sslContextFactory.setKeyStorePath(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath());
- sslContextFactory.setKeyStorePassword("storepwd");
- sslContextFactory.setKeyManagerPassword("keypwd");
- _server = new Server();
- ServerConnector connector = new ServerConnector(_server,sslContextFactory);
- _server.addConnector(connector);
- _server.setHandler(new WebSocketHandler.Simple(websocket.getClass()));
- _server.start();
- _port = connector.getLocalPort();
- }
+ // Read frame (hopefully text frame)
+ clientSocket.messages.awaitEventCount(1,500,TimeUnit.MILLISECONDS);
+ EventQueue<String> captured = clientSocket.messages;
+ Assert.assertThat("Server.session.isSecure",captured.poll(),is("session.isSecure=true"));
- @Test
- @Ignore("SSL Not yet implemented")
- public void testManyMessages() throws Exception
- {
- startServer(MyEchoSocket.class);
- int count = 1000;
- final CountDownLatch clientLatch = new CountDownLatch(count);
- startClient(new WebSocketAdapter()
- {
- @Override
- public void onWebSocketText(String message)
- {
- clientLatch.countDown();
- }
- });
-
- char[] chars = new char[256];
- Arrays.fill(chars,'x');
- String message = new String(chars);
- for (int i = 0; i < count; ++i)
+ // Shutdown the socket
+ clientSocket.close();
+ }
+ finally
{
- _session.getRemote().sendStringByFuture(message);
+ client.stop();
}
-
- Assert.assertTrue(clientLatch.await(20,TimeUnit.SECONDS));
-
- // While messages may have all arrived, the SSL close alert
- // may be in the way so give some time for it to be processed.
- TimeUnit.SECONDS.sleep(1);
}
+ /**
+ * Test that server session.upgradeRequest.requestURI reports correctly
+ */
@Test
- @Ignore("SSL Not yet implemented")
- public void testWebSocketOverSSL() throws Exception
+ public void testServerSessionRequestURI() throws Exception
{
- final String message = "message";
- final CountDownLatch serverLatch = new CountDownLatch(1);
- startServer(new WebSocketAdapter()
+ Assert.assertThat("server scheme",server.getServerUri().getScheme(),is("wss"));
+ WebSocketClient client = new WebSocketClient(server.getSslContextFactory());
+ try
{
- private Session session;
-
- @Override
- public void onWebSocketConnect(Session session)
- {
- this.session = session;
- }
-
- @Override
- public void onWebSocketText(String message)
- {
- Assert.assertEquals(message,message);
- session.getRemote().sendStringByFuture(message);
- serverLatch.countDown();
- }
- });
- final CountDownLatch clientLatch = new CountDownLatch(1);
- startClient(new WebSocketAdapter()
+ client.start();
+
+ CaptureSocket clientSocket = new CaptureSocket();
+ URI requestUri = server.getServerUri().resolve("/deep?a=b");
+ Future<Session> fut = client.connect(clientSocket,requestUri);
+
+ // wait for connect
+ Session session = fut.get(3,TimeUnit.SECONDS);
+
+ // Generate text frame
+ session.getRemote().sendString("session.upgradeRequest.requestURI");
+
+ // Read frame (hopefully text frame)
+ clientSocket.messages.awaitEventCount(1,500,TimeUnit.MILLISECONDS);
+ EventQueue<String> captured = clientSocket.messages;
+ String expected = String.format("session.upgradeRequest.requestURI=%s",requestUri.toASCIIString());
+ Assert.assertThat("session.upgradeRequest.requestURI",captured.poll(),is(expected));
+
+ // Shutdown the socket
+ clientSocket.close();
+ }
+ finally
{
- @Override
- public void onWebSocketText(String data)
- {
- Assert.assertEquals(message,data);
- clientLatch.countDown();
- }
- });
- _session.getRemote().sendStringByFuture(message);
-
- Assert.assertTrue(serverLatch.await(5,TimeUnit.SECONDS));
- Assert.assertTrue(clientLatch.await(5,TimeUnit.SECONDS));
+ client.stop();
+ }
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java
index 8ca6db30d5..7d94243657 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java
@@ -163,7 +163,7 @@ public class WebSocketServletRFCTest
}
/**
- * Test the requirement of issuing
+ * Test the requirement of issuing socket and receiving echo response
*/
@Test
public void testEcho() throws Exception
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java
index fcb40ffe70..4b1f7358a0 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java
@@ -55,6 +55,7 @@ import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
+import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.common.AcceptHash;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.ConnectionState;
@@ -128,9 +129,12 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames, Connecti
if (destWebsocketURI.getScheme().equals("wss"))
{
scheme = "https";
+ throw new RuntimeException("Sorry, BlockheadClient does not support SSL");
}
- this.destHttpURI = new URI(scheme,destWebsocketURI.getUserInfo(),destWebsocketURI.getHost(),destWebsocketURI.getPort(),destWebsocketURI.getPath(),
- destWebsocketURI.getQuery(),destWebsocketURI.getFragment());
+ this.destHttpURI = WSURI.toHttp(destWebsocketURI);
+
+ LOG.debug("WebSocket URI: {}",destWebsocketURI);
+ LOG.debug(" HTTP URI: {}",destHttpURI);
this.bufferPool = new MappedByteBufferPool(8192);
this.generator = new Generator(policy,bufferPool);
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClientConstructionTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClientConstructionTest.java
index c1e1d502bf..5a384911ed 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClientConstructionTest.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClientConstructionTest.java
@@ -18,6 +18,8 @@
package org.eclipse.jetty.websocket.server.blockhead;
+import static org.hamcrest.Matchers.*;
+
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
@@ -30,8 +32,6 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
-import static org.hamcrest.Matchers.is;
-
/**
* Gotta test some basic constructors of the BlockheadClient.
*/
@@ -47,7 +47,6 @@ public class BlockheadClientConstructionTest
data.add(new Object[] { "ws://localhost:8080/", "http://localhost:8080/" });
data.add(new Object[] { "ws://webtide.com/", "http://webtide.com/" });
data.add(new Object[] { "ws://www.webtide.com/sockets/chat", "http://www.webtide.com/sockets/chat" });
- data.add(new Object[] { "wss://dummy.eclipse.org:5454/", "https://dummy.eclipse.org:5454/" });
// @formatter:on
return data;
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/CaptureSocket.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/CaptureSocket.java
index 3f03daf519..847d9c85e8 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/CaptureSocket.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/CaptureSocket.java
@@ -18,22 +18,22 @@
package org.eclipse.jetty.websocket.server.helper;
+import java.io.IOException;
import java.sql.Connection;
-import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import org.eclipse.jetty.toolchain.test.EventQueue;
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
public class CaptureSocket extends WebSocketAdapter
{
private final CountDownLatch latch = new CountDownLatch(1);
- public List<String> messages;
+ public EventQueue<String> messages;
public CaptureSocket()
{
- messages = new ArrayList<String>();
+ messages = new EventQueue<String>();
}
public boolean awaitConnected(long timeout) throws InterruptedException
@@ -41,6 +41,18 @@ public class CaptureSocket extends WebSocketAdapter
return latch.await(timeout,TimeUnit.MILLISECONDS);
}
+ public void close()
+ {
+ try
+ {
+ getSession().close();
+ }
+ catch (IOException ignore)
+ {
+ /* ignore */
+ }
+ }
+
public void onClose(int closeCode, String message)
{
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/SessionSocket.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/SessionSocket.java
index bbfc3c5da2..9c00b8ab8e 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/SessionSocket.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/SessionSocket.java
@@ -81,6 +81,20 @@ public class SessionSocket
return;
}
+ if ("session.isSecure".equals(message))
+ {
+ String issecure = String.format("session.isSecure=%b",session.isSecure());
+ session.getRemote().sendStringByFuture(issecure);
+ return;
+ }
+
+ if ("session.upgradeRequest.requestURI".equals(message))
+ {
+ String response = String.format("session.upgradeRequest.requestURI=%s",session.getUpgradeRequest().getRequestURI().toASCIIString());
+ session.getRemote().sendStringByFuture(response);
+ return;
+ }
+
if ("harsh-disconnect".equals(message))
{
session.disconnect();
diff --git a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/ServletUpgradeRequest.java b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/ServletUpgradeRequest.java
new file mode 100644
index 0000000000..fd739e0b51
--- /dev/null
+++ b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/ServletUpgradeRequest.java
@@ -0,0 +1,269 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.websocket.servlet;
+
+import java.net.HttpCookie;
+import java.net.InetSocketAddress;
+import java.net.URISyntaxException;
+import java.security.Principal;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.jetty.websocket.api.UpgradeRequest;
+import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
+import org.eclipse.jetty.websocket.api.util.QuoteUtil;
+import org.eclipse.jetty.websocket.api.util.WSURI;
+
+/**
+ * Servlet specific {@link UpgradeRequest} implementation.
+ */
+public class ServletUpgradeRequest extends UpgradeRequest
+{
+ private HttpServletRequest req;
+
+ public ServletUpgradeRequest(HttpServletRequest request) throws URISyntaxException
+ {
+ super(WSURI.toWebsocket(request.getRequestURL(),request.getQueryString()));
+ this.req = request;
+
+ // Copy Request Line Details
+ setMethod(request.getMethod());
+ setHttpVersion(request.getProtocol());
+
+ // Copy parameters
+ super.setParameterMap(request.getParameterMap());
+
+ // Copy Cookies
+ Cookie rcookies[] = request.getCookies();
+ if (rcookies != null)
+ {
+ List<HttpCookie> cookies = new ArrayList<>();
+ for (Cookie rcookie : rcookies)
+ {
+ HttpCookie hcookie = new HttpCookie(rcookie.getName(),rcookie.getValue());
+ // no point handling domain/path/expires/secure/httponly on client request cookies
+ cookies.add(hcookie);
+ }
+ super.setCookies(cookies);
+ }
+
+ // Copy Headers
+ Enumeration<String> headerNames = request.getHeaderNames();
+ while (headerNames.hasMoreElements())
+ {
+ String name = headerNames.nextElement();
+ Enumeration<String> valuesEnum = request.getHeaders(name);
+ List<String> values = new ArrayList<>();
+ while (valuesEnum.hasMoreElements())
+ {
+ values.add(valuesEnum.nextElement());
+ }
+ setHeader(name,values);
+ }
+
+ // Parse Sub Protocols
+ Enumeration<String> protocols = request.getHeaders("Sec-WebSocket-Protocol");
+ List<String> subProtocols = new ArrayList<>();
+ String protocol = null;
+ while ((protocol == null) && (protocols != null) && protocols.hasMoreElements())
+ {
+ String candidate = protocols.nextElement();
+ for (String p : parseProtocols(candidate))
+ {
+ subProtocols.add(p);
+ }
+ }
+ setSubProtocols(subProtocols);
+
+ // Parse Extension Configurations
+ Enumeration<String> e = request.getHeaders("Sec-WebSocket-Extensions");
+ while (e.hasMoreElements())
+ {
+ Iterator<String> extTokenIter = QuoteUtil.splitAt(e.nextElement(),",");
+ while (extTokenIter.hasNext())
+ {
+ String extToken = extTokenIter.next();
+ ExtensionConfig config = ExtensionConfig.parse(extToken);
+ addExtensions(config);
+ }
+ }
+ }
+
+ public X509Certificate[] getCertificates()
+ {
+ return (X509Certificate[])req.getAttribute("javax.servlet.request.X509Certificate");
+ }
+
+ /**
+ * Equivalent to {@link HttpServletRequest#getLocalAddr()}
+ *
+ * @return the local address
+ */
+ public String getLocalAddress()
+ {
+ return req.getLocalAddr();
+ }
+
+ /**
+ * Equivalent to {@link HttpServletRequest#getLocalName()}
+ *
+ * @return the local host name
+ */
+ public String getLocalHostName()
+ {
+ return req.getLocalName();
+ }
+
+ /**
+ * Equivalent to {@link HttpServletRequest#getLocalPort()}
+ *
+ * @return the local port
+ */
+ public int getLocalPort()
+ {
+ return req.getLocalPort();
+ }
+
+ /**
+ * Return a {@link InetSocketAddress} for the local socket.
+ * <p>
+ * Warning: this can cause a DNS lookup
+ *
+ * @return the local socket address
+ */
+ public InetSocketAddress getLocalSocketAddress()
+ {
+ return new InetSocketAddress(req.getLocalAddr(),req.getLocalPort());
+ }
+
+ public Principal getPrincipal()
+ {
+ return req.getUserPrincipal();
+ }
+
+ /**
+ * Equivalent to {@link HttpServletRequest#getRemoteAddr()}
+ *
+ * @return the remote address
+ */
+ public String getRemoteAddress()
+ {
+ return req.getRemoteAddr();
+ }
+
+ /**
+ * Equivalent to {@link HttpServletRequest#getRemoteHost()}
+ *
+ * @return the remote host name
+ */
+ public String getRemoteHostName()
+ {
+ return req.getRemoteHost();
+ }
+
+ /**
+ * Equivalent to {@link HttpServletRequest#getRemotePort()}
+ *
+ * @return the remote port
+ */
+ public int getRemotePort()
+ {
+ return req.getRemotePort();
+ }
+
+ /**
+ * Return a {@link InetSocketAddress} for the remote socket.
+ * <p>
+ * Warning: this can cause a DNS lookup
+ *
+ * @return the remote socket address
+ */
+ public InetSocketAddress getRemoteSocketAddress()
+ {
+ return new InetSocketAddress(req.getRemoteAddr(),req.getRemotePort());
+ }
+
+ public Map<String, Object> getServletAttributes()
+ {
+ Map<String, Object> attributes = new HashMap<String, Object>();
+
+ for (String name : Collections.list(req.getAttributeNames()))
+ {
+ attributes.put(name,req.getAttribute(name));
+ }
+
+ return attributes;
+ }
+
+ public Map<String, List<String>> getServletParameters()
+ {
+ Map<String, List<String>> parameters = new HashMap<String, List<String>>();
+
+ for (String name : Collections.list(req.getParameterNames()))
+ {
+ parameters.put(name,Collections.unmodifiableList(Arrays.asList(req.getParameterValues(name))));
+ }
+
+ return parameters;
+ }
+
+ /**
+ * Return the HttpSession if it exists.
+ * <p>
+ * Note: this is equivalent to {@link HttpServletRequest#getSession()} and will not create a new HttpSession.
+ */
+ @Override
+ public Object getSession()
+ {
+ return this.req.getSession(false);
+ }
+
+ protected String[] parseProtocols(String protocol)
+ {
+ if (protocol == null)
+ {
+ return new String[] {};
+ }
+ protocol = protocol.trim();
+ if ((protocol == null) || (protocol.length() == 0))
+ {
+ return new String[] {};
+ }
+ String[] passed = protocol.split("\\s*,\\s*");
+ String[] protocols = new String[passed.length];
+ System.arraycopy(passed,0,protocols,0,passed.length);
+ return protocols;
+ }
+
+ public void setServletAttribute(String name, Object o)
+ {
+ this.req.setAttribute(name,o);
+ }
+
+}
diff --git a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/ServletUpgradeResponse.java b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/ServletUpgradeResponse.java
new file mode 100644
index 0000000000..c7b50dc8be
--- /dev/null
+++ b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/ServletUpgradeResponse.java
@@ -0,0 +1,87 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.websocket.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.websocket.api.UpgradeResponse;
+
+/**
+ * Servlet Specific UpgradeResponse implementation.
+ */
+public class ServletUpgradeResponse extends UpgradeResponse
+{
+ private HttpServletResponse resp;
+
+ public ServletUpgradeResponse(HttpServletResponse resp)
+ {
+ super();
+ this.resp = resp;
+ }
+
+ @Override
+ public void addHeader(String name, String value)
+ {
+ this.resp.addHeader(name,value);
+ }
+
+ @Override
+ public int getStatusCode()
+ {
+ return this.resp.getStatus();
+ }
+
+ @Override
+ public String getStatusReason()
+ {
+ throw new UnsupportedOperationException("Server cannot get Status Reason Message");
+ }
+
+ public boolean isCommitted()
+ {
+ return this.resp.isCommitted();
+ }
+
+ public void sendError(int statusCode, String message) throws IOException
+ {
+ setSuccess(false);
+ this.resp.sendError(statusCode,message);
+ }
+
+ @Override
+ public void sendForbidden(String message) throws IOException
+ {
+ setSuccess(false);
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN,message);
+ }
+
+ @Override
+ public void setHeader(String name, String value)
+ {
+ this.resp.setHeader(name,value);
+ }
+
+ public void setStatus(int status)
+ {
+ this.resp.setStatus(status);
+ }
+
+}
diff --git a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketCreator.java b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketCreator.java
index 69a36502b0..aa3d1627cc 100644
--- a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketCreator.java
+++ b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketCreator.java
@@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.servlet;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;
+import org.eclipse.jetty.websocket.api.extensions.Extension;
/**
* Abstract WebSocket creator interface.
@@ -34,9 +35,16 @@ public interface WebSocketCreator
{
/**
* Create a websocket from the incoming request.
+ * <p>
+ * Note: if you have Servlet specific information you need to access from the UpgradeRequest, cast the {@link UpgradeRequest} to
+ * {@link ServletUpgradeRequest} for this extra information.
+ * <p>
+ * Future versions of this interface will change to use the Servlet specific Upgrade Request and Response parameters.
*
* @param req
* the request details
+ * @param resp
+ * the response details
* @return a websocket object to use, or null if no websocket should be created from this request.
*/
Object createWebSocket(UpgradeRequest req, UpgradeResponse resp);
diff --git a/jetty-xml/pom.xml b/jetty-xml/pom.xml
index 3864188454..781436126f 100644
--- a/jetty-xml/pom.xml
+++ b/jetty-xml/pom.xml
@@ -8,6 +8,7 @@
<artifactId>jetty-xml</artifactId>
<name>Jetty :: XML utilities</name>
<description>The jetty xml utilities.</description>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.xml</bundle-symbolic-name>
</properties>
diff --git a/pom.xml b/pom.xml
index 09f198c78f..ec91a0fba6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,12 +8,12 @@
<artifactId>jetty-project</artifactId>
<version>9.1.0-SNAPSHOT</version>
<name>Jetty :: Project</name>
- <url>${jetty.url}</url>
+ <url>http://www.eclipse.org/jetty</url>
<packaging>pom</packaging>
<properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jetty.url>http://www.eclipse.org/jetty</jetty.url>
<orbit-servlet-api-version>3.0.0.v201112011016</orbit-servlet-api-version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<build-support-version>1.1</build-support-version>
<slf4j-version>1.6.1</slf4j-version>
<jetty-test-policy-version>1.2</jetty-test-policy-version>
@@ -748,5 +748,30 @@
</plugins>
</build>
</profile>
+ <profile>
+ <id>api-change</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>clirr-maven-plugin</artifactId>
+ <version>2.5</version>
+ <executions>
+ <execution>
+ <id>compare-api</id>
+ <phase>package</phase>
+ <goals>
+ <goal>clirr</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <minSeverity>info</minSeverity>
+ <comparisonVersion>9.0.3.v20130506</comparisonVersion>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
</profiles>
</project>
diff --git a/test-continuation-jetty6/pom.xml b/test-continuation-jetty6/pom.xml
new file mode 100644
index 0000000000..9f7f4e1f1d
--- /dev/null
+++ b/test-continuation-jetty6/pom.xml
@@ -0,0 +1,64 @@
+<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</groupId>
+ <artifactId>jetty-project</artifactId>
+ <version>7.6.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>test-continuation-jetty6</artifactId>
+ <packaging>jar</packaging>
+ <name>Test :: Continuation - (Jetty 6)</name>
+ <description>Asynchronous API</description>
+ <url>http://www.eclipse.org/jetty</url>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <!-- DO NOT DEPLOY (or Release) -->
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>test-continuation</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty</artifactId>
+ <version>6.1.26</version>
+ <type>jar</type>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>servlet-api-2.5</artifactId>
+ <groupId>org.mortbay.jetty</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlets</artifactId>
+ <version>${project.version}</version>
+ <type>jar</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/test-continuation/pom.xml b/test-continuation/pom.xml
new file mode 100644
index 0000000000..9abbc299c2
--- /dev/null
+++ b/test-continuation/pom.xml
@@ -0,0 +1,38 @@
+<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</groupId>
+ <artifactId>jetty-project</artifactId>
+ <version>7.6.11-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>test-continuation</artifactId>
+ <packaging>jar</packaging>
+ <name>Test :: Continuation</name>
+ <description>Asynchronous API</description>
+ <url>http://www.eclipse.org/jetty</url>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <!-- DO NOT DEPLOY (or Release) -->
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/test-jetty-servlet/pom.xml b/test-jetty-servlet/pom.xml
new file mode 100644
index 0000000000..a04abf7acd
--- /dev/null
+++ b/test-jetty-servlet/pom.xml
@@ -0,0 +1,24 @@
+<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</groupId>
+ <artifactId>jetty-project</artifactId>
+ <version>7.6.11-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>test-jetty-servlet</artifactId>
+ <packaging>jar</packaging>
+ <name>Test :: Jetty Servlet Tester</name>
+ <url>http://www.eclipse.org/jetty</url>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tests/pom.xml b/tests/pom.xml
index f4deb814da..c71bd23b53 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -27,6 +27,7 @@
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>tests-parent</artifactId>
<name>Jetty Tests :: Parent</name>
+ <url>http://www.eclipse.org/jetty</url>
<packaging>pom</packaging>
<build>
<plugins>
diff --git a/tests/test-integration/pom.xml b/tests/test-integration/pom.xml
index 35311f6ee1..fb5784a6e9 100644
--- a/tests/test-integration/pom.xml
+++ b/tests/test-integration/pom.xml
@@ -26,6 +26,7 @@
<artifactId>test-integration</artifactId>
<packaging>jar</packaging>
<name>Jetty Tests :: Integrations</name>
+ <url>http://www.eclipse.org/jetty</url>
<properties>
<test-wars-dir>${project.build.directory}/test-wars</test-wars-dir>
<test-libs-dir>${project.build.directory}/test-libs</test-libs-dir>
diff --git a/tests/test-loginservice/pom.xml b/tests/test-loginservice/pom.xml
index ffbdf27dc6..4cc8782adb 100644
--- a/tests/test-loginservice/pom.xml
+++ b/tests/test-loginservice/pom.xml
@@ -25,6 +25,7 @@
</parent>
<artifactId>test-loginservice</artifactId>
<name>Jetty Tests :: Login Service</name>
+ <url>http://www.eclipse.org/jetty</url>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
diff --git a/tests/test-sessions/pom.xml b/tests/test-sessions/pom.xml
index ba7813d547..a499af03d5 100644
--- a/tests/test-sessions/pom.xml
+++ b/tests/test-sessions/pom.xml
@@ -25,6 +25,7 @@
</parent>
<artifactId>test-sessions-parent</artifactId>
<name>Jetty Tests :: Sessions :: Parent</name>
+ <url>http://www.eclipse.org/jetty</url>
<packaging>pom</packaging>
<build>
</build>
diff --git a/tests/test-sessions/test-hash-sessions/pom.xml b/tests/test-sessions/test-hash-sessions/pom.xml
index c8e740a0f4..c71dcc3325 100644
--- a/tests/test-sessions/test-hash-sessions/pom.xml
+++ b/tests/test-sessions/test-hash-sessions/pom.xml
@@ -25,6 +25,7 @@
</parent>
<artifactId>test-hash-sessions</artifactId>
<name>Jetty Tests :: Sessions :: Hash</name>
+ <url>http://www.eclipse.org/jetty</url>
<build>
<plugins>
<plugin>
diff --git a/tests/test-sessions/test-jdbc-sessions/pom.xml b/tests/test-sessions/test-jdbc-sessions/pom.xml
index 21ba6eb3cc..9dab39c9de 100644
--- a/tests/test-sessions/test-jdbc-sessions/pom.xml
+++ b/tests/test-sessions/test-jdbc-sessions/pom.xml
@@ -25,6 +25,7 @@
</parent>
<artifactId>test-jdbc-sessions</artifactId>
<name>Jetty Tests :: Sessions :: JDBC</name>
+ <url>http://www.eclipse.org/jetty</url>
<build>
<plugins>
<plugin>
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReloadedSessionMissingClassTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReloadedSessionMissingClassTest.java
index 05ca117513..c34bb6b012 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReloadedSessionMissingClassTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReloadedSessionMissingClassTest.java
@@ -113,7 +113,6 @@ public class ReloadedSessionMissingClassTest
webApp.stop();
webApp.setClassLoader(loaderWithoutFoo);
- webApp.addServlet("Bar", "/bar");
//restart webapp
webApp.start();
diff --git a/tests/test-sessions/test-mongodb-sessions/pom.xml b/tests/test-sessions/test-mongodb-sessions/pom.xml
index 44c3ed9793..5e83b2a3a0 100644
--- a/tests/test-sessions/test-mongodb-sessions/pom.xml
+++ b/tests/test-sessions/test-mongodb-sessions/pom.xml
@@ -25,6 +25,7 @@
</parent>
<artifactId>test-mongodb-sessions</artifactId>
<name>Jetty Tests :: Sessions :: Mongo</name>
+ <url>http://www.eclipse.org/jetty</url>
<build>
<plugins>
<plugin>
diff --git a/tests/test-sessions/test-mongodb-sessions/src/test/resources/jetty-logging.properties b/tests/test-sessions/test-mongodb-sessions/src/test/resources/jetty-logging.properties
new file mode 100644
index 0000000000..fd2d21f974
--- /dev/null
+++ b/tests/test-sessions/test-mongodb-sessions/src/test/resources/jetty-logging.properties
@@ -0,0 +1,4 @@
+# Setup default logging implementation for during testing
+org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
+
+#org.eclipse.jetty.server.LEVEL=DEBUG \ No newline at end of file
diff --git a/tests/test-sessions/test-sessions-common/pom.xml b/tests/test-sessions/test-sessions-common/pom.xml
index d79e4f3ecf..d5aa814ad4 100644
--- a/tests/test-sessions/test-sessions-common/pom.xml
+++ b/tests/test-sessions/test-sessions-common/pom.xml
@@ -25,6 +25,7 @@
</parent>
<artifactId>test-sessions-common</artifactId>
<name>Jetty Tests :: Sessions :: Common</name>
+ <url>http://www.eclipse.org/jetty</url>
<build>
</build>
<dependencies>
diff --git a/tests/test-webapps/pom.xml b/tests/test-webapps/pom.xml
index 320da49f60..74a820efb1 100644
--- a/tests/test-webapps/pom.xml
+++ b/tests/test-webapps/pom.xml
@@ -26,6 +26,7 @@
</parent>
<artifactId>test-webapps-parent</artifactId>
<name>Jetty Tests :: WebApps :: Parent</name>
+ <url>http://www.eclipse.org/jetty</url>
<packaging>pom</packaging>
<build>
<plugins>
diff --git a/tests/test-webapps/test-jetty-webapp/pom.xml b/tests/test-webapps/test-jetty-webapp/pom.xml
index 7068937e46..fb957fa209 100644
--- a/tests/test-webapps/test-jetty-webapp/pom.xml
+++ b/tests/test-webapps/test-jetty-webapp/pom.xml
@@ -27,6 +27,7 @@
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-webapp</artifactId>
<name>Test :: Jetty Test Webapp</name>
+ <url>http://www.eclipse.org/jetty</url>
<packaging>war</packaging>
<build>
<plugins>
diff --git a/tests/test-webapps/test-jetty-webapp/src/main/java/com/acme/ChatServlet.java b/tests/test-webapps/test-jetty-webapp/src/main/java/com/acme/ChatServlet.java
index 42040f56fd..dabfacd81c 100644
--- a/tests/test-webapps/test-jetty-webapp/src/main/java/com/acme/ChatServlet.java
+++ b/tests/test-webapps/test-jetty-webapp/src/main/java/com/acme/ChatServlet.java
@@ -19,13 +19,11 @@
package com.acme;
import java.io.IOException;
-import java.io.PrintWriter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicReference;
-
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
@@ -34,57 +32,70 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
// Simple asynchronous Chat room.
// This does not handle duplicate usernames or multiple frames/tabs from the same browser
// Some code is duplicated for clarity.
@SuppressWarnings("serial")
public class ChatServlet extends HttpServlet
{
+ private static final Logger LOG = Log.getLogger(ChatServlet.class);
+
+ private long asyncTimeout = 10000;
+
+ public void init()
+ {
+ String parameter = getServletConfig().getInitParameter("asyncTimeout");
+ if (parameter != null)
+ asyncTimeout = Long.parseLong(parameter);
+ }
// inner class to hold message queue for each chat room member
class Member implements AsyncListener
{
final String _name;
- final AtomicReference<AsyncContext> _async=new AtomicReference<>();
- final Queue<String> _queue = new LinkedList<String>();
-
+ final AtomicReference<AsyncContext> _async = new AtomicReference<>();
+ final Queue<String> _queue = new LinkedList<>();
+
Member(String name)
{
- _name=name;
+ _name = name;
}
-
+
@Override
public void onTimeout(AsyncEvent event) throws IOException
{
+ LOG.debug("resume request");
AsyncContext async = _async.get();
- if (async!=null && _async.compareAndSet(async,null))
+ if (async != null && _async.compareAndSet(async, null))
{
HttpServletResponse response = (HttpServletResponse)async.getResponse();
response.setContentType("text/json;charset=utf-8");
- PrintWriter out=response.getWriter();
- out.print("{action:\"poll\"}");
+ response.getOutputStream().write("{action:\"poll\"}".getBytes());
async.complete();
}
}
-
+
@Override
public void onStartAsync(AsyncEvent event) throws IOException
{
event.getAsyncContext().addListener(this);
}
-
+
@Override
public void onError(AsyncEvent event) throws IOException
{
}
-
+
@Override
public void onComplete(AsyncEvent event) throws IOException
{
}
}
- Map<String,Map<String,Member>> _rooms = new HashMap<String,Map<String, Member>>();
+ Map<String, Map<String, Member>> _rooms = new HashMap<>();
// Handle Ajax calls from browser
@@ -92,113 +103,119 @@ public class ChatServlet extends HttpServlet
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// Ajax calls are form encoded
- String action = request.getParameter("action");
+ boolean join = Boolean.parseBoolean(request.getParameter("join"));
String message = request.getParameter("message");
String username = request.getParameter("user");
- if (action.equals("join"))
- join(request,response,username);
- else if (action.equals("poll"))
- poll(request,response,username);
- else if (action.equals("chat"))
- chat(request,response,username,message);
- }
+ LOG.debug("doPost called. join={},message={},username={}", join, message, username);
+ if (username == null)
+ {
+ LOG.debug("no paramter user set, sending 503");
+ response.sendError(503, "user==null");
+ return;
+ }
- private synchronized void join(HttpServletRequest request,HttpServletResponse response,String username)
- throws IOException
- {
- Member member = new Member(username);
- Map<String,Member> room=_rooms.get(request.getPathInfo());
- if (room==null)
+ Map<String, Member> room = getRoom(request.getPathInfo());
+ Member member = getMember(username, room);
+
+ if (message != null)
{
- room=new HashMap<String,Member>();
- _rooms.put(request.getPathInfo(),room);
+ sendMessageToAllMembers(message, username, room);
+ }
+ // If a message is set, we only want to enter poll mode if the user is a new user. This is necessary to avoid
+ // two parallel requests per user (one is already in async wait and the new one). Sending a message will
+ // dispatch to an existing poll request if necessary and the client will issue a new request to receive the
+ // next message or long poll again.
+ if (message == null || join)
+ {
+ synchronized (member)
+ {
+ LOG.debug("Queue size: {}", member._queue.size());
+ if (member._queue.size() > 0)
+ {
+ sendSingleMessage(response, member);
+ }
+ else
+ {
+ LOG.debug("starting async");
+ AsyncContext async = request.startAsync();
+ async.setTimeout(asyncTimeout);
+ async.addListener(member);
+ if (!member._async.compareAndSet(null, async))
+ throw new IllegalStateException();
+ }
+ }
}
- room.put(username,member);
- response.setContentType("text/json;charset=utf-8");
- PrintWriter out=response.getWriter();
- out.print("{action:\"join\"}");
}
- private synchronized void poll(HttpServletRequest request,HttpServletResponse response,String username)
- throws IOException
+ private Member getMember(String username, Map<String, Member> room)
{
- Map<String,Member> room=_rooms.get(request.getPathInfo());
- if (room==null)
+ Member member = room.get(username);
+ if (member == null)
{
- response.sendError(503);
- return;
+ LOG.debug("user: {} in room: {} doesn't exist. Creating new user.", username, room);
+ member = new Member(username);
+ room.put(username, member);
}
- final Member member = room.get(username);
- if (member==null)
+ return member;
+ }
+
+ private Map<String, Member> getRoom(String path)
+ {
+ Map<String, Member> room = _rooms.get(path);
+ if (room == null)
{
- response.sendError(503);
- return;
+ LOG.debug("room: {} doesn't exist. Creating new room.", path);
+ room = new HashMap<>();
+ _rooms.put(path, room);
}
+ return room;
+ }
- synchronized(member)
- {
- if (member._queue.size()>0)
- {
- // Send one chat message
- response.setContentType("text/json;charset=utf-8");
- StringBuilder buf=new StringBuilder();
+ private void sendSingleMessage(HttpServletResponse response, Member member) throws IOException
+ {
+ response.setContentType("text/json;charset=utf-8");
+ StringBuilder buf = new StringBuilder();
- buf.append("{\"action\":\"poll\",");
- buf.append("\"from\":\"");
- buf.append(member._queue.poll());
- buf.append("\",");
+ buf.append("{\"from\":\"");
+ buf.append(member._queue.poll());
+ buf.append("\",");
- String message = member._queue.poll();
- int quote=message.indexOf('"');
- while (quote>=0)
- {
- message=message.substring(0,quote)+'\\'+message.substring(quote);
- quote=message.indexOf('"',quote+2);
- }
- buf.append("\"chat\":\"");
- buf.append(message);
- buf.append("\"}");
- byte[] bytes = buf.toString().getBytes("utf-8");
- response.setContentLength(bytes.length);
- response.getOutputStream().write(bytes);
- }
- else
- {
- AsyncContext async = request.startAsync();
- async.setTimeout(10000);
- async.addListener(member);
- if (!member._async.compareAndSet(null,async))
- throw new IllegalStateException();
- }
+ String returnMessage = member._queue.poll();
+ int quote = returnMessage.indexOf('"');
+ while (quote >= 0)
+ {
+ returnMessage = returnMessage.substring(0, quote) + '\\' + returnMessage.substring(quote);
+ quote = returnMessage.indexOf('"', quote + 2);
}
+ buf.append("\"chat\":\"");
+ buf.append(returnMessage);
+ buf.append("\"}");
+ byte[] bytes = buf.toString().getBytes("utf-8");
+ response.setContentLength(bytes.length);
+ response.getOutputStream().write(bytes);
}
- private synchronized void chat(HttpServletRequest request,HttpServletResponse response,String username,String message)
- throws IOException
+ private void sendMessageToAllMembers(String message, String username, Map<String, Member> room)
{
- Map<String,Member> room=_rooms.get(request.getPathInfo());
- if (room!=null)
+ LOG.debug("Sending message: {} from: {}", message, username);
+ for (Member m : room.values())
{
- // Post chat to all members
- for (Member m:room.values())
+ synchronized (m)
{
- synchronized (m)
- {
- m._queue.add(username); // from
- m._queue.add(message); // chat
+ m._queue.add(username); // from
+ m._queue.add(message); // chat
- // wakeup member if polling
- AsyncContext async=m._async.get();
- if (async!=null & m._async.compareAndSet(async,null))
- async.dispatch();
+ // wakeup member if polling
+ AsyncContext async = m._async.get();
+ LOG.debug("Async found: {}", async);
+ if (async != null & m._async.compareAndSet(async, null))
+ {
+ LOG.debug("dispatch");
+ async.dispatch();
}
}
}
-
- response.setContentType("text/json;charset=utf-8");
- PrintWriter out=response.getWriter();
- out.print("{action:\"chat\"}");
}
// Serve the HTML with embedded CSS and Javascript.
@@ -206,10 +223,10 @@ public class ChatServlet extends HttpServlet
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
- if (request.getParameter("action")!=null)
- doPost(request,response);
+ if (request.getParameter("action") != null)
+ doPost(request, response);
else
- getServletContext().getNamedDispatcher("default").forward(request,response);
+ getServletContext().getNamedDispatcher("default").forward(request, response);
}
}
diff --git a/tests/test-webapps/test-jetty-webapp/src/main/resources/jetty-logging.properties b/tests/test-webapps/test-jetty-webapp/src/main/resources/jetty-logging.properties
new file mode 100644
index 0000000000..d474e35347
--- /dev/null
+++ b/tests/test-webapps/test-jetty-webapp/src/main/resources/jetty-logging.properties
@@ -0,0 +1,2 @@
+org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
+com.acme.LEVEL=INFO
diff --git a/tests/test-webapps/test-jetty-webapp/src/main/webapp/chat/index.html b/tests/test-webapps/test-jetty-webapp/src/main/webapp/chat/index.html
index cc8f833154..53e4795b1c 100644
--- a/tests/test-webapps/test-jetty-webapp/src/main/webapp/chat/index.html
+++ b/tests/test-webapps/test-jetty-webapp/src/main/webapp/chat/index.html
@@ -30,38 +30,28 @@
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.send(body);
}
- ;
- function send(action, user, message, handler)
+ function send(user, message, handler, join)
{
if (message) message = message.replace('%', '%25').replace('&', '%26').replace('=', '%3D');
if (user) user = user.replace('%', '%25').replace('&', '%26').replace('=', '%3D');
- xhr('POST', 'chat', 'action=' + action + '&user=' + user + '&message=' + message, handler);
+ var requestBody = 'user=' + user + (message ? '&message=' + message : '') + (join ? '&join=true' : '');
+ xhr('POST', 'chat', requestBody , handler);
}
- ;
-
var room = {
- join:function (name)
+ join: function (name)
{
this._username = name;
$('join').className = 'hidden';
$('joined').className = '';
$('phrase').focus();
- send('join', room._username, null, room._joined);
- },
- _joined:function ()
- {
- send('chat', room._username, 'has joined!', room._startPolling);
- },
- _startPolling:function ()
- {
- send('poll', room._username, null, room._poll);
+ send(room._username, 'has joined!', room._poll, true);
},
- chat:function (text)
+ chat: function (text)
{
if (text != null && text.length > 0)
- send('chat', room._username, text);
+ send(room._username, text, room._poll, false);
},
- _poll:function (m)
+ _poll: function (m)
{
//console.debug(m);
if (m.chat)
@@ -79,10 +69,9 @@
chat.appendChild(lineBreak);
chat.scrollTop = chat.scrollHeight - chat.clientHeight;
}
- if (m.action == 'poll')
- send('poll', room._username, null, room._poll);
+ send(room._username, null, room._poll, false);
},
- _end:''
+ _end: ''
};
</script>
<style type='text/css'>
@@ -106,7 +95,7 @@
padding: 4px;
background-color: #e0e0e0;
border: 1px solid black;
- border-top: 0px
+ border-top: 0
}
input#phrase {
@@ -122,14 +111,6 @@
div.hidden {
display: none;
}
-
- span.from {
- font-weight: bold;
- }
-
- span.alert {
- font-style: italic;
- }
</style>
</head>
<body>
diff --git a/tests/test-webapps/test-jetty-webapp/src/test/java/org/eclipse/jetty/ChatServletTest.java b/tests/test-webapps/test-jetty-webapp/src/test/java/org/eclipse/jetty/ChatServletTest.java
new file mode 100644
index 0000000000..eb8717f195
--- /dev/null
+++ b/tests/test-webapps/test-jetty-webapp/src/test/java/org/eclipse/jetty/ChatServletTest.java
@@ -0,0 +1,93 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty;
+
+import com.acme.ChatServlet;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlet.ServletTester;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+@RunWith(JUnit4.class)
+public class ChatServletTest
+{
+
+ private final ServletTester tester = new ServletTester();
+
+ @Before
+ public void setUp() throws Exception
+ {
+ tester.setContextPath("/");
+
+ ServletHolder dispatch = tester.addServlet(ChatServlet.class, "/chat/*");
+ dispatch.setInitParameter("asyncTimeout", "500");
+ tester.start();
+ }
+
+ @After
+ public void tearDown() throws Exception
+ {
+ tester.stop();
+ }
+
+ @Test
+ public void testLogin() throws Exception
+ {
+ assertResponse("user=test&join=true&message=has%20joined!", "{\"from\":\"test\",\"chat\":\"has joined!\"}");
+ }
+
+ @Test
+ public void testChat() throws Exception
+ {
+ assertResponse("user=test&join=true&message=has%20joined!", "{\"from\":\"test\",\"chat\":\"has joined!\"}");
+ String response = tester.getResponses(createRequestString("user=test&message=message"));
+ assertThat(response.contains("{"), is(false)); // make sure we didn't get a json body
+ }
+
+ @Test
+ public void testPoll() throws Exception
+ {
+ assertResponse("user=test", "{action:\"poll\"}");
+ }
+
+ private void assertResponse(String requestBody, String expectedResponse) throws Exception
+ {
+ String response = tester.getResponses(createRequestString(requestBody));
+ assertThat(response.contains(expectedResponse), is(true));
+ }
+
+ private String createRequestString(String body)
+ {
+ StringBuilder req1 = new StringBuilder();
+ req1.append("POST /chat/ HTTP/1.1\r\n");
+ req1.append("Host: tester\r\n");
+ req1.append("Content-length: " + body.length() + "\r\n");
+ req1.append("Content-type: application/x-www-form-urlencoded\r\n");
+ req1.append("Connection: close\r\n");
+ req1.append("\r\n");
+ req1.append(body);
+ return req1.toString();
+ }
+}
diff --git a/tests/test-webapps/test-webapp-rfc2616/pom.xml b/tests/test-webapps/test-webapp-rfc2616/pom.xml
index f3e432d579..f458ac0079 100644
--- a/tests/test-webapps/test-webapp-rfc2616/pom.xml
+++ b/tests/test-webapps/test-webapp-rfc2616/pom.xml
@@ -25,6 +25,7 @@
</parent>
<artifactId>test-webapp-rfc2616</artifactId>
<name>Jetty Tests :: WebApp :: RFC2616</name>
+ <url>http://www.eclipse.org/jetty</url>
<packaging>war</packaging>
<build>
<plugins>

Back to the top