Merged branch 'jetty-9.1.x' into 'master'.
diff --git a/VERSION.txt b/VERSION.txt
index 6d87bc7..7b8a856 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1,3 +1,5 @@
+jetty-9.2.0-SNAPSHOT
+
jetty-9.1.4.v20140401 - 01 April 2014
+ 414206 Rewrite rules re-encode requestURI
+ 414885 Don't expose JDT classes by default
diff --git a/aggregates/jetty-all/pom.xml b/aggregates/jetty-all/pom.xml
index 37932e6..de45168 100644
--- a/aggregates/jetty-all/pom.xml
+++ b/aggregates/jetty-all/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/apache-jsp/pom.xml b/apache-jsp/pom.xml
new file mode 100644
index 0000000..27bafe5
--- /dev/null
+++ b/apache-jsp/pom.xml
@@ -0,0 +1,95 @@
+<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>9.2.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>apache-jsp</artifactId>
+ <name>Jetty :: Apache JSP</name>
+ <url>http://www.eclipse.org/jetty</url>
+ <packaging>jar</packaging>
+ <properties>
+ <bundle-symbolic-name>${project.groupId}.${project.artifactId}</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.apache.jsp.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}"</Export-Package>
+ <Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
+ <Provide-Capability>osgi.serviceloader; osgi.serviceloader=javax.servlet.ServletContainerInitializer</Provide-Capability>
+ <_nouses>true</_nouses>
+ </instructions>
+ </configuration>
+ </execution>
+ </executions>
+ </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>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Schemas -->
+ <dependency>
+ <groupId>org.eclipse.jetty.toolchain</groupId>
+ <artifactId>jetty-schemas</artifactId>
+ </dependency>
+
+ <!-- servlet api -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+
+ <!-- JSP Api -->
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>javax.servlet.jsp-api</artifactId>
+ </dependency>
+
+ <!-- JSP Impl -->
+ <dependency>
+ <groupId>org.mortbay.jasper</groupId>
+ <artifactId>apache-jsp</artifactId>
+ </dependency>
+
+ <!-- Eclipse Java Compiler (for JSP Compilation) -->
+ <dependency>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>org.eclipse.jdt.core</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/apache-jsp/src/main/config/modules/jsp-impl/apache-jsp.mod b/apache-jsp/src/main/config/modules/jsp-impl/apache-jsp.mod
new file mode 100644
index 0000000..aed547c
--- /dev/null
+++ b/apache-jsp/src/main/config/modules/jsp-impl/apache-jsp.mod
@@ -0,0 +1,10 @@
+#
+# Apache JSP Module
+#
+
+[name]
+jsp-impl
+
+[lib]
+lib/apache-jsp/*.jar
+
diff --git a/apache-jsp/src/main/java/org/eclipse/jetty/apache/jsp/JettyJasperInitializer.java b/apache-jsp/src/main/java/org/eclipse/jetty/apache/jsp/JettyJasperInitializer.java
new file mode 100644
index 0000000..4cd7993
--- /dev/null
+++ b/apache-jsp/src/main/java/org/eclipse/jetty/apache/jsp/JettyJasperInitializer.java
@@ -0,0 +1,114 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.apache.jsp;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.apache.jasper.servlet.JasperInitializer;
+import org.apache.jasper.servlet.TldPreScanned;
+import org.apache.jasper.servlet.TldScanner;
+import org.xml.sax.SAXException;
+
+/**
+ * JettyJasperInitializer
+ *
+ */
+public class JettyJasperInitializer extends JasperInitializer
+{
+
+ /**
+ * NullTldScanner
+ *
+ * Does nothing. Used when we can tell that all jsps have been precompiled, in which case
+ * the tlds are not needed.
+ */
+ private final class NullTldScanner extends TldScanner
+ {
+ /**
+ * @param context
+ * @param namespaceAware
+ * @param validation
+ * @param blockExternal
+ */
+ private NullTldScanner(ServletContext context, boolean namespaceAware, boolean validation, boolean blockExternal)
+ {
+ super(context, namespaceAware, validation, blockExternal);
+ }
+
+ /**
+ * @see org.apache.jasper.servlet.TldScanner#scan()
+ */
+ @Override
+ public void scan() throws IOException, SAXException
+ {
+ return; //do nothing
+ }
+
+ /**
+ * @see org.apache.jasper.servlet.TldScanner#getListeners()
+ */
+ @Override
+ public List<String> getListeners()
+ {
+ return Collections.emptyList();
+ }
+
+ /**
+ * @see org.apache.jasper.servlet.TldScanner#scanJars()
+ */
+ @Override
+ public void scanJars()
+ {
+ return; //do nothing
+ }
+ }
+
+ /**
+ * Make a TldScanner, and prefeed it the tlds that have already been discovered in jar files
+ * by the MetaInfConfiguration.
+ *
+ * @see org.apache.jasper.servlet.JasperInitializer#prepareScanner(javax.servlet.ServletContext, boolean, boolean, boolean)
+ */
+ @Override
+ public TldScanner newTldScanner(ServletContext context, boolean namespaceAware, boolean validate, boolean blockExternal)
+ {
+ String tmp = context.getInitParameter("org.eclipse.jetty.jsp.precompiled");
+ if (tmp!=null && !tmp.equals("") && Boolean.valueOf(tmp))
+ {
+ return new NullTldScanner(context, namespaceAware, validate, blockExternal);
+ }
+
+ Collection<URL> tldUrls = (Collection<URL>)context.getAttribute("org.eclipse.jetty.tlds");
+ if (tldUrls != null && !tldUrls.isEmpty())
+ {
+ return new TldPreScanned(context,namespaceAware,validate,blockExternal,tldUrls);
+ }
+ return super.newTldScanner(context, namespaceAware, validate, blockExternal);
+ }
+
+
+}
diff --git a/apache-jsp/src/main/java/org/eclipse/jetty/apache/jsp/JuliLog.java b/apache-jsp/src/main/java/org/eclipse/jetty/apache/jsp/JuliLog.java
new file mode 100644
index 0000000..e58781d
--- /dev/null
+++ b/apache-jsp/src/main/java/org/eclipse/jetty/apache/jsp/JuliLog.java
@@ -0,0 +1,188 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.apache.jsp;
+
+public class JuliLog implements org.apache.juli.logging.Log
+{
+ public static org.apache.juli.logging.Log getInstance(String name)
+ {
+ return new JuliLog(name);
+ }
+
+ private final org.eclipse.jetty.util.log.Logger _logger;
+ private final org.eclipse.jetty.util.log.StdErrLog _stdErrLog;
+
+ public JuliLog()
+ {
+ _logger=org.eclipse.jetty.util.log.Log.getRootLogger();
+ _stdErrLog=(_logger instanceof org.eclipse.jetty.util.log.StdErrLog) ? (org.eclipse.jetty.util.log.StdErrLog)_logger:null;
+ }
+
+ public JuliLog(String name)
+ {
+ _logger=org.eclipse.jetty.util.log.Log.getLogger(name);
+ _stdErrLog=(_logger instanceof org.eclipse.jetty.util.log.StdErrLog) ? (org.eclipse.jetty.util.log.StdErrLog)_logger:null;
+ }
+
+ @Override
+ public boolean isDebugEnabled()
+ {
+ return _logger.isDebugEnabled();
+ }
+
+ @Override
+ public boolean isErrorEnabled()
+ {
+ return _stdErrLog==null?true:_stdErrLog.getLevel()<=org.eclipse.jetty.util.log.StdErrLog.LEVEL_WARN;
+ }
+
+ @Override
+ public boolean isFatalEnabled()
+ {
+ return _stdErrLog==null?true:_stdErrLog.getLevel()<=org.eclipse.jetty.util.log.StdErrLog.LEVEL_WARN;
+ }
+
+ @Override
+ public boolean isInfoEnabled()
+ {
+ return _stdErrLog==null?true:_stdErrLog.getLevel()<=org.eclipse.jetty.util.log.StdErrLog.LEVEL_INFO;
+ }
+
+ @Override
+ public boolean isTraceEnabled()
+ {
+ return _stdErrLog==null?true:_stdErrLog.getLevel()<=org.eclipse.jetty.util.log.StdErrLog.LEVEL_DEBUG;
+ }
+
+ @Override
+ public boolean isWarnEnabled()
+ {
+ return _stdErrLog==null?true:_stdErrLog.getLevel()<=org.eclipse.jetty.util.log.StdErrLog.LEVEL_WARN;
+ }
+
+ @Override
+ public void trace(Object message)
+ {
+ if (message instanceof String)
+ _logger.debug((String)message);
+ else
+ _logger.debug("{}",message);
+ }
+
+ @Override
+ public void trace(Object message, Throwable t)
+ {
+ if (message instanceof String)
+ _logger.debug((String)message,t);
+ else
+ _logger.debug("{}",message,t);
+ }
+
+ @Override
+ public void debug(Object message)
+ {
+ if (message instanceof String)
+ _logger.debug((String)message);
+ else
+ _logger.debug("{}",message);
+ }
+
+ @Override
+ public void debug(Object message, Throwable t)
+ {
+ if (message instanceof String)
+ _logger.debug((String)message,t);
+ else
+ _logger.debug("{}",message,t);
+ }
+
+ @Override
+ public void info(Object message)
+ {
+ if (message instanceof String)
+ _logger.info((String)message);
+ else
+ _logger.info("{}",message);
+ }
+
+ @Override
+ public void info(Object message, Throwable t)
+ {
+ if (message instanceof String)
+ _logger.info((String)message,t);
+ else
+ _logger.info("{}",message,t);
+ }
+
+ @Override
+ public void warn(Object message)
+ {
+ if (message instanceof String)
+ _logger.warn((String)message);
+ else
+ _logger.warn("{}",message);
+ }
+
+ @Override
+ public void warn(Object message, Throwable t)
+ {
+ if (message instanceof String)
+ _logger.warn((String)message,t);
+ else
+ _logger.warn("{}",message,t);
+ }
+
+ @Override
+ public void error(Object message)
+ {
+ if (message instanceof String)
+ _logger.warn((String)message);
+ else
+ _logger.warn("{}",message);
+ }
+
+ @Override
+ public void error(Object message, Throwable t)
+ {
+ if (message instanceof String)
+ _logger.warn((String)message,t);
+ else
+ _logger.warn("{}",message,t);
+ }
+
+ @Override
+ public void fatal(Object message)
+ {
+ if (message instanceof String)
+ _logger.warn((String)message);
+ else
+ _logger.warn("{}",message);
+ }
+
+ @Override
+ public void fatal(Object message, Throwable t)
+ {
+ if (message instanceof String)
+ _logger.warn((String)message,t);
+ else
+ _logger.warn("{}",message,t);
+ }
+}
+
+
diff --git a/apache-jsp/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer b/apache-jsp/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer
new file mode 100644
index 0000000..6346705
--- /dev/null
+++ b/apache-jsp/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer
@@ -0,0 +1 @@
+org.eclipse.jetty.apache.jsp.JettyJasperInitializer
diff --git a/apache-jsp/src/main/resources/META-INF/services/org.apache.juli.logging.Log b/apache-jsp/src/main/resources/META-INF/services/org.apache.juli.logging.Log
new file mode 100644
index 0000000..efa397b
--- /dev/null
+++ b/apache-jsp/src/main/resources/META-INF/services/org.apache.juli.logging.Log
@@ -0,0 +1 @@
+org.eclipse.jetty.apache.jsp.JuliLog
diff --git a/apache-jstl/pom.xml b/apache-jstl/pom.xml
new file mode 100644
index 0000000..38c8158
--- /dev/null
+++ b/apache-jstl/pom.xml
@@ -0,0 +1,49 @@
+<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>9.2.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>apache-jstl</artifactId>
+ <name>Apache :: JSTL module</name>
+ <url>http://tomcat.apache.org/taglibs/standard/</url>
+ <packaging>jar</packaging>
+
+ <build>
+ <plugins>
+ <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>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <!-- JSTL Api -->
+ <dependency>
+ <groupId>org.apache.taglibs</groupId>
+ <artifactId>taglibs-standard-spec</artifactId>
+ </dependency>
+
+ <!-- JSTL Impl -->
+ <dependency>
+ <groupId>org.apache.taglibs</groupId>
+ <artifactId>taglibs-standard-impl</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/apache-jstl/src/main/config/modules/jsp-impl/apache-jstl.mod b/apache-jstl/src/main/config/modules/jsp-impl/apache-jstl.mod
new file mode 100644
index 0000000..804b191
--- /dev/null
+++ b/apache-jstl/src/main/config/modules/jsp-impl/apache-jstl.mod
@@ -0,0 +1,8 @@
+#
+# Apache JSTL
+#
+[name]
+jstl-impl
+
+[lib]
+lib/apache-jstl/*.jar
diff --git a/apache-jstl/src/main/resources/readme.txt b/apache-jstl/src/main/resources/readme.txt
new file mode 100644
index 0000000..a516023
--- /dev/null
+++ b/apache-jstl/src/main/resources/readme.txt
@@ -0,0 +1,4 @@
+This empty jar file is purely to work around a problem with the Maven Dependency plugin.
+Several modules in jetty use the Dependency plugin to copy or unpack the dependencies of other modules.
+However, the Dependency plugin is not capable of unpacking or copying a dependency of type 'pom', which
+this module is, as it consists purely of external dependencies needed to run jsp.
diff --git a/examples/async-rest/async-rest-jar/pom.xml b/examples/async-rest/async-rest-jar/pom.xml
index a8ff514..9af2078 100644
--- a/examples/async-rest/async-rest-jar/pom.xml
+++ b/examples/async-rest/async-rest-jar/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.example-async-rest</groupId>
diff --git a/examples/async-rest/async-rest-webapp/pom.xml b/examples/async-rest/async-rest-webapp/pom.xml
index 582d5a0..1779812 100644
--- a/examples/async-rest/async-rest-webapp/pom.xml
+++ b/examples/async-rest/async-rest-webapp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.example-async-rest</groupId>
diff --git a/examples/async-rest/pom.xml b/examples/async-rest/pom.xml
index b2b6ca3..84bd9a4 100644
--- a/examples/async-rest/pom.xml
+++ b/examples/async-rest/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.examples</groupId>
<artifactId>examples-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/examples/embedded/pom.xml b/examples/embedded/pom.xml
index 8c0abae..30019e0 100644
--- a/examples/embedded/pom.xml
+++ b/examples/embedded/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.examples</groupId>
<artifactId>examples-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/examples/pom.xml b/examples/pom.xml
index 2fadf1a..737b90f 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.eclipse.jetty.examples</groupId>
diff --git a/jetty-alpn/jetty-alpn-client/pom.xml b/jetty-alpn/jetty-alpn-client/pom.xml
new file mode 100644
index 0000000..0c3bb4d
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-client/pom.xml
@@ -0,0 +1,76 @@
+<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-alpn-parent</artifactId>
+ <version>9.2.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-alpn-client</artifactId>
+ <name>Jetty :: ALPN Client</name>
+ <description>Jetty ALPN client services</description>
+ <url>http://www.eclipse.org/jetty</url>
+ <properties>
+ <bundle-symbolic-name>${project.groupId}.alpn.client</bundle-symbolic-name>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <executions>
+ <execution>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ <configuration>
+ <instructions>
+ <Import-Package>org.eclipse.jetty.alpn;resolution:=optional</Import-Package>
+ </instructions>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <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>
+ <!-- always include the sources to be able to prepare the eclipse-jetty-SDK feature
+ with a snapshot. -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <configuration>
+ <onlyAnalyze>org.eclipse.jetty.alpn.*</onlyAnalyze>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-io</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.alpn</groupId>
+ <artifactId>alpn-api</artifactId>
+ <version>${alpn.api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.toolchain</groupId>
+ <artifactId>jetty-test-helper</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/jetty-alpn/jetty-alpn-client/src/main/java/org/eclipse/jetty/alpn/client/ALPNClientConnection.java b/jetty-alpn/jetty-alpn-client/src/main/java/org/eclipse/jetty/alpn/client/ALPNClientConnection.java
new file mode 100644
index 0000000..1cc08ab
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-client/src/main/java/org/eclipse/jetty/alpn/client/ALPNClientConnection.java
@@ -0,0 +1,87 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.alpn.client;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import javax.net.ssl.SSLEngine;
+
+import org.eclipse.jetty.alpn.ALPN;
+import org.eclipse.jetty.io.ClientConnectionFactory;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.io.NegotiatingClientConnection;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+public class ALPNClientConnection extends NegotiatingClientConnection implements ALPN.ClientProvider
+{
+ private static final Logger LOG = Log.getLogger(ALPNClientConnection.class);
+
+ private final String protocol;
+
+ public ALPNClientConnection(EndPoint endPoint, Executor executor, ClientConnectionFactory connectionFactory, SSLEngine sslEngine, Map<String, Object> context, String protocol)
+ {
+ super(endPoint, executor, sslEngine, connectionFactory, context);
+ this.protocol = protocol;
+ ALPN.put(sslEngine, this);
+ }
+
+ @Override
+ public boolean supports()
+ {
+ return true;
+ }
+
+ @Override
+ public void unsupported()
+ {
+ ALPN.remove(getSSLEngine());
+ completed();
+ }
+
+ @Override
+ public List<String> protocols()
+ {
+ return Arrays.asList(protocol);
+ }
+
+ @Override
+ public void selected(String protocol)
+ {
+ if (this.protocol.equals(protocol))
+ {
+ ALPN.remove(getSSLEngine());
+ completed();
+ }
+ else
+ {
+ LOG.info("Could not negotiate protocol: server {} - client {}", protocol, this.protocol);
+ close();
+ }
+ }
+
+ @Override
+ public void close()
+ {
+ ALPN.remove(getSSLEngine());
+ super.close();
+ }
+}
diff --git a/jetty-alpn/jetty-alpn-client/src/main/java/org/eclipse/jetty/alpn/client/ALPNClientConnectionFactory.java b/jetty-alpn/jetty-alpn-client/src/main/java/org/eclipse/jetty/alpn/client/ALPNClientConnectionFactory.java
new file mode 100644
index 0000000..881c6a5
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-client/src/main/java/org/eclipse/jetty/alpn/client/ALPNClientConnectionFactory.java
@@ -0,0 +1,51 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.alpn.client;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.Executor;
+
+import javax.net.ssl.SSLEngine;
+
+import org.eclipse.jetty.io.ClientConnectionFactory;
+import org.eclipse.jetty.io.Connection;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.io.NegotiatingClientConnectionFactory;
+import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
+
+public class ALPNClientConnectionFactory extends NegotiatingClientConnectionFactory
+{
+ private final Executor executor;
+ private final String protocol;
+
+ public ALPNClientConnectionFactory(Executor executor, ClientConnectionFactory connectionFactory, String protocol)
+ {
+ super(connectionFactory);
+ this.executor = executor;
+ this.protocol = protocol;
+ }
+
+ @Override
+ public Connection newConnection(EndPoint endPoint, Map<String, Object> context) throws IOException
+ {
+ return new ALPNClientConnection(endPoint, executor, getClientConnectionFactory(),
+ (SSLEngine)context.get(SslClientConnectionFactory.SSL_ENGINE_CONTEXT_KEY), context, protocol);
+ }
+}
diff --git a/jetty-alpn/jetty-alpn-server/pom.xml b/jetty-alpn/jetty-alpn-server/pom.xml
new file mode 100644
index 0000000..6634192
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/pom.xml
@@ -0,0 +1,94 @@
+<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-alpn-parent</artifactId>
+ <version>9.2.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-alpn-server</artifactId>
+ <name>Jetty :: ALPN Server</name>
+ <description>Jetty ALPN server services</description>
+ <url>http://www.eclipse.org/jetty</url>
+ <properties>
+ <bundle-symbolic-name>${project.groupId}.alpn.server</bundle-symbolic-name>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <executions>
+ <execution>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ <configuration>
+ <instructions>
+ <Import-Package>org.eclipse.jetty.alpn,*</Import-Package>
+ <_nouses>true</_nouses>
+ </instructions>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <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>
+ <!-- always include the sources to be able to prepare the eclipse-jetty-SDK feature
+ with a snapshot. -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <configuration>
+ <onlyAnalyze>org.eclipse.jetty.alpn.*</onlyAnalyze>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.alpn</groupId>
+ <artifactId>alpn-api</artifactId>
+ <version>${alpn.api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.toolchain</groupId>
+ <artifactId>jetty-test-helper</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/etc/protonego-alpn.xml b/jetty-alpn/jetty-alpn-server/src/main/config/etc/protonego-alpn.xml
new file mode 100644
index 0000000..293de04
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/config/etc/protonego-alpn.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+
+<Configure id="protonego" class="org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory">
+ <Arg name="protocols">
+ <Array type="String">
+ <Item>spdy/3</Item>
+ <Item>spdy/2</Item>
+ <Item>http/1.1</Item>
+ </Array>
+ </Arg>
+
+ <Set name="defaultProtocol">http/1.1</Set>
+
+</Configure>
+
diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_40.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_40.mod
new file mode 100644
index 0000000..bee4693
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_40.mod
@@ -0,0 +1,8 @@
+[name]
+protonego-boot
+
+[files]
+http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/7.0.0.v20140317/alpn-boot-7.0.0.v20140317.jar:lib/alpn/alpn-boot-7.0.0.v20140317.jar
+
+[exec]
+-Xbootclasspath/p:lib/alpn/alpn-boot-7.0.0.v20140317.jar
diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_45.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_45.mod
new file mode 100644
index 0000000..bee4693
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_45.mod
@@ -0,0 +1,8 @@
+[name]
+protonego-boot
+
+[files]
+http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/7.0.0.v20140317/alpn-boot-7.0.0.v20140317.jar:lib/alpn/alpn-boot-7.0.0.v20140317.jar
+
+[exec]
+-Xbootclasspath/p:lib/alpn/alpn-boot-7.0.0.v20140317.jar
diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_51.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_51.mod
new file mode 100644
index 0000000..bee4693
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_51.mod
@@ -0,0 +1,8 @@
+[name]
+protonego-boot
+
+[files]
+http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/7.0.0.v20140317/alpn-boot-7.0.0.v20140317.jar:lib/alpn/alpn-boot-7.0.0.v20140317.jar
+
+[exec]
+-Xbootclasspath/p:lib/alpn/alpn-boot-7.0.0.v20140317.jar
diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_55.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_55.mod
new file mode 100644
index 0000000..bee4693
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_55.mod
@@ -0,0 +1,8 @@
+[name]
+protonego-boot
+
+[files]
+http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/7.0.0.v20140317/alpn-boot-7.0.0.v20140317.jar:lib/alpn/alpn-boot-7.0.0.v20140317.jar
+
+[exec]
+-Xbootclasspath/p:lib/alpn/alpn-boot-7.0.0.v20140317.jar
diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0.mod
new file mode 100644
index 0000000..4089153
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0.mod
@@ -0,0 +1,8 @@
+[name]
+protonego-boot
+
+[files]
+http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.0.0.v20140317/alpn-boot-8.0.0.v20140317.jar:lib/alpn/alpn-boot-8.0.0.v20140317.jar
+
+[exec]
+-Xbootclasspath/p:lib/alpn/alpn-boot-8.0.0.v20140317.jar
diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0_05.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0_05.mod
new file mode 100644
index 0000000..4089153
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0_05.mod
@@ -0,0 +1,8 @@
+[name]
+protonego-boot
+
+[files]
+http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.0.0.v20140317/alpn-boot-8.0.0.v20140317.jar:lib/alpn/alpn-boot-8.0.0.v20140317.jar
+
+[exec]
+-Xbootclasspath/p:lib/alpn/alpn-boot-8.0.0.v20140317.jar
diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn.mod
new file mode 100644
index 0000000..0e399f0
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn.mod
@@ -0,0 +1,36 @@
+# ALPN is provided via a -Xbootclasspath that modifies the secure connections
+# in java to support the ALPN layer needed for SPDY (and eventually HTTP/2)
+#
+# This modification has a tight dependency on specific recent updates of
+# Java 1.7 and Java 1.8
+# (Java versions prior to 1.7u40 are not supported)
+#
+# The alpn protonego module will use an appropriate alpn-boot jar for your
+# specific version of Java.
+#
+# IMPORTANT: Versions of Java that exist after this module was created are
+# not guaranteed to work with existing alpn-boot jars, and might
+# need a new alpn-boot to be created / tested / deployed by the
+# Jetty project in order to provide support for these future
+# Java versions.
+#
+# All versions of alpn-boot can be found at
+# http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/
+
+[name]
+protonego-impl
+
+[depend]
+protonego-impl/alpn-${java.version}
+
+[lib]
+lib/jetty-alpn-client-${jetty.version}.jar
+lib/jetty-alpn-server-${jetty.version}.jar
+
+[xml]
+etc/protonego-alpn.xml
+
+[files]
+lib/
+lib/alpn/
+
diff --git a/jetty-alpn/jetty-alpn-server/src/main/java/org/eclipse/jetty/alpn/server/ALPNServerConnection.java b/jetty-alpn/jetty-alpn-server/src/main/java/org/eclipse/jetty/alpn/server/ALPNServerConnection.java
new file mode 100644
index 0000000..509682e
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/java/org/eclipse/jetty/alpn/server/ALPNServerConnection.java
@@ -0,0 +1,77 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.alpn.server;
+
+import java.util.Collections;
+import java.util.List;
+import javax.net.ssl.SSLEngine;
+
+import org.eclipse.jetty.alpn.ALPN;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.NegotiatingServerConnection;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+public class ALPNServerConnection extends NegotiatingServerConnection implements ALPN.ServerProvider
+{
+ private static final Logger LOG = Log.getLogger(ALPNServerConnection.class);
+
+ public ALPNServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol)
+ {
+ super(connector, endPoint, engine, protocols, defaultProtocol);
+ ALPN.put(engine, this);
+ }
+
+ @Override
+ public void unsupported()
+ {
+ select(Collections.<String>emptyList());
+ }
+
+ @Override
+ public String select(List<String> clientProtocols)
+ {
+ List<String> serverProtocols = getProtocols();
+ String negotiated = null;
+ for (String clientProtocol : clientProtocols)
+ {
+ if (serverProtocols.contains(clientProtocol))
+ {
+ negotiated = clientProtocol;
+ break;
+ }
+ }
+ if (negotiated == null)
+ {
+ negotiated = getDefaultProtocol();
+ }
+ LOG.debug("{} protocol selected {}", this, negotiated);
+ setProtocol(negotiated);
+ ALPN.remove(getSSLEngine());
+ return negotiated;
+ }
+
+ @Override
+ public void close()
+ {
+ ALPN.remove(getSSLEngine());
+ super.close();
+ }
+}
diff --git a/jetty-alpn/jetty-alpn-server/src/main/java/org/eclipse/jetty/alpn/server/ALPNServerConnectionFactory.java b/jetty-alpn/jetty-alpn-server/src/main/java/org/eclipse/jetty/alpn/server/ALPNServerConnectionFactory.java
new file mode 100644
index 0000000..a6e386b
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/java/org/eclipse/jetty/alpn/server/ALPNServerConnectionFactory.java
@@ -0,0 +1,61 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.alpn.server;
+
+import java.util.List;
+import javax.net.ssl.SSLEngine;
+
+import org.eclipse.jetty.alpn.ALPN;
+import org.eclipse.jetty.io.AbstractConnection;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
+import org.eclipse.jetty.util.annotation.Name;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+public class ALPNServerConnectionFactory extends NegotiatingServerConnectionFactory
+{
+ private static final Logger LOG = Log.getLogger(ALPNServerConnectionFactory.class);
+
+ public ALPNServerConnectionFactory(@Name("protocols") String... protocols)
+ {
+ super("alpn", protocols);
+ try
+ {
+ ClassLoader alpnClassLoader = ALPN.class.getClassLoader();
+ if (alpnClassLoader != null)
+ {
+ LOG.warn("ALPN must be in the boot classloader, not in: " + alpnClassLoader);
+ throw new IllegalStateException("ALPN must be in the boot classloader");
+ }
+ }
+ catch (Throwable x)
+ {
+ LOG.warn("ALPN not available", x);
+ throw new IllegalStateException("ALPN not available", x);
+ }
+ }
+
+ @Override
+ protected AbstractConnection newServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol)
+ {
+ return new ALPNServerConnection(connector, endPoint, engine, protocols, defaultProtocol);
+ }
+}
diff --git a/jetty-alpn/pom.xml b/jetty-alpn/pom.xml
new file mode 100644
index 0000000..689b859
--- /dev/null
+++ b/jetty-alpn/pom.xml
@@ -0,0 +1,17 @@
+<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>9.2.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-alpn-parent</artifactId>
+ <packaging>pom</packaging>
+ <name>Jetty :: ALPN :: Parent</name>
+ <description>Jetty ALPN services parent</description>
+ <url>http://www.eclipse.org/jetty</url>
+ <modules>
+ <module>jetty-alpn-server</module>
+ <module>jetty-alpn-client</module>
+ </modules>
+</project>
diff --git a/jetty-annotations/pom.xml b/jetty-annotations/pom.xml
index bb6d838..f07812f 100644
--- a/jetty-annotations/pom.xml
+++ b/jetty-annotations/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-annotations</artifactId>
diff --git a/jetty-ant/pom.xml b/jetty-ant/pom.xml
index cc2012d..3f9ade0 100644
--- a/jetty-ant/pom.xml
+++ b/jetty-ant/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-ant</artifactId>
diff --git a/jetty-client/pom.xml b/jetty-client/pom.xml
index 9eee4c9..ea2eb2d 100644
--- a/jetty-client/pom.xml
+++ b/jetty-client/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java
index f7f17c3..0f0a9f3 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java
@@ -45,6 +45,7 @@
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
public class HttpClientRedirectTest extends AbstractHttpClientServerTest
@@ -244,8 +245,10 @@
}
@Test
+ @Ignore
public void testRedirectFailed() throws Exception
{
+ // TODO this test is failing with timout after an ISP upgrade?? DNS dependent?
try
{
client.newRequest("localhost", connector.getLocalPort())
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpReceiverTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpReceiverTest.java
deleted file mode 100644
index 86c0b64..0000000
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpReceiverTest.java
+++ /dev/null
@@ -1,220 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.client;
-
-public class HttpReceiverTest
-{
-// @Rule
-// public final TestTracker tracker = new TestTracker();
-//
-// private HttpClient client;
-// private HttpDestination destination;
-// private ByteArrayEndPoint endPoint;
-// private HttpConnection connection;
-// private HttpConversation conversation;
-//
-// @Before
-// public void init() throws Exception
-// {
-// client = new HttpClient();
-// client.start();
-// destination = new HttpDestination(client, "http", "localhost", 8080);
-// endPoint = new ByteArrayEndPoint();
-// connection = new HttpConnection(client, endPoint, destination);
-// conversation = new HttpConversation(client, 1);
-// }
-//
-// @After
-// public void destroy() throws Exception
-// {
-// client.stop();
-// }
-//
-// protected HttpExchange newExchange()
-// {
-// HttpRequest request = new HttpRequest(client, URI.create("http://localhost"));
-// FutureResponseListener listener = new FutureResponseListener(request);
-// HttpExchange exchange = new HttpExchange(conversation, destination, request, Collections.<Response.ResponseListener>singletonList(listener));
-// conversation.getExchanges().offer(exchange);
-// connection.associate(exchange);
-// exchange.requestComplete();
-// exchange.terminateRequest();
-// return exchange;
-// }
-//
-// @Test
-// public void test_Receive_NoResponseContent() throws Exception
-// {
-// endPoint.setInput("" +
-// "HTTP/1.1 200 OK\r\n" +
-// "Content-length: 0\r\n" +
-// "\r\n");
-// HttpExchange exchange = newExchange();
-// FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
-// connection.receive();
-//
-// Response response = listener.get(5, TimeUnit.SECONDS);
-// Assert.assertNotNull(response);
-// Assert.assertEquals(200, response.getStatus());
-// Assert.assertEquals("OK", response.getReason());
-// Assert.assertSame(HttpVersion.HTTP_1_1, response.getVersion());
-// HttpFields headers = response.getHeaders();
-// Assert.assertNotNull(headers);
-// Assert.assertEquals(1, headers.size());
-// Assert.assertEquals("0", headers.get(HttpHeader.CONTENT_LENGTH));
-// }
-//
-// @Test
-// public void test_Receive_ResponseContent() throws Exception
-// {
-// String content = "0123456789ABCDEF";
-// endPoint.setInput("" +
-// "HTTP/1.1 200 OK\r\n" +
-// "Content-length: " + content.length() + "\r\n" +
-// "\r\n" +
-// content);
-// HttpExchange exchange = newExchange();
-// FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
-// connection.receive();
-//
-// Response response = listener.get(5, TimeUnit.SECONDS);
-// Assert.assertNotNull(response);
-// Assert.assertEquals(200, response.getStatus());
-// Assert.assertEquals("OK", response.getReason());
-// Assert.assertSame(HttpVersion.HTTP_1_1, response.getVersion());
-// HttpFields headers = response.getHeaders();
-// Assert.assertNotNull(headers);
-// Assert.assertEquals(1, headers.size());
-// Assert.assertEquals(String.valueOf(content.length()), headers.get(HttpHeader.CONTENT_LENGTH));
-// String received = listener.getContentAsString(StandardCharsets.UTF_8);
-// Assert.assertEquals(content, received);
-// }
-//
-// @Test
-// public void test_Receive_ResponseContent_EarlyEOF() throws Exception
-// {
-// String content1 = "0123456789";
-// String content2 = "ABCDEF";
-// endPoint.setInput("" +
-// "HTTP/1.1 200 OK\r\n" +
-// "Content-length: " + (content1.length() + content2.length()) + "\r\n" +
-// "\r\n" +
-// content1);
-// HttpExchange exchange = newExchange();
-// FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
-// connection.receive();
-// endPoint.setInputEOF();
-// connection.receive();
-//
-// try
-// {
-// listener.get(5, TimeUnit.SECONDS);
-// Assert.fail();
-// }
-// catch (ExecutionException e)
-// {
-// Assert.assertTrue(e.getCause() instanceof EOFException);
-// }
-// }
-//
-// @Test
-// public void test_Receive_ResponseContent_IdleTimeout() throws Exception
-// {
-// endPoint.setInput("" +
-// "HTTP/1.1 200 OK\r\n" +
-// "Content-length: 1\r\n" +
-// "\r\n");
-// HttpExchange exchange = newExchange();
-// FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
-// connection.receive();
-// // Simulate an idle timeout
-// connection.idleTimeout();
-//
-// try
-// {
-// listener.get(5, TimeUnit.SECONDS);
-// Assert.fail();
-// }
-// catch (ExecutionException e)
-// {
-// Assert.assertTrue(e.getCause() instanceof TimeoutException);
-// }
-// }
-//
-// @Test
-// public void test_Receive_BadResponse() throws Exception
-// {
-// endPoint.setInput("" +
-// "HTTP/1.1 200 OK\r\n" +
-// "Content-length: A\r\n" +
-// "\r\n");
-// HttpExchange exchange = newExchange();
-// FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
-// connection.receive();
-//
-// try
-// {
-// listener.get(5, TimeUnit.SECONDS);
-// Assert.fail();
-// }
-// catch (ExecutionException e)
-// {
-// Assert.assertTrue(e.getCause() instanceof HttpResponseException);
-// }
-// }
-//
-// @Test
-// public void test_Receive_GZIPResponseContent_Fragmented() throws Exception
-// {
-// byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-// ByteArrayOutputStream baos = new ByteArrayOutputStream();
-// try (GZIPOutputStream gzipOutput = new GZIPOutputStream(baos))
-// {
-// gzipOutput.write(data);
-// }
-// byte[] gzip = baos.toByteArray();
-//
-// endPoint.setInput("" +
-// "HTTP/1.1 200 OK\r\n" +
-// "Content-Length: " + gzip.length + "\r\n" +
-// "Content-Encoding: gzip\r\n" +
-// "\r\n");
-// HttpExchange exchange = newExchange();
-// FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
-// connection.receive();
-// endPoint.reset();
-//
-// ByteBuffer buffer = ByteBuffer.wrap(gzip);
-// int fragment = buffer.limit() - 1;
-// buffer.limit(fragment);
-// endPoint.setInput(buffer);
-// connection.receive();
-// endPoint.reset();
-//
-// buffer.limit(gzip.length);
-// buffer.position(fragment);
-// endPoint.setInput(buffer);
-// connection.receive();
-//
-// ContentResponse response = listener.get(5, TimeUnit.SECONDS);
-// Assert.assertNotNull(response);
-// Assert.assertEquals(200, response.getStatus());
-// Assert.assertArrayEquals(data, response.getContent());
-// }
-}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpSenderTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpSenderTest.java
deleted file mode 100644
index 3883ebf..0000000
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpSenderTest.java
+++ /dev/null
@@ -1,280 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.client;
-
-public class HttpSenderTest
-{
-// @Rule
-// public final TestTracker tracker = new TestTracker();
-//
-// private HttpClient client;
-//
-// @Before
-// public void init() throws Exception
-// {
-// client = new HttpClient();
-// client.start();
-// }
-//
-// @After
-// public void destroy() throws Exception
-// {
-// client.stop();
-// }
-//
-// @Test
-// public void test_Send_NoRequestContent() throws Exception
-// {
-// ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
-// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
-// HttpConnection connection = new HttpConnection(client, endPoint, destination);
-// Request request = client.newRequest(URI.create("http://localhost/"));
-// final CountDownLatch headersLatch = new CountDownLatch(1);
-// final CountDownLatch successLatch = new CountDownLatch(1);
-// request.listener(new Request.Listener.Adapter()
-// {
-// @Override
-// public void onHeaders(Request request)
-// {
-// headersLatch.countDown();
-// }
-//
-// @Override
-// public void onSuccess(Request request)
-// {
-// successLatch.countDown();
-// }
-// });
-// connection.send(request, (Response.CompleteListener)null);
-//
-// String requestString = endPoint.takeOutputString();
-// Assert.assertTrue(requestString.startsWith("GET "));
-// Assert.assertTrue(requestString.endsWith("\r\n\r\n"));
-// Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
-// Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
-// }
-//
-// @Slow
-// @Test
-// public void test_Send_NoRequestContent_IncompleteFlush() throws Exception
-// {
-// ByteArrayEndPoint endPoint = new ByteArrayEndPoint("", 16);
-// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
-// HttpConnection connection = new HttpConnection(client, endPoint, destination);
-// Request request = client.newRequest(URI.create("http://localhost/"));
-// connection.send(request, (Response.CompleteListener)null);
-//
-// // This take will free space in the buffer and allow for the write to complete
-// StringBuilder builder = new StringBuilder(endPoint.takeOutputString());
-//
-// // Wait for the write to complete
-// TimeUnit.SECONDS.sleep(1);
-//
-// String chunk = endPoint.takeOutputString();
-// while (chunk.length() > 0)
-// {
-// builder.append(chunk);
-// chunk = endPoint.takeOutputString();
-// }
-//
-// String requestString = builder.toString();
-// Assert.assertTrue(requestString.startsWith("GET "));
-// Assert.assertTrue(requestString.endsWith("\r\n\r\n"));
-// }
-//
-// @Test
-// public void test_Send_NoRequestContent_Exception() throws Exception
-// {
-// ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
-// // Shutdown output to trigger the exception on write
-// endPoint.shutdownOutput();
-// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
-// HttpConnection connection = new HttpConnection(client, endPoint, destination);
-// Request request = client.newRequest(URI.create("http://localhost/"));
-// final CountDownLatch failureLatch = new CountDownLatch(2);
-// request.listener(new Request.Listener.Adapter()
-// {
-// @Override
-// public void onFailure(Request request, Throwable x)
-// {
-// failureLatch.countDown();
-// }
-// });
-// connection.send(request, new Response.Listener.Adapter()
-// {
-// @Override
-// public void onComplete(Result result)
-// {
-// Assert.assertTrue(result.isFailed());
-// failureLatch.countDown();
-// }
-// });
-//
-// Assert.assertTrue(failureLatch.await(5, TimeUnit.SECONDS));
-// }
-//
-// @Test
-// public void test_Send_NoRequestContent_IncompleteFlush_Exception() throws Exception
-// {
-// ByteArrayEndPoint endPoint = new ByteArrayEndPoint("", 16);
-// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
-// HttpConnection connection = new HttpConnection(client, endPoint, destination);
-// Request request = client.newRequest(URI.create("http://localhost/"));
-// final CountDownLatch failureLatch = new CountDownLatch(2);
-// request.listener(new Request.Listener.Adapter()
-// {
-// @Override
-// public void onFailure(Request request, Throwable x)
-// {
-// failureLatch.countDown();
-// }
-// });
-// connection.send(request, new Response.Listener.Adapter()
-// {
-// @Override
-// public void onComplete(Result result)
-// {
-// Assert.assertTrue(result.isFailed());
-// failureLatch.countDown();
-// }
-// });
-//
-// // Shutdown output to trigger the exception on write
-// endPoint.shutdownOutput();
-// // This take will free space in the buffer and allow for the write to complete
-// // although it will fail because we shut down the output
-// endPoint.takeOutputString();
-//
-// Assert.assertTrue(failureLatch.await(5, TimeUnit.SECONDS));
-// }
-//
-// @Test
-// public void test_Send_SmallRequestContent_InOneBuffer() throws Exception
-// {
-// ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
-// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
-// HttpConnection connection = new HttpConnection(client, endPoint, destination);
-// Request request = client.newRequest(URI.create("http://localhost/"));
-// String content = "abcdef";
-// request.content(new ByteBufferContentProvider(ByteBuffer.wrap(content.getBytes(StandardCharsets.UTF_8))));
-// final CountDownLatch headersLatch = new CountDownLatch(1);
-// final CountDownLatch successLatch = new CountDownLatch(1);
-// request.listener(new Request.Listener.Adapter()
-// {
-// @Override
-// public void onHeaders(Request request)
-// {
-// headersLatch.countDown();
-// }
-//
-// @Override
-// public void onSuccess(Request request)
-// {
-// successLatch.countDown();
-// }
-// });
-// connection.send(request, (Response.CompleteListener)null);
-//
-// String requestString = endPoint.takeOutputString();
-// Assert.assertTrue(requestString.startsWith("GET "));
-// Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content));
-// Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
-// Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
-// }
-//
-// @Test
-// public void test_Send_SmallRequestContent_InTwoBuffers() throws Exception
-// {
-// ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
-// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
-// HttpConnection connection = new HttpConnection(client, endPoint, destination);
-// Request request = client.newRequest(URI.create("http://localhost/"));
-// String content1 = "0123456789";
-// String content2 = "abcdef";
-// request.content(new ByteBufferContentProvider(ByteBuffer.wrap(content1.getBytes(StandardCharsets.UTF_8)), ByteBuffer.wrap(content2.getBytes(StandardCharsets.UTF_8))));
-// final CountDownLatch headersLatch = new CountDownLatch(1);
-// final CountDownLatch successLatch = new CountDownLatch(1);
-// request.listener(new Request.Listener.Adapter()
-// {
-// @Override
-// public void onHeaders(Request request)
-// {
-// headersLatch.countDown();
-// }
-//
-// @Override
-// public void onSuccess(Request request)
-// {
-// successLatch.countDown();
-// }
-// });
-// connection.send(request, (Response.CompleteListener)null);
-//
-// String requestString = endPoint.takeOutputString();
-// Assert.assertTrue(requestString.startsWith("GET "));
-// Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content1 + content2));
-// Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
-// Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
-// }
-//
-// @Test
-// public void test_Send_SmallRequestContent_Chunked_InTwoChunks() throws Exception
-// {
-// ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
-// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
-// HttpConnection connection = new HttpConnection(client, endPoint, destination);
-// Request request = client.newRequest(URI.create("http://localhost/"));
-// String content1 = "0123456789";
-// String content2 = "ABCDEF";
-// request.content(new ByteBufferContentProvider(ByteBuffer.wrap(content1.getBytes(StandardCharsets.UTF_8)), ByteBuffer.wrap(content2.getBytes(StandardCharsets.UTF_8)))
-// {
-// @Override
-// public long getLength()
-// {
-// return -1;
-// }
-// });
-// final CountDownLatch headersLatch = new CountDownLatch(1);
-// final CountDownLatch successLatch = new CountDownLatch(1);
-// request.listener(new Request.Listener.Adapter()
-// {
-// @Override
-// public void onHeaders(Request request)
-// {
-// headersLatch.countDown();
-// }
-//
-// @Override
-// public void onSuccess(Request request)
-// {
-// successLatch.countDown();
-// }
-// });
-// connection.send(request, (Response.CompleteListener)null);
-//
-// String requestString = endPoint.takeOutputString();
-// Assert.assertTrue(requestString.startsWith("GET "));
-// String content = Integer.toHexString(content1.length()).toUpperCase(Locale.ENGLISH) + "\r\n" + content1 + "\r\n";
-// content += Integer.toHexString(content2.length()).toUpperCase(Locale.ENGLISH) + "\r\n" + content2 + "\r\n";
-// content += "0\r\n\r\n";
-// Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content));
-// Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
-// Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
-// }
-}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java
new file mode 100644
index 0000000..0be2b91
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java
@@ -0,0 +1,262 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.client.http;
+
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.zip.GZIPOutputStream;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.HttpExchange;
+import org.eclipse.jetty.client.HttpRequest;
+import org.eclipse.jetty.client.HttpResponseException;
+import org.eclipse.jetty.client.Origin;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.client.api.Response;
+import org.eclipse.jetty.client.util.FutureResponseListener;
+import org.eclipse.jetty.http.HttpFields;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.http.HttpVersion;
+import org.eclipse.jetty.io.ByteArrayEndPoint;
+import org.eclipse.jetty.toolchain.test.TestTracker;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class HttpReceiverOverHTTPTest
+{
+ @Rule
+ public final TestTracker tracker = new TestTracker();
+
+ private HttpClient client;
+ private HttpDestinationOverHTTP destination;
+ private ByteArrayEndPoint endPoint;
+ private HttpConnectionOverHTTP connection;
+
+ @Before
+ public void init() throws Exception
+ {
+ client = new HttpClient();
+ client.start();
+ destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
+ endPoint = new ByteArrayEndPoint();
+ connection = new HttpConnectionOverHTTP(endPoint, destination);
+ }
+
+ @After
+ public void destroy() throws Exception
+ {
+ client.stop();
+ }
+
+ protected HttpExchange newExchange()
+ {
+ HttpRequest request = (HttpRequest)client.newRequest("http://localhost");
+ FutureResponseListener listener = new FutureResponseListener(request);
+ HttpExchange exchange = new HttpExchange(destination, request, Collections.<Response.ResponseListener>singletonList(listener));
+ connection.getHttpChannel().associate(exchange);
+ exchange.requestComplete();
+ exchange.terminateRequest(null);
+ return exchange;
+ }
+
+ @Test
+ public void test_Receive_NoResponseContent() throws Exception
+ {
+ endPoint.setInput("" +
+ "HTTP/1.1 200 OK\r\n" +
+ "Content-length: 0\r\n" +
+ "\r\n");
+ HttpExchange exchange = newExchange();
+ FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
+ connection.getHttpChannel().receive();
+
+ Response response = listener.get(5, TimeUnit.SECONDS);
+ Assert.assertNotNull(response);
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("OK", response.getReason());
+ Assert.assertSame(HttpVersion.HTTP_1_1, response.getVersion());
+ HttpFields headers = response.getHeaders();
+ Assert.assertNotNull(headers);
+ Assert.assertEquals(1, headers.size());
+ Assert.assertEquals("0", headers.get(HttpHeader.CONTENT_LENGTH));
+ }
+
+ @Test
+ public void test_Receive_ResponseContent() throws Exception
+ {
+ String content = "0123456789ABCDEF";
+ endPoint.setInput("" +
+ "HTTP/1.1 200 OK\r\n" +
+ "Content-length: " + content.length() + "\r\n" +
+ "\r\n" +
+ content);
+ HttpExchange exchange = newExchange();
+ FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
+ connection.getHttpChannel().receive();
+
+ Response response = listener.get(5, TimeUnit.SECONDS);
+ Assert.assertNotNull(response);
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals("OK", response.getReason());
+ Assert.assertSame(HttpVersion.HTTP_1_1, response.getVersion());
+ HttpFields headers = response.getHeaders();
+ Assert.assertNotNull(headers);
+ Assert.assertEquals(1, headers.size());
+ Assert.assertEquals(String.valueOf(content.length()), headers.get(HttpHeader.CONTENT_LENGTH));
+ String received = listener.getContentAsString(StandardCharsets.UTF_8);
+ Assert.assertEquals(content, received);
+ }
+
+ @Test
+ public void test_Receive_ResponseContent_EarlyEOF() throws Exception
+ {
+ String content1 = "0123456789";
+ String content2 = "ABCDEF";
+ endPoint.setInput("" +
+ "HTTP/1.1 200 OK\r\n" +
+ "Content-length: " + (content1.length() + content2.length()) + "\r\n" +
+ "\r\n" +
+ content1);
+ HttpExchange exchange = newExchange();
+ FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
+ connection.getHttpChannel().receive();
+ endPoint.setInputEOF();
+ connection.getHttpChannel().receive();
+
+ try
+ {
+ listener.get(5, TimeUnit.SECONDS);
+ Assert.fail();
+ }
+ catch (ExecutionException e)
+ {
+ Assert.assertTrue(e.getCause() instanceof EOFException);
+ }
+ }
+
+ @Test
+ public void test_Receive_ResponseContent_IdleTimeout() throws Exception
+ {
+ endPoint.setInput("" +
+ "HTTP/1.1 200 OK\r\n" +
+ "Content-length: 1\r\n" +
+ "\r\n");
+ HttpExchange exchange = newExchange();
+ FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
+ connection.getHttpChannel().receive();
+ // Simulate an idle timeout
+ connection.onReadTimeout();
+
+ try
+ {
+ listener.get(5, TimeUnit.SECONDS);
+ Assert.fail();
+ }
+ catch (ExecutionException e)
+ {
+ Assert.assertTrue(e.getCause() instanceof TimeoutException);
+ }
+ }
+
+ @Test
+ public void test_Receive_BadResponse() throws Exception
+ {
+ endPoint.setInput("" +
+ "HTTP/1.1 200 OK\r\n" +
+ "Content-length: A\r\n" +
+ "\r\n");
+ HttpExchange exchange = newExchange();
+ FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
+ connection.getHttpChannel().receive();
+
+ try
+ {
+ listener.get(5, TimeUnit.SECONDS);
+ Assert.fail();
+ }
+ catch (ExecutionException e)
+ {
+ Assert.assertTrue(e.getCause() instanceof HttpResponseException);
+ }
+ }
+
+ @Test
+ public void test_Receive_GZIPResponseContent_Fragmented() throws Exception
+ {
+ byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (GZIPOutputStream gzipOutput = new GZIPOutputStream(baos))
+ {
+ gzipOutput.write(data);
+ }
+ byte[] gzip = baos.toByteArray();
+
+ endPoint.setInput("" +
+ "HTTP/1.1 200 OK\r\n" +
+ "Content-Length: " + gzip.length + "\r\n" +
+ "Content-Encoding: gzip\r\n" +
+ "\r\n");
+
+ HttpRequest request = (HttpRequest)client.newRequest("http://localhost");
+ final CountDownLatch latch = new CountDownLatch(1);
+ FutureResponseListener listener = new FutureResponseListener(request)
+ {
+ @Override
+ public void onContent(Response response, ByteBuffer content)
+ {
+ super.onContent(response, content);
+ latch.countDown();
+ }
+ };
+ HttpExchange exchange = new HttpExchange(destination, request, Collections.<Response.ResponseListener>singletonList(listener));
+ connection.getHttpChannel().associate(exchange);
+ exchange.requestComplete();
+ exchange.terminateRequest(null);
+ connection.getHttpChannel().receive();
+ endPoint.reset();
+
+ ByteBuffer buffer = ByteBuffer.wrap(gzip);
+ int fragment = buffer.limit() - 1;
+ buffer.limit(fragment);
+ endPoint.setInput(buffer);
+ connection.getHttpChannel().receive();
+ endPoint.reset();
+
+ buffer.limit(gzip.length);
+ buffer.position(fragment);
+ endPoint.setInput(buffer);
+ connection.getHttpChannel().receive();
+
+ ContentResponse response = listener.get(5, TimeUnit.SECONDS);
+ Assert.assertNotNull(response);
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
+ Assert.assertArrayEquals(data, response.getContent());
+ }
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpSenderOverHTTPTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpSenderOverHTTPTest.java
new file mode 100644
index 0000000..afe1ec7
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpSenderOverHTTPTest.java
@@ -0,0 +1,302 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.client.http;
+
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Locale;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.Origin;
+import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.client.api.Response;
+import org.eclipse.jetty.client.api.Result;
+import org.eclipse.jetty.client.util.ByteBufferContentProvider;
+import org.eclipse.jetty.io.ByteArrayEndPoint;
+import org.eclipse.jetty.toolchain.test.TestTracker;
+import org.eclipse.jetty.toolchain.test.annotation.Slow;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class HttpSenderOverHTTPTest
+{
+ @Rule
+ public final TestTracker tracker = new TestTracker();
+
+ private HttpClient client;
+
+ @Before
+ public void init() throws Exception
+ {
+ client = new HttpClient();
+ client.start();
+ }
+
+ @After
+ public void destroy() throws Exception
+ {
+ client.stop();
+ }
+
+ @Test
+ public void test_Send_NoRequestContent() throws Exception
+ {
+ ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
+ HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
+ HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
+ Request request = client.newRequest(URI.create("http://localhost/"));
+ final CountDownLatch headersLatch = new CountDownLatch(1);
+ final CountDownLatch successLatch = new CountDownLatch(1);
+ request.listener(new Request.Listener.Adapter()
+ {
+ @Override
+ public void onHeaders(Request request)
+ {
+ headersLatch.countDown();
+ }
+
+ @Override
+ public void onSuccess(Request request)
+ {
+ successLatch.countDown();
+ }
+ });
+ connection.send(request, null);
+
+ String requestString = endPoint.takeOutputString();
+ Assert.assertTrue(requestString.startsWith("GET "));
+ Assert.assertTrue(requestString.endsWith("\r\n\r\n"));
+ Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
+ }
+
+ @Slow
+ @Test
+ public void test_Send_NoRequestContent_IncompleteFlush() throws Exception
+ {
+ ByteArrayEndPoint endPoint = new ByteArrayEndPoint("", 16);
+ HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
+ HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
+ Request request = client.newRequest(URI.create("http://localhost/"));
+ connection.send(request, null);
+
+ // This take will free space in the buffer and allow for the write to complete
+ StringBuilder builder = new StringBuilder(endPoint.takeOutputString());
+
+ // Wait for the write to complete
+ TimeUnit.SECONDS.sleep(1);
+
+ String chunk = endPoint.takeOutputString();
+ while (chunk.length() > 0)
+ {
+ builder.append(chunk);
+ chunk = endPoint.takeOutputString();
+ }
+
+ String requestString = builder.toString();
+ Assert.assertTrue(requestString.startsWith("GET "));
+ Assert.assertTrue(requestString.endsWith("\r\n\r\n"));
+ }
+
+ @Test
+ public void test_Send_NoRequestContent_Exception() throws Exception
+ {
+ ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
+ // Shutdown output to trigger the exception on write
+ endPoint.shutdownOutput();
+ HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
+ HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
+ Request request = client.newRequest(URI.create("http://localhost/"));
+ final CountDownLatch failureLatch = new CountDownLatch(2);
+ request.listener(new Request.Listener.Adapter()
+ {
+ @Override
+ public void onFailure(Request request, Throwable x)
+ {
+ failureLatch.countDown();
+ }
+ });
+ connection.send(request, new Response.Listener.Adapter()
+ {
+ @Override
+ public void onComplete(Result result)
+ {
+ Assert.assertTrue(result.isFailed());
+ failureLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(failureLatch.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void test_Send_NoRequestContent_IncompleteFlush_Exception() throws Exception
+ {
+ ByteArrayEndPoint endPoint = new ByteArrayEndPoint("", 16);
+ HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
+ HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
+ Request request = client.newRequest(URI.create("http://localhost/"));
+ final CountDownLatch failureLatch = new CountDownLatch(2);
+ request.listener(new Request.Listener.Adapter()
+ {
+ @Override
+ public void onFailure(Request request, Throwable x)
+ {
+ failureLatch.countDown();
+ }
+ });
+ connection.send(request, new Response.Listener.Adapter()
+ {
+ @Override
+ public void onComplete(Result result)
+ {
+ Assert.assertTrue(result.isFailed());
+ failureLatch.countDown();
+ }
+ });
+
+ // Shutdown output to trigger the exception on write
+ endPoint.shutdownOutput();
+ // This take will free space in the buffer and allow for the write to complete
+ // although it will fail because we shut down the output
+ endPoint.takeOutputString();
+
+ Assert.assertTrue(failureLatch.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void test_Send_SmallRequestContent_InOneBuffer() throws Exception
+ {
+ ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
+ HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
+ HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
+ Request request = client.newRequest(URI.create("http://localhost/"));
+ String content = "abcdef";
+ request.content(new ByteBufferContentProvider(ByteBuffer.wrap(content.getBytes(StandardCharsets.UTF_8))));
+ final CountDownLatch headersLatch = new CountDownLatch(1);
+ final CountDownLatch successLatch = new CountDownLatch(1);
+ request.listener(new Request.Listener.Adapter()
+ {
+ @Override
+ public void onHeaders(Request request)
+ {
+ headersLatch.countDown();
+ }
+
+ @Override
+ public void onSuccess(Request request)
+ {
+ successLatch.countDown();
+ }
+ });
+ connection.send(request, null);
+
+ String requestString = endPoint.takeOutputString();
+ Assert.assertTrue(requestString.startsWith("GET "));
+ Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content));
+ Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void test_Send_SmallRequestContent_InTwoBuffers() throws Exception
+ {
+ ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
+ HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
+ HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
+ Request request = client.newRequest(URI.create("http://localhost/"));
+ String content1 = "0123456789";
+ String content2 = "abcdef";
+ request.content(new ByteBufferContentProvider(ByteBuffer.wrap(content1.getBytes(StandardCharsets.UTF_8)), ByteBuffer.wrap(content2.getBytes(StandardCharsets.UTF_8))));
+ final CountDownLatch headersLatch = new CountDownLatch(1);
+ final CountDownLatch successLatch = new CountDownLatch(1);
+ request.listener(new Request.Listener.Adapter()
+ {
+ @Override
+ public void onHeaders(Request request)
+ {
+ headersLatch.countDown();
+ }
+
+ @Override
+ public void onSuccess(Request request)
+ {
+ successLatch.countDown();
+ }
+ });
+ connection.send(request, null);
+
+ String requestString = endPoint.takeOutputString();
+ Assert.assertTrue(requestString.startsWith("GET "));
+ Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content1 + content2));
+ Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void test_Send_SmallRequestContent_Chunked_InTwoChunks() throws Exception
+ {
+ ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
+ HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
+ HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
+ Request request = client.newRequest(URI.create("http://localhost/"));
+ String content1 = "0123456789";
+ String content2 = "ABCDEF";
+ request.content(new ByteBufferContentProvider(ByteBuffer.wrap(content1.getBytes(StandardCharsets.UTF_8)), ByteBuffer.wrap(content2.getBytes(StandardCharsets.UTF_8)))
+ {
+ @Override
+ public long getLength()
+ {
+ return -1;
+ }
+ });
+ final CountDownLatch headersLatch = new CountDownLatch(1);
+ final CountDownLatch successLatch = new CountDownLatch(1);
+ request.listener(new Request.Listener.Adapter()
+ {
+ @Override
+ public void onHeaders(Request request)
+ {
+ headersLatch.countDown();
+ }
+
+ @Override
+ public void onSuccess(Request request)
+ {
+ successLatch.countDown();
+ }
+ });
+ connection.send(request, null);
+
+ String requestString = endPoint.takeOutputString();
+ Assert.assertTrue(requestString.startsWith("GET "));
+ String content = Integer.toHexString(content1.length()).toUpperCase(Locale.ENGLISH) + "\r\n" + content1 + "\r\n";
+ content += Integer.toHexString(content2.length()).toUpperCase(Locale.ENGLISH) + "\r\n" + content2 + "\r\n";
+ content += "0\r\n\r\n";
+ Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content));
+ Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
+ }
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java
index c360f70..bdef5f2 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java
@@ -77,6 +77,7 @@
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
public class SslBytesServerTest extends SslBytesTest
@@ -237,7 +238,7 @@
threadPool.shutdownNow();
}
- @Test
+ @Test(timeout=10000)
public void testHandshake() throws Exception
{
final SSLSocket client = newClient();
@@ -1390,7 +1391,9 @@
closeClient(client);
}
- @Test
+ // TODO work out why this test frequently fails
+ @Ignore
+ @Test(timeout=10000)
public void testRequestWithContentWithRenegotiationInMiddleOfContentWhenRenegotiationIsForbidden() throws Exception
{
assumeJavaVersionSupportsTLSRenegotiations();
@@ -1616,7 +1619,7 @@
closeClient(client);
}
- @Test
+ @Test(timeout=10000)
public void testRequestWithBigContentWithRenegotiationInMiddleOfContentWithSplitBoundary() throws Exception
{
assumeJavaVersionSupportsTLSRenegotiations();
diff --git a/jetty-continuation/pom.xml b/jetty-continuation/pom.xml
index e7219dc..a926837 100644
--- a/jetty-continuation/pom.xml
+++ b/jetty-continuation/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-continuation</artifactId>
diff --git a/jetty-deploy/pom.xml b/jetty-deploy/pom.xml
index 979acb0..0325c56 100644
--- a/jetty-deploy/pom.xml
+++ b/jetty-deploy/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-deploy</artifactId>
diff --git a/jetty-distribution/pom.xml b/jetty-distribution/pom.xml
index 5e43fa7..5003e02 100644
--- a/jetty-distribution/pom.xml
+++ b/jetty-distribution/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<artifactId>jetty-distribution</artifactId>
<name>Jetty :: Distribution Assemblies</name>
@@ -302,7 +302,7 @@
<configuration>
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
<excludeGroupIds>org.eclipse.jetty.orbit,org.eclipse.jetty.spdy,org.eclipse.jetty.websocket,org.eclipse.jetty.fcgi,org.eclipse.jetty.toolchain,org.apache.taglibs</excludeGroupIds>
- <excludeArtifactIds>jetty-all,jetty-jsp,jetty-start,jetty-monitor</excludeArtifactIds>
+ <excludeArtifactIds>jetty-all,jetty-jsp,apache-jsp,jetty-start,jetty-monitor</excludeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</configuration>
@@ -458,6 +458,20 @@
</configuration>
</execution>
<execution>
+ <id>copy-apache-jsp-deps</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <includeGroupIds>org.eclipse.jetty,org.eclipse.jetty.toolchain,javax.servlet.jsp,org.mortbay.jasper,org.mortbay.jasper,org.eclipse.jetty.orbit</includeGroupIds>
+ <includeArtifactIds>apache-jsp,javax.servlet.jsp-api,apache-el,org.eclipse.jdt.core</includeArtifactIds>
+ <includeTypes>jar</includeTypes>
+ <prependGroupId>true</prependGroupId>
+ <outputDirectory>${assembly-directory}/lib/apache-jsp</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
<id>copy-jstl-api</id>
<phase>generate-resources</phase>
<goals>
@@ -485,6 +499,20 @@
</configuration>
</execution>
<execution>
+ <id>copy-apache-jstl-deps</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <excludeGroupIds>org.glassfish.web</excludeGroupIds>
+ <includeArtifactIds>taglibs-standard-spec,taglibs-standard-impl</includeArtifactIds>
+ <prependGroupId>true</prependGroupId>
+ <includeTypes>jar</includeTypes>
+ <outputDirectory>${assembly-directory}/lib/apache-jstl</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
<id>copy-jaspi-deps</id>
<phase>generate-resources</phase>
<goals>
@@ -526,7 +554,7 @@
<argument>jetty.home=${assembly-directory}</argument>
<argument>jetty.base=${assembly-directory}</argument>
<argument>--add-to-start=server,deploy,websocket,ext,resources</argument>
- <argument>--add-to-startd=jsp,http</argument>
+ <argument>--add-to-startd=jsp,jstl,http</argument>
</arguments>
</configuration>
<goals>
@@ -541,8 +569,8 @@
<arguments>
<argument>jetty.home=${assembly-directory}</argument>
<argument>jetty.base=${assembly-directory}/demo-base</argument>
- <argument>--add-to-start=server,continuation,deploy,ext,resources,client,annotations,jndi,servlets</argument>
- <argument>--add-to-startd-ini=jsp,http,https</argument>
+ <argument>--add-to-start=server,continuation,deploy,websocket,ext,resources,client,annotations,jndi,servlets</argument>
+ <argument>--add-to-startd-ini=jsp,jstl,http,https</argument>
</arguments>
</configuration>
<goals>
@@ -669,6 +697,11 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-quickstart</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-start</artifactId>
<version>${project.version}</version>
</dependency>
@@ -699,6 +732,16 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
+ <artifactId>apache-jsp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>apache-jstl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>
<version>${project.version}</version>
</dependency>
@@ -766,6 +809,11 @@
<type>war</type>
</dependency>
<dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-alpn-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.eclipse.jetty.example-async-rest</groupId>
<artifactId>example-async-rest-webapp</artifactId>
<version>${project.version}</version>
diff --git a/jetty-distribution/src/main/resources/modules/jsp.mod b/jetty-distribution/src/main/resources/modules/jsp.mod
new file mode 100644
index 0000000..4924ed9
--- /dev/null
+++ b/jetty-distribution/src/main/resources/modules/jsp.mod
@@ -0,0 +1,20 @@
+#
+# Jetty JSP Module
+#
+
+[depend]
+servlet
+jsp-impl/${jsp-impl}-jsp
+
+[ini-template]
+# JSP Configuration
+
+# Select JSP implementation, choices are
+# glassfish : The reference implementation
+# default in jetty <= 9.1
+# apache : The apache version
+# default jetty >= 9.2
+jsp-impl=apache
+
+# To use an non-jdk compiler for JSP compilation uncomment next line
+# -Dorg.apache.jasper.compiler.disablejsr199=true
diff --git a/jetty-distribution/src/main/resources/modules/jstl.mod b/jetty-distribution/src/main/resources/modules/jstl.mod
new file mode 100644
index 0000000..cb06244
--- /dev/null
+++ b/jetty-distribution/src/main/resources/modules/jstl.mod
@@ -0,0 +1,14 @@
+#
+# Jetty JSP Module
+#
+
+[depend]
+jsp
+jsp-impl/${jsp-impl}-jstl
+
+[ini-template]
+# JSTL Configuration
+# The glassfish jsp-impl includes JSTL by default and this module
+# is not required to activate it.
+# The apache jsp-impl does not include JSTL by default and this module
+# is required to put JSTL on the container classpath
diff --git a/jetty-distribution/src/main/resources/modules/protonego.mod b/jetty-distribution/src/main/resources/modules/protonego.mod
new file mode 100644
index 0000000..d7bba9f
--- /dev/null
+++ b/jetty-distribution/src/main/resources/modules/protonego.mod
@@ -0,0 +1,15 @@
+#
+# Protocol Negotiatin Selection Module
+#
+
+[depend]
+protonego-impl/${protonego}
+
+[ini-template]
+# Protocol Negotiation Implementation Selection
+# choices are:
+# 'npn' : original implementation for SPDY (now deprecated)
+# 'alpn' : replacement for NPN, in use by current SPDY implementations
+# and the future HTTP/2 spec
+# Note: java 1.8+ are ALPN only.
+protonego=alpn
diff --git a/jetty-fcgi/fcgi-client/pom.xml b/jetty-fcgi/fcgi-client/pom.xml
index aeb2d6d..fc7542e 100644
--- a/jetty-fcgi/fcgi-client/pom.xml
+++ b/jetty-fcgi/fcgi-client/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-fcgi/fcgi-distribution/pom.xml b/jetty-fcgi/fcgi-distribution/pom.xml
index c265796..81d03d9 100644
--- a/jetty-fcgi/fcgi-distribution/pom.xml
+++ b/jetty-fcgi/fcgi-distribution/pom.xml
@@ -5,7 +5,7 @@
<parent>
<artifactId>fcgi-parent</artifactId>
<groupId>org.eclipse.jetty.fcgi</groupId>
- <version>9.1.4-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-fcgi/fcgi-http-client-transport/pom.xml b/jetty-fcgi/fcgi-http-client-transport/pom.xml
index 61fe9fe..d911c12 100644
--- a/jetty-fcgi/fcgi-http-client-transport/pom.xml
+++ b/jetty-fcgi/fcgi-http-client-transport/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-parent</artifactId>
- <version>9.1.4-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-fcgi/fcgi-proxy/pom.xml b/jetty-fcgi/fcgi-proxy/pom.xml
index d313dc7..149d189 100644
--- a/jetty-fcgi/fcgi-proxy/pom.xml
+++ b/jetty-fcgi/fcgi-proxy/pom.xml
@@ -5,7 +5,7 @@
<parent>
<artifactId>fcgi-parent</artifactId>
<groupId>org.eclipse.jetty.fcgi</groupId>
- <version>9.1.4-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-fcgi/fcgi-server/pom.xml b/jetty-fcgi/fcgi-server/pom.xml
index 9335f29..4b343cb 100644
--- a/jetty-fcgi/fcgi-server/pom.xml
+++ b/jetty-fcgi/fcgi-server/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-fcgi/pom.xml b/jetty-fcgi/pom.xml
index 1812d57..d309fec 100644
--- a/jetty-fcgi/pom.xml
+++ b/jetty-fcgi/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-http-spi/pom.xml b/jetty-http-spi/pom.xml
index 3697bbd..a21e2e3 100644
--- a/jetty-http-spi/pom.xml
+++ b/jetty-http-spi/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http-spi</artifactId>
diff --git a/jetty-http/pom.xml b/jetty-http/pom.xml
index 0681b33..67d85ac 100644
--- a/jetty-http/pom.xml
+++ b/jetty-http/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http</artifactId>
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpMethod.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpMethod.java
index ef13232..8a26268 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpMethod.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpMethod.java
@@ -38,7 +38,8 @@
DELETE,
TRACE,
CONNECT,
- MOVE;
+ MOVE,
+ PROXY;
/* ------------------------------------------------------------ */
/**
@@ -48,7 +49,7 @@
* @param limit The first non valid index
* @return A HttpMethod if a match or null if no easy match.
*/
- public static HttpMethod lookAheadGet(byte[] bytes, int position, int limit)
+ public static HttpMethod lookAheadGet(byte[] bytes, final int position, int limit)
{
int length=limit-position;
if (length<4)
@@ -62,6 +63,8 @@
case 'P':
if (bytes[position+1]=='O' && bytes[position+2]=='S' && bytes[position+3]=='T' && length>=5 && bytes[position+4]==' ')
return POST;
+ if (bytes[position+1]=='R' && bytes[position+2]=='O' && bytes[position+3]=='X' && length>=6 && bytes[position+4]=='Y' && bytes[position+5]==' ')
+ return PROXY;
if (bytes[position+1]=='U' && bytes[position+2]=='T' && bytes[position+3]==' ')
return PUT;
break;
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
index 8443f67..ee40a74 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
@@ -104,6 +104,7 @@
SPACE2,
REQUEST_VERSION,
REASON,
+ PROXY,
HEADER,
HEADER_IN_NAME,
HEADER_VALUE,
@@ -403,7 +404,7 @@
* otherwise skip white space until something else to parse.
*/
private boolean quickStart(ByteBuffer buffer)
- {
+ {
if (_requestHandler!=null)
{
_method = HttpMethod.lookAheadGet(buffer);
@@ -411,6 +412,7 @@
{
_methodString = _method.asString();
buffer.position(buffer.position()+_methodString.length()+1);
+
setState(State.SPACE1);
return false;
}
@@ -655,7 +657,29 @@
version=HttpVersion.lookAheadGet(buffer.array(),buffer.arrayOffset()+buffer.position()-1,buffer.arrayOffset()+buffer.limit());
else
version=HttpVersion.CACHE.getBest(buffer,0,buffer.remaining());
- if (version!=null)
+ if (version==null)
+ {
+ if (_method==HttpMethod.PROXY)
+ {
+ if (!(_requestHandler instanceof ProxyHandler))
+ throw new BadMessage();
+
+ _uri.flip();
+ String protocol=BufferUtil.toString(_uri);
+ // This is the proxy protocol, so we can assume entire first line is in buffer else 400
+ buffer.position(buffer.position()-1);
+ String sAddr = getProxyField(buffer);
+ String dAddr = getProxyField(buffer);
+ int sPort = BufferUtil.takeInt(buffer);
+ next(buffer);
+ int dPort = BufferUtil.takeInt(buffer);
+ next(buffer);
+ _state=State.START;
+ ((ProxyHandler)_requestHandler).proxied(protocol,sAddr,dAddr,sPort,dPort);
+ return false;
+ }
+ }
+ else
{
int pos = buffer.position()+version.asString().length()-1;
if (pos<buffer.limit())
@@ -715,8 +739,7 @@
if (_connectionFields==null && _version.getVersion()>=HttpVersion.HTTP_1_1.getVersion())
{
int header_cache = _handler.getHeaderCacheSize();
- if (header_cache>0)
- _connectionFields=new ArrayTernaryTrie<>(header_cache);
+ _connectionFields=new ArrayTernaryTrie<>(header_cache);
}
setState(State.HEADER);
@@ -1334,24 +1357,36 @@
protected boolean parseContent(ByteBuffer buffer)
{
+ int remaining=buffer.remaining();
+ if (remaining==0 && _state==State.CONTENT)
+ {
+ long content=_contentLength - _contentPosition;
+ if (content == 0)
+ {
+ setState(State.END);
+ if (_handler.messageComplete())
+ return true;
+ }
+ }
+
// Handle _content
byte ch;
- while (_state.ordinal() < State.END.ordinal() && buffer.hasRemaining())
+ while (_state.ordinal() < State.END.ordinal() && remaining>0)
{
switch (_state)
{
case EOF_CONTENT:
_contentChunk=buffer.asReadOnlyBuffer();
- _contentPosition += _contentChunk.remaining();
- buffer.position(buffer.position()+_contentChunk.remaining());
+ _contentPosition += remaining;
+ buffer.position(buffer.position()+remaining);
if (_handler.content(_contentChunk))
return true;
break;
case CONTENT:
{
- long remaining=_contentLength - _contentPosition;
- if (remaining == 0)
+ long content=_contentLength - _contentPosition;
+ if (content == 0)
{
setState(State.END);
if (_handler.messageComplete())
@@ -1362,25 +1397,25 @@
_contentChunk=buffer.asReadOnlyBuffer();
// limit content by expected size
- if (_contentChunk.remaining() > remaining)
+ if (remaining > content)
{
// We can cast remaining to an int as we know that it is smaller than
// or equal to length which is already an int.
- _contentChunk.limit(_contentChunk.position()+(int)remaining);
+ _contentChunk.limit(_contentChunk.position()+(int)content);
}
_contentPosition += _contentChunk.remaining();
buffer.position(buffer.position()+_contentChunk.remaining());
- boolean handle=_handler.content(_contentChunk);
+ if (_handler.content(_contentChunk))
+ return true;
+
if(_contentPosition == _contentLength)
{
setState(State.END);
if (_handler.messageComplete())
return true;
}
- if (handle)
- return true;
}
break;
}
@@ -1440,8 +1475,8 @@
case CHUNK:
{
- int remaining=_chunkLength - _chunkPosition;
- if (remaining == 0)
+ int chunk=_chunkLength - _chunkPosition;
+ if (chunk == 0)
{
setState(State.CHUNKED_CONTENT);
}
@@ -1449,13 +1484,13 @@
{
_contentChunk=buffer.asReadOnlyBuffer();
- if (_contentChunk.remaining() > remaining)
- _contentChunk.limit(_contentChunk.position()+remaining);
- remaining=_contentChunk.remaining();
+ if (remaining > chunk)
+ _contentChunk.limit(_contentChunk.position()+chunk);
+ chunk=_contentChunk.remaining();
- _contentPosition += remaining;
- _chunkPosition += remaining;
- buffer.position(buffer.position()+remaining);
+ _contentPosition += chunk;
+ _chunkPosition += chunk;
+ buffer.position(buffer.position()+chunk);
if (_handler.content(_contentChunk))
return true;
}
@@ -1470,7 +1505,10 @@
default:
break;
+
}
+
+ remaining=buffer.remaining();
}
return false;
}
@@ -1586,6 +1624,11 @@
public int getHeaderCacheSize();
}
+ public interface ProxyHandler
+ {
+ void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort);
+ }
+
public interface RequestHandler<T> extends HttpHandler<T>
{
/**
@@ -1618,4 +1661,20 @@
{
return _connectionFields;
}
+
+ private String getProxyField(ByteBuffer buffer)
+ {
+ _string.setLength(0);
+ _length=0;
+
+ while (buffer.hasRemaining())
+ {
+ // process each character
+ byte ch=next(buffer);
+ if (ch<=' ')
+ return _string.toString();
+ _string.append((char)ch);
+ }
+ throw new BadMessage();
+ }
}
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java
index 38c77af..6bc6ae2 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java
@@ -1398,6 +1398,63 @@
}
+ @Test
+ public void testProxyProtocol() throws Exception
+ {
+ ByteBuffer buffer=BufferUtil
+ .toBuffer("PROXY TCP4 107.47.45.254 10.0.1.116 27689 80\015\012"
+ +"GET / HTTP/1.1\015\012"
+ +"Host: localhost \015\012"
+ +"Connection: close\015\012"+"\015\012"+"\015\012");
+
+ Handler handler=new Handler();
+ HttpParser parser=new HttpParser((HttpParser.RequestHandler)handler);
+ parseAll(parser, buffer);
+
+ assertTrue(_headerCompleted);
+ assertTrue(_messageCompleted);
+ assertEquals("GET", _methodOrVersion);
+ assertEquals("/", _uriOrStatus);
+ assertEquals("HTTP/1.1", _versionOrReason);
+ assertEquals("PROXY TCP4 107.47.45.254 10.0.1.116 27689 80", handler._proxy);
+ assertEquals("Host", _hdr[0]);
+ assertEquals("localhost", _val[0]);
+ assertEquals("Connection", _hdr[1]);
+ assertEquals("close", _val[1]);
+ assertEquals(1, _headers);
+ }
+
+ @Test
+ public void testSplitProxyHeaderParseTest() throws Exception
+ {
+ Handler handler=new Handler();
+ HttpParser parser=new HttpParser((HttpParser.RequestHandler)handler);
+
+ ByteBuffer buffer=BufferUtil.toBuffer("PROXY TCP4 207.47.45.254 10.0.1.116 27689 80\015\012");
+ parser.parseNext(buffer);
+
+ buffer=BufferUtil.toBuffer(
+ "GET / HTTP/1.1\015\012"
+ +"Host: localhost \015\012"
+ +"Connection: close\015\012"
+ +"\015\012"
+ +"\015\012");
+
+ parser.parseNext(buffer);
+ assertTrue(_headerCompleted);
+ assertTrue(_messageCompleted);
+ assertEquals("GET", _methodOrVersion);
+ assertEquals("/", _uriOrStatus);
+ assertEquals("HTTP/1.1", _versionOrReason);
+ assertEquals("PROXY TCP4 207.47.45.254 10.0.1.116 27689 80", handler._proxy);
+ assertEquals("Host", _hdr[0]);
+ assertEquals("localhost", _val[0]);
+ assertEquals("Connection", _hdr[1]);
+ assertEquals("close", _val[1]);
+ assertEquals(1, _headers);
+ }
+
+
@Before
public void init()
{
@@ -1429,9 +1486,10 @@
private boolean _headerCompleted;
private boolean _messageCompleted;
- private class Handler implements HttpParser.RequestHandler<ByteBuffer>, HttpParser.ResponseHandler<ByteBuffer>
+ private class Handler implements HttpParser.RequestHandler<ByteBuffer>, HttpParser.ResponseHandler<ByteBuffer>, HttpParser.ProxyHandler
{
private HttpFields fields;
+ String _proxy;
@Override
public boolean content(ByteBuffer ref)
@@ -1539,5 +1597,11 @@
{
return 512;
}
+
+ @Override
+ public void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort)
+ {
+ _proxy="PROXY "+protocol+" "+sAddr+" "+dAddr+" "+sPort+" "+dPort;
+ }
}
}
diff --git a/jetty-io/pom.xml b/jetty-io/pom.xml
index d146f2e..c587972 100644
--- a/jetty-io/pom.xml
+++ b/jetty-io/pom.xml
@@ -2,7 +2,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-io</artifactId>
diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/NegotiatingClientConnection.java
similarity index 92%
rename from jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnection.java
rename to jetty-io/src/main/java/org/eclipse/jetty/io/NegotiatingClientConnection.java
index a2fc851..cd05630 100644
--- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnection.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/NegotiatingClientConnection.java
@@ -16,18 +16,13 @@
// ========================================================================
//
-package org.eclipse.jetty.spdy.client;
+package org.eclipse.jetty.io;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.Executor;
import javax.net.ssl.SSLEngine;
-import org.eclipse.jetty.io.AbstractConnection;
-import org.eclipse.jetty.io.ClientConnectionFactory;
-import org.eclipse.jetty.io.Connection;
-import org.eclipse.jetty.io.EndPoint;
-import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java b/jetty-io/src/main/java/org/eclipse/jetty/io/NegotiatingClientConnectionFactory.java
similarity index 92%
rename from jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java
rename to jetty-io/src/main/java/org/eclipse/jetty/io/NegotiatingClientConnectionFactory.java
index 50a1e5b..ff38600 100644
--- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/NegotiatingClientConnectionFactory.java
@@ -16,9 +16,8 @@
// ========================================================================
//
-package org.eclipse.jetty.spdy.client;
+package org.eclipse.jetty.io;
-import org.eclipse.jetty.io.ClientConnectionFactory;
public abstract class NegotiatingClientConnectionFactory implements ClientConnectionFactory
{
diff --git a/jetty-jaas/pom.xml b/jetty-jaas/pom.xml
index f8f57e6..ddc80f9 100644
--- a/jetty-jaas/pom.xml
+++ b/jetty-jaas/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jaas</artifactId>
diff --git a/jetty-jaspi/pom.xml b/jetty-jaspi/pom.xml
index e45825c..9f8fc89 100644
--- a/jetty-jaspi/pom.xml
+++ b/jetty-jaspi/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jaspi</artifactId>
diff --git a/jetty-jmx/pom.xml b/jetty-jmx/pom.xml
index 803d084..56a5cae 100644
--- a/jetty-jmx/pom.xml
+++ b/jetty-jmx/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jmx</artifactId>
diff --git a/jetty-jmx/src/main/config/modules/jmx.mod b/jetty-jmx/src/main/config/modules/jmx.mod
index f8cadb5..ee091c7 100644
--- a/jetty-jmx/src/main/config/modules/jmx.mod
+++ b/jetty-jmx/src/main/config/modules/jmx.mod
@@ -2,6 +2,9 @@
# JMX Module
#
+[depend]
+server
+
[lib]
lib/jetty-jmx-${jetty.version}.jar
diff --git a/jetty-jndi/pom.xml b/jetty-jndi/pom.xml
index 66ffd58..c40a600 100644
--- a/jetty-jndi/pom.xml
+++ b/jetty-jndi/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jndi</artifactId>
diff --git a/jetty-jsp/pom.xml b/jetty-jsp/pom.xml
index 21c1dca..c9002c2 100644
--- a/jetty-jsp/pom.xml
+++ b/jetty-jsp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jsp</artifactId>
diff --git a/jetty-jsp/src/main/config/modules/jsp-impl/glassfish-jsp.mod b/jetty-jsp/src/main/config/modules/jsp-impl/glassfish-jsp.mod
new file mode 100644
index 0000000..130d2b3
--- /dev/null
+++ b/jetty-jsp/src/main/config/modules/jsp-impl/glassfish-jsp.mod
@@ -0,0 +1,8 @@
+#
+# Glassfish JSP Module
+#
+[name]
+jsp-impl
+
+[lib]
+lib/jsp/*.jar
diff --git a/jetty-jsp/src/main/config/modules/jsp-impl/glassfish-jstl.mod b/jetty-jsp/src/main/config/modules/jsp-impl/glassfish-jstl.mod
new file mode 100644
index 0000000..4b8e6f3
--- /dev/null
+++ b/jetty-jsp/src/main/config/modules/jsp-impl/glassfish-jstl.mod
@@ -0,0 +1,6 @@
+#
+# Glassfish JSTL
+[name]
+jstl-impl
+
+# This file is empty as glassfish jstl is provided by glassfish jsp
diff --git a/jetty-jsp/src/main/config/modules/jsp.mod b/jetty-jsp/src/main/config/modules/jsp.mod
deleted file mode 100644
index b67dfe2..0000000
--- a/jetty-jsp/src/main/config/modules/jsp.mod
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Jetty JSP Module
-#
-
-[depend]
-servlet
-
-[lib]
-lib/jsp/*.jar
-
-[ini-template]
-# JSP Configuration
-# To use an non-jdk compiler for JSP compilation uncomment next line
-# -Dorg.apache.jasper.compiler.disablejsr199=true
diff --git a/jetty-jspc-maven-plugin/pom.xml b/jetty-jspc-maven-plugin/pom.xml
index ad5472a..2f709b2 100644
--- a/jetty-jspc-maven-plugin/pom.xml
+++ b/jetty-jspc-maven-plugin/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jspc-maven-plugin</artifactId>
@@ -73,8 +73,18 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>apache-jsp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ant</groupId>
+ <artifactId>ant</artifactId>
+ <version>1.8.4</version>
+ </dependency>
+ <dependency>
<groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-jsp</artifactId>
+ <artifactId>apache-jstl</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
diff --git a/jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java b/jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java
index 1e6d103..ac3e45f 100644
--- a/jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java
+++ b/jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java
@@ -79,6 +79,7 @@
public class JspcMojo extends AbstractMojo
{
public static final String END_OF_WEBAPP = "</web-app>";
+ public static final String PRECOMPILED_FLAG = "org.eclipse.jetty.jsp.precompiled";
/**
@@ -207,7 +208,7 @@
/**
* Patterns of jars on the system path that contain tlds. Use | to separate each pattern.
*
- * @parameter default-value=".*taglibs[^/]*\.jar|.*jstl-impl[^/]*\.jar$
+ * @parameter default-value=".*taglibs[^/]*\.jar|.*jstl[^/]*\.jar$
*/
private String tldJarNamePatterns;
@@ -294,9 +295,9 @@
jspc.setWebXmlFragment(webXmlFragment);
jspc.setUriroot(webAppSourceDirectory);
jspc.setOutputDir(generatedClasses);
- jspc.setClassPath(webAppClassPath.toString());
+ jspc.setClassPath(sysClassPath+System.getProperty("path.separator")+webAppClassPath.toString());
jspc.setCompile(true);
- jspc.setSystemClassPath(sysClassPath);
+ //jspc.setSystemClassPath(sysClassPath);
// JspC#setExtensions() does not exist, so
@@ -419,6 +420,10 @@
mergedWebXmlWriter.println(line);
}
}
+
+ //put in a context init-param to flag that the contents have been precompiled
+ mergedWebXmlWriter.println("<context-param><param-name>"+PRECOMPILED_FLAG+"</param-name><param-value>true</param-value></context-param>");
+
// put in the generated fragment
try (BufferedReader fragmentWebXmlReader = new BufferedReader(
@@ -541,13 +546,16 @@
*/
private List<URL> getSystemJarsWithTlds() throws Exception
{
+ getLog().debug("tld pattern=" + tldJarNamePatterns);
final List<URL> list = new ArrayList<URL>();
List<URI> artifactUris = new ArrayList<URI>();
Pattern pattern = Pattern.compile(tldJarNamePatterns);
for (Iterator<Artifact> iter = pluginArtifacts.iterator(); iter.hasNext(); )
{
Artifact pluginArtifact = iter.next();
- artifactUris.add(Resource.newResource(pluginArtifact.getFile()).getURI());
+ Resource res = Resource.newResource(pluginArtifact.getFile());
+ getLog().debug("scan jar: "+res.getURI());
+ artifactUris.add(res.getURI());
}
PatternMatcher matcher = new PatternMatcher()
diff --git a/jetty-maven-plugin/pom.xml b/jetty-maven-plugin/pom.xml
index b92a91f..eefa280 100644
--- a/jetty-maven-plugin/pom.xml
+++ b/jetty-maven-plugin/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-maven-plugin</artifactId>
@@ -122,19 +122,19 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-jsp</artifactId>
+ <artifactId>apache-jsp</artifactId>
<version>${project.version}</version>
</dependency>
- <!-- dependency>
- <groupId>org.eclipse.jetty.orbit</groupId>
- <artifactId>javax.activation</artifactId>
- <scope>compile</scope>
- </dependency -->
- <dependency>
- <groupId>javax.transaction</groupId>
- <artifactId>javax.transaction-api</artifactId>
- <scope>compile</scope>
- </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>apache-jstl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.transaction</groupId>
+ <artifactId>javax.transaction-api</artifactId>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
<reporting>
<plugins>
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 818073e..e4d8348 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
@@ -62,7 +62,7 @@
{
private static final Logger LOG = Log.getLogger(JettyWebAppContext.class);
- private static final String DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN = ".*/javax.servlet-[^/]*\\.jar$|.*/servlet-api-[^/]*\\.jar$";
+ private static final String DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN = ".*/javax.servlet-[^/]*\\.jar$|.*/servlet-api-[^/]*\\.jar$|.*javax.servlet.jsp.jstl-[^/]*\\.jar";
private static final String WEB_INF_CLASSES_PREFIX = "/WEB-INF/classes";
private static final String WEB_INF_LIB_PREFIX = "/WEB-INF/lib";
diff --git a/jetty-monitor/pom.xml b/jetty-monitor/pom.xml
index a6fdceb..2b5611a 100644
--- a/jetty-monitor/pom.xml
+++ b/jetty-monitor/pom.xml
@@ -19,7 +19,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-monitor</artifactId>
diff --git a/jetty-nosql/pom.xml b/jetty-nosql/pom.xml
index d65a221..7c4b1c8 100644
--- a/jetty-nosql/pom.xml
+++ b/jetty-nosql/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-nosql</artifactId>
diff --git a/jetty-osgi/jetty-osgi-alpn/pom.xml b/jetty-osgi/jetty-osgi-alpn/pom.xml
new file mode 100644
index 0000000..3698b98
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-alpn/pom.xml
@@ -0,0 +1,47 @@
+<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>9.2.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-osgi-alpn</artifactId>
+ <name>Jetty :: OSGi ALPN Fragment</name>
+ <packaging>jar</packaging>
+ <properties>
+ <bundle-symbolic-name>org.eclipse.jetty.osgi.alpn.fragment</bundle-symbolic-name>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.7</version>
+ <executions>
+ <execution>
+ <id>parse-version</id>
+ <goals>
+ <goal>parse-version</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifestEntries>
+ <Bundle-ManifestVersion>2</Bundle-ManifestVersion>
+ <Bundle-SymbolicName>${bundle-symbolic-name};singleton:=true</Bundle-SymbolicName>
+ <Bundle-Name>Jetty OSGi ALPN Fragment</Bundle-Name>
+ <Bundle-Version>${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}</Bundle-Version>
+ <Export-Package>org.eclipse.jetty.alpn;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}"</Export-Package>
+ <Fragment-Host>system.bundle;extension:=framework</Fragment-Host>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
index 0efecc3..8dfd29d 100644
--- a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-boot-jsp</artifactId>
diff --git a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
index 1bc7177..a785f58 100644
--- a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-osgi/jetty-osgi-boot/pom.xml b/jetty-osgi/jetty-osgi-boot/pom.xml
index a52ebfa..5a02af5 100644
--- a/jetty-osgi/jetty-osgi-boot/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-boot</artifactId>
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultBundleClassLoaderHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultBundleClassLoaderHelper.java
index 79e350c..199bde3 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultBundleClassLoaderHelper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultBundleClassLoaderHelper.java
@@ -37,37 +37,81 @@
public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
{
private static final Logger LOG = Log.getLogger(BundleClassLoaderHelper.class);
+ private static enum OSGiContainerType {EquinoxOld, EquinoxLuna, FelixOld, Felix403};
+ private static OSGiContainerType osgiContainer;
+ private static Class Equinox_BundleHost_Class;
+ private static Class Equinox_EquinoxBundle_Class;
+ private static Class Felix_BundleImpl_Class;
+ private static Class Felix_BundleWiring_Class;
+ //old equinox
+ private static Method Equinox_BundleHost_getBundleLoader_method;
+ private static Method Equinox_BundleLoader_createClassLoader_method;
+ //new equinox
+ private static Method Equinox_EquinoxBundle_getModuleClassLoader_Method;
+
+ //new felix
+ private static Method Felix_BundleImpl_Adapt_Method;
+ //old felix
+ private static Field Felix_BundleImpl_m_Modules_Field;
+ private static Field Felix_ModuleImpl_m_ClassLoader_Field;
+ private static Method Felix_BundleWiring_getClassLoader_Method;
- private static boolean identifiedOsgiImpl = false;
-
- private static boolean isEquinox = false;
-
- private static boolean isFelix = false;
-
- private static void init(Bundle bundle)
+
+ private static void checkContainerType (Bundle bundle)
{
- identifiedOsgiImpl = true;
+ if (osgiContainer != null)
+ return;
+
try
{
- isEquinox = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost") != null;
+ Equinox_BundleHost_Class = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost");
+ osgiContainer = OSGiContainerType.EquinoxOld;
+ return;
}
- catch (Throwable t)
+ catch (ClassNotFoundException e)
{
- isEquinox = false;
+ LOG.ignore(e);
}
- if (!isEquinox)
+
+ try
{
+ Equinox_EquinoxBundle_Class = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.internal.framework.EquinoxBundle");
+ osgiContainer = OSGiContainerType.EquinoxLuna;
+ return;
+ }
+ catch (ClassNotFoundException e)
+ {
+ LOG.ignore(e);
+ }
+
+ try
+ {
+ //old felix or new felix?
+ Felix_BundleImpl_Class = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl");
try
{
- isFelix = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl") != null;
+ Felix_BundleImpl_Adapt_Method = Felix_BundleImpl_Class.getDeclaredMethod("adapt", new Class[] {Class.class});
+ osgiContainer = OSGiContainerType.Felix403;
+ return;
}
- catch (Throwable t2)
+ catch (NoSuchMethodException e)
{
- isFelix = false;
+ osgiContainer = OSGiContainerType.FelixOld;
+ return;
}
}
+ catch (ClassNotFoundException e)
+ {
+ LOG.warn("Unknown OSGi container type");
+ return;
+ }
+
}
+
+
+
+
/**
* Assuming the bundle is started.
*
@@ -77,7 +121,7 @@
public ClassLoader getBundleClassLoader(Bundle bundle)
{
String bundleActivator = (String) bundle.getHeaders().get("Bundle-Activator");
-
+
if (bundleActivator == null)
{
bundleActivator = (String) bundle.getHeaders().get("Jetty-ClassInBundle");
@@ -93,80 +137,135 @@
LOG.warn(e);
}
}
- // resort to introspection
- if (!identifiedOsgiImpl)
+
+ // resort to introspection
+ return getBundleClassLoaderForContainer(bundle);
+ }
+
+ /**
+ * @param bundle
+ * @return
+ */
+ private ClassLoader getBundleClassLoaderForContainer (Bundle bundle)
+ {
+ checkContainerType (bundle);
+ if (osgiContainer == null)
{
- init(bundle);
- }
- if (isEquinox)
- {
- return internalGetEquinoxBundleClassLoader(bundle);
- }
- else if (isFelix)
- {
- return internalGetFelixBundleClassLoader(bundle);
+ LOG.warn("No classloader for unknown OSGi container type");
+ return null;
}
- LOG.warn("No classloader found for bundle "+bundle.getSymbolicName());
- return null;
+ switch (osgiContainer)
+ {
+ case EquinoxOld:
+ case EquinoxLuna:
+ {
+ return internalGetEquinoxBundleClassLoader(bundle);
+ }
+
+ case FelixOld:
+ case Felix403:
+ {
+ return internalGetFelixBundleClassLoader(bundle);
+ }
+ default:
+ {
+ LOG.warn("No classloader found for bundle "+bundle.getSymbolicName());
+ return null;
+
+ }
+ }
}
+
+
- private static Method Equinox_BundleHost_getBundleLoader_method;
-
- private static Method Equinox_BundleLoader_createClassLoader_method;
-
+ /**
+ * @param bundle
+ * @return
+ */
private static ClassLoader internalGetEquinoxBundleClassLoader(Bundle bundle)
{
- // assume equinox:
- try
+ if (osgiContainer == OSGiContainerType.EquinoxOld)
{
- if (Equinox_BundleHost_getBundleLoader_method == null)
+ try
{
- Equinox_BundleHost_getBundleLoader_method =
- bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost").getDeclaredMethod("getBundleLoader", new Class[] {});
- Equinox_BundleHost_getBundleLoader_method.setAccessible(true);
+ if (Equinox_BundleHost_getBundleLoader_method == null)
+ {
+ Equinox_BundleHost_getBundleLoader_method =
+ Equinox_BundleHost_Class.getDeclaredMethod("getBundleLoader", new Class[] {});
+ Equinox_BundleHost_getBundleLoader_method.setAccessible(true);
+ }
+ Object bundleLoader = Equinox_BundleHost_getBundleLoader_method.invoke(bundle, new Object[] {});
+ if (Equinox_BundleLoader_createClassLoader_method == null && bundleLoader != null)
+ {
+ Equinox_BundleLoader_createClassLoader_method =
+ bundleLoader.getClass().getClassLoader().loadClass("org.eclipse.osgi.internal.loader.BundleLoader").getDeclaredMethod("createClassLoader", new Class[] {});
+ Equinox_BundleLoader_createClassLoader_method.setAccessible(true);
+ }
+ return (ClassLoader) Equinox_BundleLoader_createClassLoader_method.invoke(bundleLoader, new Object[] {});
}
- Object bundleLoader = Equinox_BundleHost_getBundleLoader_method.invoke(bundle, new Object[] {});
- if (Equinox_BundleLoader_createClassLoader_method == null && bundleLoader != null)
+ catch (ClassNotFoundException t)
{
- Equinox_BundleLoader_createClassLoader_method =
- bundleLoader.getClass().getClassLoader().loadClass("org.eclipse.osgi.internal.loader.BundleLoader").getDeclaredMethod("createClassLoader", new Class[] {});
- Equinox_BundleLoader_createClassLoader_method.setAccessible(true);
+ LOG.warn(t);
+ return null;
}
- return (ClassLoader) Equinox_BundleLoader_createClassLoader_method.invoke(bundleLoader, new Object[] {});
+ catch (Throwable t)
+ {
+ LOG.warn(t);
+ return null;
+ }
}
- catch (Throwable t)
+
+ if (osgiContainer == OSGiContainerType.EquinoxLuna)
{
- LOG.warn(t);
+ try
+ {
+ if (Equinox_EquinoxBundle_getModuleClassLoader_Method == null)
+ Equinox_EquinoxBundle_getModuleClassLoader_Method = Equinox_EquinoxBundle_Class.getDeclaredMethod("getModuleClassLoader", new Class[] {Boolean.TYPE});
+
+ Equinox_EquinoxBundle_getModuleClassLoader_Method.setAccessible(true);
+ return (ClassLoader)Equinox_EquinoxBundle_getModuleClassLoader_Method.invoke(bundle, new Object[] {Boolean.FALSE});
+ }
+ catch (Exception e)
+ {
+ LOG.warn(e);
+ return null;
+ }
}
+
LOG.warn("No classloader for equinox platform for bundle "+bundle.getSymbolicName());
return null;
}
- private static Field Felix_BundleImpl_m_modules_field;
+
- private static Field Felix_ModuleImpl_m_classLoader_field;
-
- private static Method Felix_adapt_method;
-
- private static Method Felix_bundle_wiring_getClassLoader_method;
-
- private static Class Felix_bundleWiringClazz;
- private static Boolean isFelix403 = null;
-
+ /**
+ * @param bundle
+ * @return
+ */
private static ClassLoader internalGetFelixBundleClassLoader(Bundle bundle)
{
- //firstly, try to find classes matching a newer version of felix
- initFelix403(bundle);
-
- if (isFelix403.booleanValue())
+
+ if (osgiContainer == OSGiContainerType.Felix403)
{
try
{
- Object wiring = Felix_adapt_method.invoke(bundle, new Object[] {Felix_bundleWiringClazz});
- ClassLoader cl = (ClassLoader)Felix_bundle_wiring_getClassLoader_method.invoke(wiring);
- return cl;
+ if (Felix_BundleWiring_Class == null)
+ Felix_BundleWiring_Class = bundle.getClass().getClassLoader().loadClass("org.osgi.framework.wiring.BundleWiring");
+
+
+ Felix_BundleImpl_Adapt_Method.setAccessible(true);
+
+ if (Felix_BundleWiring_getClassLoader_Method == null)
+ {
+ Felix_BundleWiring_getClassLoader_Method = Felix_BundleWiring_Class.getDeclaredMethod("getClassLoader");
+ Felix_BundleWiring_getClassLoader_Method.setAccessible(true);
+ }
+
+
+ Object wiring = Felix_BundleImpl_Adapt_Method.invoke(bundle, new Object[] {Felix_BundleWiring_Class});
+ return (ClassLoader)Felix_BundleWiring_getClassLoader_Method.invoke(wiring);
}
catch (Exception e)
{
@@ -176,123 +275,92 @@
}
- // Fallback to trying earlier versions of felix.
- if (Felix_BundleImpl_m_modules_field == null)
- {
+ if (osgiContainer == OSGiContainerType.FelixOld)
+ {
try
{
- Class bundleImplClazz = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl");
- Felix_BundleImpl_m_modules_field = bundleImplClazz.getDeclaredField("m_modules");
- Felix_BundleImpl_m_modules_field.setAccessible(true);
- }
- catch (ClassNotFoundException e)
- {
- LOG.warn(e);
- }
- catch (NoSuchFieldException e)
- {
- LOG.warn(e);
- }
- }
+ if (Felix_BundleImpl_m_Modules_Field == null)
+ {
+ Felix_BundleImpl_m_Modules_Field = Felix_BundleImpl_Class.getDeclaredField("m_modules");
+ Felix_BundleImpl_m_Modules_Field.setAccessible(true);
+ }
- // Figure out which version of the modules is exported
- Object currentModuleImpl;
- try
- {
- Object[] moduleArray = (Object[]) Felix_BundleImpl_m_modules_field.get(bundle);
- currentModuleImpl = moduleArray[moduleArray.length - 1];
- }
- catch (Throwable t2)
- {
- try
- {
- List<Object> moduleArray = (List<Object>) Felix_BundleImpl_m_modules_field.get(bundle);
- currentModuleImpl = moduleArray.get(moduleArray.size() - 1);
- }
+ // Figure out which version of the modules is exported
+ Object currentModuleImpl;
+
+ try
+ {
+ Object[] moduleArray = (Object[]) Felix_BundleImpl_m_Modules_Field.get(bundle);
+ currentModuleImpl = moduleArray[moduleArray.length - 1];
+ }
+ catch (Throwable t2)
+ {
+ try
+ {
+ List<Object> moduleArray = (List<Object>) Felix_BundleImpl_m_Modules_Field.get(bundle);
+ currentModuleImpl = moduleArray.get(moduleArray.size() - 1);
+ }
+ catch (Exception e)
+ {
+ LOG.warn(e);
+ return null;
+ }
+ }
+
+ if (Felix_ModuleImpl_m_ClassLoader_Field == null && currentModuleImpl != null)
+ {
+ try
+ {
+ Felix_ModuleImpl_m_ClassLoader_Field = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.ModuleImpl").getDeclaredField("m_classLoader");
+ Felix_ModuleImpl_m_ClassLoader_Field.setAccessible(true);
+ }
+ catch (Exception e)
+ {
+ LOG.warn(e);
+ return null;
+ }
+ }
+
+ // first make sure that the classloader is ready:
+ // the m_classLoader field must be initialized by the
+ // ModuleImpl.getClassLoader() private method.
+ ClassLoader cl = null;
+ try
+ {
+ cl = (ClassLoader) Felix_ModuleImpl_m_ClassLoader_Field.get(currentModuleImpl);
+ if (cl != null)
+ return cl;
+ }
+ catch (Exception e)
+ {
+ LOG.warn(e);
+ return null;
+ }
+
+ // looks like it was not ready:
+ // the m_classLoader field must be initialized by the
+ // ModuleImpl.getClassLoader() private method.
+ // this call will do that.
+ try
+ {
+ bundle.loadClass("java.lang.Object");
+ cl = (ClassLoader) Felix_ModuleImpl_m_ClassLoader_Field.get(currentModuleImpl);
+ return cl;
+ }
+ catch (Exception e)
+ {
+ LOG.warn(e);
+ return null;
+ }
+ }
catch (Exception e)
{
LOG.warn(e);
return null;
}
}
-
- if (Felix_ModuleImpl_m_classLoader_field == null && currentModuleImpl != null)
- {
- try
- {
- Felix_ModuleImpl_m_classLoader_field = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.ModuleImpl").getDeclaredField("m_classLoader");
- Felix_ModuleImpl_m_classLoader_field.setAccessible(true);
- }
- catch (ClassNotFoundException e)
- {
- LOG.warn(e);
- return null;
- }
- catch (NoSuchFieldException e)
- {
- LOG.warn(e);
- return null;
- }
- }
- // first make sure that the classloader is ready:
- // the m_classLoader field must be initialized by the
- // ModuleImpl.getClassLoader() private method.
- ClassLoader cl = null;
- try
- {
- cl = (ClassLoader) Felix_ModuleImpl_m_classLoader_field.get(currentModuleImpl);
- if (cl != null)
- return cl;
- }
- catch (Exception e)
- {
- LOG.warn(e);
- return null;
- }
- // looks like it was not ready:
- // the m_classLoader field must be initialized by the
- // ModuleImpl.getClassLoader() private method.
- // this call will do that.
- try
- {
- bundle.loadClass("java.lang.Object");
- cl = (ClassLoader) Felix_ModuleImpl_m_classLoader_field.get(currentModuleImpl);
- return cl;
- }
- catch (Exception e)
- {
- LOG.warn(e);
- return null;
- }
- }
-
-
- private static void initFelix403 (Bundle bundle)
- {
- //see if the version of Felix is a new one
- if (isFelix403 == null)
- {
- try
- {
- Class bundleImplClazz = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl");
- Felix_bundleWiringClazz = bundle.getClass().getClassLoader().loadClass("org.osgi.framework.wiring.BundleWiring");
- Felix_adapt_method = bundleImplClazz.getDeclaredMethod("adapt", new Class[] {Class.class});
- Felix_adapt_method.setAccessible(true);
- Felix_bundle_wiring_getClassLoader_method = Felix_bundleWiringClazz.getDeclaredMethod("getClassLoader");
- Felix_bundle_wiring_getClassLoader_method.setAccessible(true);
- isFelix403 = Boolean.TRUE;
- }
- catch (ClassNotFoundException e)
- {
- LOG.warn("Felix 4.x classes not found in environment");
- isFelix403 = Boolean.FALSE;
- }
- catch (NoSuchMethodException e)
- {
- LOG.warn("Felix 4.x classes not found in environment");
- isFelix403 = Boolean.FALSE;
- }
- }
+ LOG.warn("No classloader for felix platform for bundle "+bundle.getSymbolicName());
+ return null;
}
}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java
index c1d3bca..fed6f8b 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java
@@ -63,7 +63,25 @@
// DirZipBundleEntry
private static Field ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = null;// ZipFile
+
+ private static final String[] FILE_BUNDLE_ENTRY_CLASSES = {"org.eclipse.osgi.baseadaptor.bundlefile.FileBundleEntry","org.eclipse.osgi.storage.bundlefile.FileBundleEntry"};
+ private static final String[] ZIP_BUNDLE_ENTRY_CLASSES = {"org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleEntry","org.eclipse.osgi.storage.bundlefile.ZipBundleEntry"};
+ private static final String[] DIR_ZIP_BUNDLE_ENTRY_CLASSES = {"org.eclipse.osgi.baseadaptor.bundlefile.DirZipBundleEntry","org.eclipse.osgi.storage.bundlefile.DirZipBundleEntry"};
+ private static final String[] BUNDLE_URL_CONNECTION_CLASSES = {"org.eclipse.osgi.framework.internal.core.BundleURLConnection", "org.eclipse.osgi.storage.url.BundleURLConnection"};
+
+ public static boolean match (String name, String... names)
+ {
+ if (name == null || names == null)
+ return false;
+ boolean matched = false;
+ for (int i=0; i< names.length && !matched; i++)
+ if (name.equals(names[i]))
+ matched = true;
+ return matched;
+ }
+
+
/**
* Works with equinox, felix, nuxeo and probably more. Not exactly in the
* spirit of OSGi but quite necessary to support self-contained webapps and
@@ -107,7 +125,8 @@
BUNDLE_ENTRY_FIELD.setAccessible(true);
}
Object bundleEntry = BUNDLE_ENTRY_FIELD.get(con);
- if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.FileBundleEntry"))
+
+ if (match(bundleEntry.getClass().getName(), FILE_BUNDLE_ENTRY_CLASSES))
{
if (FILE_FIELD == null)
{
@@ -117,7 +136,7 @@
File f = (File) FILE_FIELD.get(bundleEntry);
return f.getParentFile().getParentFile();
}
- else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleEntry"))
+ else if (match(bundleEntry.getClass().getName(), ZIP_BUNDLE_ENTRY_CLASSES))
{
url = bundle.getEntry("/");
@@ -144,7 +163,7 @@
ZipFile zipFile = (ZipFile) ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.get(zipBundleFile);
return new File(zipFile.getName());
}
- else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.DirZipBundleEntry"))
+ else if (match (bundleEntry.getClass().getName(), DIR_ZIP_BUNDLE_ENTRY_CLASSES))
{
// that will not happen as we did ask for the manifest not a
// directory.
@@ -309,7 +328,7 @@
URLConnection conn = url.openConnection();
conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
- if (BUNDLE_URL_CONNECTION_getLocalURL == null && conn.getClass().getName().equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
+ if (BUNDLE_URL_CONNECTION_getLocalURL == null && match(conn.getClass().getName(), BUNDLE_URL_CONNECTION_CLASSES))
{
BUNDLE_URL_CONNECTION_getLocalURL = conn.getClass().getMethod("getLocalURL", null);
BUNDLE_URL_CONNECTION_getLocalURL.setAccessible(true);
@@ -340,7 +359,9 @@
URLConnection conn = url.openConnection();
conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
- if (BUNDLE_URL_CONNECTION_getFileURL == null && conn.getClass().getName().equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
+ if (BUNDLE_URL_CONNECTION_getFileURL == null
+ &&
+ match (conn.getClass().getName(), BUNDLE_URL_CONNECTION_CLASSES))
{
BUNDLE_URL_CONNECTION_getFileURL = conn.getClass().getMethod("getFileURL", null);
BUNDLE_URL_CONNECTION_getFileURL.setAccessible(true);
diff --git a/jetty-osgi/jetty-osgi-httpservice/pom.xml b/jetty-osgi/jetty-osgi-httpservice/pom.xml
index c061b28..91087d7 100644
--- a/jetty-osgi/jetty-osgi-httpservice/pom.xml
+++ b/jetty-osgi/jetty-osgi-httpservice/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-httpservice</artifactId>
@@ -28,6 +28,7 @@
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
diff --git a/jetty-osgi/jetty-osgi-npn/pom.xml b/jetty-osgi/jetty-osgi-npn/pom.xml
index 63a46e6..db524d9 100644
--- a/jetty-osgi/jetty-osgi-npn/pom.xml
+++ b/jetty-osgi/jetty-osgi-npn/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-npn</artifactId>
diff --git a/jetty-osgi/pom.xml b/jetty-osgi/pom.xml
index a89a1c6..6dbd99d 100644
--- a/jetty-osgi/pom.xml
+++ b/jetty-osgi/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
@@ -22,12 +22,23 @@
<module>jetty-osgi-boot</module>
<module>jetty-osgi-boot-jsp</module>
<module>jetty-osgi-boot-warurl</module>
- <module>jetty-osgi-npn</module>
<module>jetty-osgi-httpservice</module>
<module>test-jetty-osgi-webapp</module>
<module>test-jetty-osgi-context</module>
<module>test-jetty-osgi</module>
+ <module>jetty-osgi-alpn</module>
</modules>
+ <profiles>
+ <profile>
+ <id>npn</id>
+ <activation>
+ <jdk>1.7</jdk>
+ </activation>
+ <modules>
+ <module>jetty-osgi-npn</module>
+ </modules>
+ </profile>
+ </profiles>
<build>
<resources>
<resource>
diff --git a/jetty-osgi/test-jetty-osgi-context/pom.xml b/jetty-osgi/test-jetty-osgi-context/pom.xml
index 46ad381..941b13b 100644
--- a/jetty-osgi/test-jetty-osgi-context/pom.xml
+++ b/jetty-osgi/test-jetty-osgi-context/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-jetty-osgi-context</artifactId>
@@ -21,10 +21,12 @@
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
diff --git a/jetty-osgi/test-jetty-osgi-webapp/pom.xml b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
index 23a67d6..1a0f37b 100644
--- a/jetty-osgi/test-jetty-osgi-webapp/pom.xml
+++ b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -21,10 +21,12 @@
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
+ <scope>provided</scope>
</dependency>
</dependencies>
diff --git a/jetty-osgi/test-jetty-osgi/pom.xml b/jetty-osgi/test-jetty-osgi/pom.xml
index d417372..cf6810a 100644
--- a/jetty-osgi/test-jetty-osgi/pom.xml
+++ b/jetty-osgi/test-jetty-osgi/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -14,40 +14,14 @@
<bundle-symbolic-name>${project.groupId}.boot.test.spdy</bundle-symbolic-name>
<jetty-orbit-url>http://download.eclipse.org/jetty/orbit/</jetty-orbit-url>
<assembly-directory>target/distribution</assembly-directory>
- <exam.version>2.6.0</exam.version>
- <url.version>1.4.0</url.version>
- <paxswissbox.version>1.5.1</paxswissbox.version>
- <felixversion>4.0.3</felixversion>
+ <exam.version>3.4.0</exam.version>
+ <url.version>1.5.2</url.version>
<injection.bundle.version>1.0</injection.bundle.version>
- <runner.version>1.7.6</runner.version>
+ <runner.version>1.8.5</runner.version>
</properties>
<dependencies>
<!-- Pax Exam Dependencies -->
- <!-- OPS4J Swissbox Dependencies -->
- <dependency>
- <groupId>org.ops4j.pax.swissbox</groupId>
- <artifactId>pax-swissbox-core</artifactId>
- <version>${paxswissbox.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.swissbox</groupId>
- <artifactId>pax-swissbox-extender</artifactId>
- <version>${paxswissbox.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.swissbox</groupId>
- <artifactId>pax-swissbox-lifecycle</artifactId>
- <version>${paxswissbox.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.swissbox</groupId>
- <artifactId>pax-swissbox-framework</artifactId>
- <version>${paxswissbox.version}</version>
- <scope>test</scope>
- </dependency>
+
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam</artifactId>
@@ -55,61 +29,21 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.apache.geronimo.specs</groupId>
- <artifactId>geronimo-atinject_1.0_spec</artifactId>
- <version>${injection.bundle.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-inject</artifactId>
<version>${exam.version}</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.apache.aries.spifly</groupId>
- <artifactId>org.apache.aries.spifly.dynamic.bundle</artifactId>
- <version>1.0.0</version>
- <scope>test</scope>
- </dependency>
- <!-- Don't use the native container for now. Observed limitations:
- - single test with a single configuration
- - does not read the versions of the dependencies from the pom.xml
- and hence hardcode the bundles versions in the source code instead
- - no support for most configuration options for the OSGi container. -->
- <!--dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-container-native</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency-->
-
- <!-- container is not bad but not enough config parameters yet
- can't pass the VMOption for npn-boot
+ <!-- use the forked container so we can pass it system properties eg for npn/alpn -->
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-forked</artifactId>
<version>${exam.version}</version>
<scope>test</scope>
</dependency>
- -->
-
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-container-paxrunner</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>org.ops4j.pax.runner</groupId>
- <artifactId>pax-runner-no-jcl</artifactId>
- <version>${runner.version}</version>
- <scope>test</scope>
- </dependency>
-
+
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-junit4</artifactId>
@@ -134,29 +68,82 @@
<version>${url.version}</version>
<scope>test</scope>
</dependency>
+
<!-- OSGi R4 frameworks -->
+<!--
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
- <version>${felixversion}</version>
+ <version>4.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-testforge</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <!-- For sane logging -->
-<!--
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <version>1.6.1</version>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.enterprise</artifactId>
+ <version>5.0.0</version>
<scope>test</scope>
</dependency>
-->
<dependency>
+ <groupId>org.eclipse</groupId>
+ <artifactId>osgi</artifactId>
+ <version>3.9.1-v20140110-1610</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.osgi</groupId>
+ <artifactId>org.eclipse.osgi.services</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+
+ <!-- Jetty OSGi Deps -->
+ <dependency>
+ <groupId>org.eclipse.jetty.osgi</groupId>
+ <artifactId>jetty-osgi-boot</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.osgi</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.osgi</groupId>
+ <artifactId>org.eclipse.osgi.services</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.osgi</groupId>
+ <artifactId>jetty-osgi-boot-jsp</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.osgi</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.osgi</groupId>
+ <artifactId>org.eclipse.osgi.services</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.toolchain</groupId>
+ <artifactId>jetty-jsp-fragment</artifactId>
+ <version>2.3.3</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.osgi</groupId>
+ <artifactId>jetty-httpservice</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>test</scope>
@@ -167,36 +154,55 @@
<version>1.1.1</version>
<scope>test</scope>
</dependency>
- <!-- OSGi Deps -->
+
<dependency>
- <groupId>org.eclipse.jetty.osgi</groupId>
- <artifactId>jetty-osgi-boot</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-atinject_1.0_spec</artifactId>
+ <version>${injection.bundle.version}</version>
+ <scope>test</scope>
</dependency>
<dependency>
- <groupId>org.eclipse.jetty.osgi</groupId>
- <artifactId>jetty-osgi-boot-jsp</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
+ <groupId>org.apache.aries.spifly</groupId>
+ <artifactId>org.apache.aries.spifly.dynamic.bundle</artifactId>
+ <version>1.0.0</version>
+ <scope>test</scope>
</dependency>
<dependency>
- <groupId>org.eclipse.jetty.toolchain</groupId>
- <artifactId>jetty-jsp-fragment</artifactId>
- <version>2.3.3</version>
- <scope>provided</scope>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm</artifactId>
+ <version>4.1</version>
</dependency>
<dependency>
- <groupId>org.eclipse.jetty.osgi</groupId>
- <artifactId>jetty-httpservice</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-commons</artifactId>
+ <version>4.1</version>
</dependency>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-tree</artifactId>
+ <version>4.1</version>
+ </dependency>
+
+
<!-- Jetty Deps -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<scope>runtime</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-commons</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-tree</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
@@ -324,14 +330,20 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.mortbay.jetty.npn</groupId>
- <artifactId>npn-boot</artifactId>
- <version>${npn.version}</version>
+ <groupId>org.mortbay.jetty.alpn</groupId>
+ <artifactId>alpn-boot</artifactId>
+ <version>${alpn.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
- <artifactId>jetty-osgi-npn</artifactId>
+ <artifactId>jetty-osgi-alpn</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-alpn-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
@@ -348,7 +360,9 @@
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
+
<!-- Eclipse OSGi Deps -->
+<!--
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
@@ -360,7 +374,6 @@
<scope>runtime</scope>
<exclusions>
<exclusion>
- <!-- we use the servlet jar from orbit -->
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
@@ -371,6 +384,9 @@
<artifactId>servlet</artifactId>
<scope>runtime</scope>
</dependency>
+
+-->
+
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-webapp</artifactId>
@@ -402,9 +418,8 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- No point defining -Xbootclasspath as the actual OSGi VM is run as a forked process by pax-exam -->
- <!--argLine>-Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn.version}/npn-boot-${npn.version}.jar</argLine-->
- <!-- But we do pass the sys property of the npn-boot jar -->
- <argLine>-Dmortbay-npn-boot=${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn.version}/npn-boot-${npn.version}.jar</argLine>
+ <!-- But we do pass the sys property of the alpn-boot jar so that it can be configued inside tests -->
+ <argLine>-Dmortbay-alpn-boot=${settings.localRepository}/org/mortbay/jetty/alpn/alpn-boot/${alpn.version}/alpn-boot-${alpn.version}.jar</argLine>
</configuration>
</plugin>
<plugin>
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-spdy.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-spdy.xml
index 8c06a2c..2bc1fe3 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-spdy.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-spdy.xml
@@ -4,7 +4,7 @@
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
- <!-- HttpChannel Configuration -->
+ <!-- Add HTTP Customizer for Secure request -->
<!-- =========================================================== -->
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
<Set name="secureScheme">https</Set>
@@ -16,7 +16,7 @@
<Set name="responseHeaderSize">8192</Set>
<Call name="addCustomizer">
<Arg>
- <New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/>
+ <New class="org.eclipse.jetty.server.SecureRequestCustomizer"/>
</Arg>
</Call>
</New>
@@ -36,53 +36,6 @@
</New>
<!-- =========================================================== -->
- <!-- Add HTTP Customizer for Secure request -->
- <!-- =========================================================== -->
- <Ref refid="httpConfig">
- <Call name="addCustomizer">
- <Arg>
- <New class="org.eclipse.jetty.server.SecureRequestCustomizer"/>
- </Arg>
- </Call>
- </Ref>
-
- <!-- =========================================================== -->
- <!-- Create a push strategy which can be used by reference by -->
- <!-- individual connection factories below. -->
- <!-- -->
- <!-- Consult the javadoc of o.e.j.spdy.server.http.ReferrerPushStrategy -->
- <!-- for all configuration that may be set here. -->
- <!-- =========================================================== -->
- <New id="pushStrategy" class="org.eclipse.jetty.spdy.server.http.ReferrerPushStrategy">
- <!-- Uncomment to blacklist browsers for this push strategy. If one of the blacklisted Strings occurs in the
- user-agent header sent by the client, push will be disabled for this browser. This is case insensitive" -->
- <!--
- <Set name="UserAgentBlacklist">
- <Array type="String">
- <Item>.*(?i)firefox/14.*</Item>
- <Item>.*(?i)firefox/15.*</Item>
- <Item>.*(?i)firefox/16.*</Item>
- </Array>
- </Set>
- -->
-
- <!-- Uncomment to override default file extensions to push -->
- <!--
- <Set name="PushRegexps">
- <Array type="String">
- <Item>.*\.css</Item>
- <Item>.*\.js</Item>
- <Item>.*\.png</Item>
- <Item>.*\.jpg</Item>
- <Item>.*\.gif</Item>
- </Array>
- </Set>
- -->
- <Set name="referrerPushPeriod">5000</Set>
- <Set name="maxAssociatedResources">32</Set>
- </New>
-
- <!-- =========================================================== -->
<!-- Set connectors -->
<!-- =========================================================== -->
<Call id="sslConnector" name="addConnector">
@@ -95,7 +48,7 @@
<Array type="org.eclipse.jetty.server.ConnectionFactory">
<Item>
<New class="org.eclipse.jetty.server.SslConnectionFactory">
- <Arg name="next">npn</Arg>
+ <Arg name="next">alpn</Arg>
<Arg name="sslContextFactory">
<Ref refid="sslContextFactory"/>
</Arg>
@@ -103,7 +56,7 @@
</Item>
<Item>
- <New class="org.eclipse.jetty.spdy.server.NPNServerConnectionFactory">
+ <New class="org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory">
<Arg name="protocols">
<Array type="String">
<Item>spdy/3</Item>
@@ -124,8 +77,6 @@
<!-- Set the initial window size for this SPDY connector. -->
<!-- See: http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.8-WINDOW_UPDATE -->
<Set name="initialWindowSize">65536</Set>
- <!-- Uncomment to enable the push strategy with id "pushStrategy" -->
- <!-- <Arg name="pushStrategy"><Ref refid="pushStrategy"/></Arg> -->
</New>
</Item>
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootContextAsService.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootContextAsService.java
index 94ecd39..0dfc1bb 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootContextAsService.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootContextAsService.java
@@ -37,12 +37,13 @@
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.Configuration;
-import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.junit.PaxExam;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
@@ -55,12 +56,11 @@
* Tests the ServiceContextProvider.
*
*/
-@RunWith(JUnit4TestRunner.class)
+@RunWith(PaxExam.class)
public class TestJettyOSGiBootContextAsService
{
- private static final boolean LOGGING_ENABLED = false;
+ private static final String LOG_LEVEL = "WARN";
- private static final boolean REMOTE_DEBUGGING = false;
@Inject
BundleContext bundleContext = null;
@@ -69,7 +69,6 @@
public static Option[] configure()
{
ArrayList<Option> options = new ArrayList<Option>();
- TestOSGiUtil.addMoreOSGiContainers(options);
options.add(CoreOptions.junitBundles());
options.addAll(configureJettyHomeAndPort("jetty-selector.xml"));
options.add(CoreOptions.bootDelegationPackages("org.xml.sax", "org.xml.*", "org.w3c.*", "javax.xml.*"));
@@ -79,22 +78,10 @@
// to pick up and deploy
options.add(mavenBundle().groupId("org.eclipse.jetty.osgi").artifactId("test-jetty-osgi-context").versionAsInProject().start());
- String logLevel = "WARN";
- // Enable Logging
- if (LOGGING_ENABLED)
- logLevel = "INFO";
+ options.addAll(Arrays.asList(options(systemProperty("pax.exam.logging").value("none"))));
+ options.addAll(Arrays.asList(options(systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(LOG_LEVEL))));
+ options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.LEVEL").value(LOG_LEVEL))));
-
- options.addAll(Arrays.asList(options(
- // install log service using pax runners profile abstraction (there
- // are more profiles, like DS)
- // logProfile(),
- // this is how you set the default log level when using pax logging
- // (logProfile)
- systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(logLevel),
- systemProperty("org.eclipse.jetty.LEVEL").value(logLevel))));
-
-
return options.toArray(new Option[options.size()]);
}
@@ -117,6 +104,7 @@
return options;
}
+ @Ignore
@Test
public void assertAllBundlesActiveOrResolved()
{
@@ -148,14 +136,6 @@
ServiceReference[] refs = bundleContext.getServiceReferences(ContextHandler.class.getName(), null);
assertNotNull(refs);
assertEquals(1, refs.length);
- //uncomment for debugging
- /*
- String[] keys = refs[0].getPropertyKeys();
- if (keys != null)
- {
- for (String k : keys)
- System.err.println("service property: " + k + ", " + refs[0].getProperty(k));
- }*/
ContextHandler ch = (ContextHandler) bundleContext.getService(refs[0]);
assertEquals("/acme", ch.getContextPath());
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootCore.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootCore.java
index 2c23318..d31760d 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootCore.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootCore.java
@@ -19,19 +19,23 @@
package org.eclipse.jetty.osgi.test;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import javax.inject.Inject;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.MavenUtils;
import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.Configuration;
-import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.options.MavenUrlReference.VersionResolver;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -40,27 +44,30 @@
/**
* Default OSGi setup integration test
*/
-@RunWith( JUnit4TestRunner.class )
+@RunWith( PaxExam.class )
public class TestJettyOSGiBootCore
{
-
+ private static final String LOG_LEVEL = "WARN";
public static int DEFAULT_JETTY_HTTP_PORT = 9876;
-
+
@Inject
private BundleContext bundleContext;
-
+
@Configuration
public Option[] config()
{
VersionResolver resolver = MavenUtils.asInProject();
ArrayList<Option> options = new ArrayList<Option>();
- TestOSGiUtil.addMoreOSGiContainers(options);
options.addAll(provisionCoreJetty());
options.add(CoreOptions.junitBundles());
options.addAll(httpServiceJetty());
+ options.addAll(Arrays.asList(options(systemProperty("pax.exam.logging").value("none"))));
+ options.addAll(Arrays.asList(options(systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(LOG_LEVEL))));
+ options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.LEVEL").value(LOG_LEVEL))));
+
return options.toArray(new Option[options.size()]);
}
-
+
public static List<Option> provisionCoreJetty()
{
List<Option> res = new ArrayList<Option>();
@@ -75,12 +82,21 @@
public static List<Option> coreJettyDependencies()
{
List<Option> res = new ArrayList<Option>();
- res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm" ).versionAsInProject().start());
- res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-commons" ).versionAsInProject().start());
- res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-tree" ).versionAsInProject().start());
- res.add(mavenBundle().groupId( "org.apache.aries" ).artifactId( "org.apache.aries.util" ).version("1.0.0").start());
- res.add(mavenBundle().groupId( "org.apache.aries.spifly" ).artifactId( "org.apache.aries.spifly.dynamic.bundle" ).version("1.0.0").start());
+ String jdk = System.getProperty("java.version");
+ int firstdot = jdk.indexOf(".");
+ jdk = jdk.substring(0,firstdot+2);
+ double version = Double.parseDouble(jdk);
+
+ if (version < 1.8)
+ {
+ res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm" ).versionAsInProject().start());
+ res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-commons" ).versionAsInProject().start());
+ res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-tree" ).versionAsInProject().start());
+ res.add(mavenBundle().groupId( "org.apache.aries" ).artifactId( "org.apache.aries.util" ).version("1.0.0").start());
+ res.add(mavenBundle().groupId( "org.apache.aries.spifly" ).artifactId( "org.apache.aries.spifly.dynamic.bundle" ).version("1.0.0").start());
+ }
+
res.add(mavenBundle().groupId( "javax.servlet" ).artifactId( "javax.servlet-api" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "javax.annotation" ).artifactId( "javax.annotation-api" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.apache.geronimo.specs" ).artifactId( "geronimo-jta_1.1_spec" ).version("1.1.1").noStart());
@@ -103,7 +119,10 @@
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-client" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-jndi" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-plus" ).versionAsInProject().noStart());
- res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-annotations" ).versionAsInProject().start());
+ if (version < 1.8)
+ {
+ res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-annotations" ).versionAsInProject().start());
+ }
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-api" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-common" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-servlet" ).versionAsInProject().noStart());
@@ -124,9 +143,12 @@
return res;
}
+ @Ignore
@Test
public void assertAllBundlesActiveOrResolved() throws Exception
{
+
+ TestOSGiUtil.debugBundles(bundleContext);
TestOSGiUtil.assertAllBundlesActiveOrResolved(bundleContext);
}
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootSpdy.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootSpdy.java
index 9558861..0cb66a5 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootSpdy.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootSpdy.java
@@ -31,21 +31,23 @@
import javax.inject.Inject;
import org.junit.Assert;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.Configuration;
-import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
/**
* SPDY setup.
*/
-@RunWith(JUnit4TestRunner.class)
+@RunWith(PaxExam.class)
public class TestJettyOSGiBootSpdy
{
- private static final boolean LOGGING_ENABLED = false;
+ private static final String LOG_LEVEL = "WARN";
private static final String JETTY_SPDY_PORT = "jetty.spdy.port";
@@ -58,31 +60,14 @@
public Option[] config()
{
ArrayList<Option> options = new ArrayList<Option>();
-
- TestOSGiUtil.addMoreOSGiContainers(options);
-
-
options.addAll(TestJettyOSGiBootWithJsp.configureJettyHomeAndPort("jetty-spdy.xml"));
options.addAll(TestJettyOSGiBootCore.coreJettyDependencies());
+ options.addAll(spdyJettyDependencies());
options.add(CoreOptions.junitBundles());
options.addAll(TestJettyOSGiBootCore.httpServiceJetty());
- options.addAll(spdyJettyDependencies());
-
- String logLevel = "WARN";
-
- // Enable Logging
- if (LOGGING_ENABLED)
- logLevel = "INFO";
-
-
- options.addAll(Arrays.asList(options(
- // install log service using pax runners profile abstraction (there
- // are more profiles, like DS)
- // logProfile(),
- // this is how you set the default log level when using pax logging
- // (logProfile)
- systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(logLevel),
- systemProperty("org.eclipse.jetty.LEVEL").value(logLevel))));
+ options.addAll(Arrays.asList(options(systemProperty("pax.exam.logging").value("none"))));
+ options.addAll(Arrays.asList(options(systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(LOG_LEVEL))));
+ options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.LEVEL").value(LOG_LEVEL))));
return options.toArray(new Option[options.size()]);
}
@@ -90,37 +75,39 @@
{
List<Option> res = new ArrayList<Option>();
res.add(CoreOptions.systemProperty(JETTY_SPDY_PORT).value(String.valueOf(DEFAULT_JETTY_SPDY_PORT)));
- // java
- // -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn-version}/npn-boot-${npn-version}.jar
- // res.add(CoreOptions.vmOptions("-Xbootclasspath/p:"+System.getenv("HOME")+"/.m2/repository/org/mortbay/jetty/npn/npn-boot/"+npnBootVersion+"/npn-boot-"+npnBootVersion+".jar"));
- String npnBoot = System.getProperty("mortbay-npn-boot");
- if (npnBoot == null) { throw new IllegalStateException("Define path to npn boot jar as system property -Dmortbay-npn-boot"); }
- File checkNpnBoot = new File(npnBoot);
- if (!checkNpnBoot.exists()) { throw new IllegalStateException("Unable to find the npn boot jar here: " + npnBoot); }
- res.add(CoreOptions.vmOptions("-Xbootclasspath/p:" + npnBoot));
- // res.add(CoreOptions.bootDelegationPackages("org.eclipse.jetty.npn"));
+ String alpnBoot = System.getProperty("mortbay-alpn-boot");
+ if (alpnBoot == null) { throw new IllegalStateException("Define path to alpn boot jar as system property -Dmortbay-alpn-boot"); }
+ File checkALPNBoot = new File(alpnBoot);
+ if (!checkALPNBoot.exists()) { throw new IllegalStateException("Unable to find the alpn boot jar here: " + alpnBoot); }
- res.add(mavenBundle().groupId("org.eclipse.jetty.osgi").artifactId("jetty-osgi-npn").versionAsInProject().noStart());
+
+ res.add(CoreOptions.vmOptions("-Xbootclasspath/p:" + alpnBoot));
+
+ res.add(mavenBundle().groupId("org.eclipse.jetty.osgi").artifactId("jetty-osgi-alpn").versionAsInProject().noStart());
+ res.add(mavenBundle().groupId("org.eclipse.jetty").artifactId("jetty-alpn-server").versionAsInProject().start());
+
+ res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-client").versionAsInProject().noStart());
res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-core").versionAsInProject().noStart());
res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-server").versionAsInProject().noStart());
res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-http-common").versionAsInProject().noStart());
res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-http-server").versionAsInProject().noStart());
- res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-client").versionAsInProject().noStart());
return res;
}
@Test
- public void checkNpnBootOnBootstrapClasspath() throws Exception
+ public void checkALPNBootOnBootstrapClasspath() throws Exception
{
- Class<?> npn = Thread.currentThread().getContextClassLoader().loadClass("org.eclipse.jetty.npn.NextProtoNego");
- Assert.assertNotNull(npn);
- Assert.assertNull(npn.getClassLoader());
+ Class<?> alpn = Thread.currentThread().getContextClassLoader().loadClass("org.eclipse.jetty.alpn.ALPN");
+ Assert.assertNotNull(alpn);
+ Assert.assertNull(alpn.getClassLoader());
}
+ @Ignore
@Test
public void assertAllBundlesActiveOrResolved()
{
+ TestOSGiUtil.debugBundles(bundleContext);
TestOSGiUtil.assertAllBundlesActiveOrResolved(bundleContext);
}
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootWebAppAsService.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootWebAppAsService.java
index b43279c..cf2e30f 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootWebAppAsService.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootWebAppAsService.java
@@ -38,12 +38,13 @@
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.webapp.WebAppContext;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.Configuration;
-import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.junit.PaxExam;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
@@ -58,12 +59,10 @@
* httpservice web-bundle. Then make sure we can deploy an OSGi service on the
* top of this.
*/
-@RunWith(JUnit4TestRunner.class)
+@RunWith(PaxExam.class)
public class TestJettyOSGiBootWebAppAsService
{
- private static final boolean LOGGING_ENABLED = false;
-
- private static final boolean REMOTE_DEBUGGING = false;
+ private static final String LOG_LEVEL = "WARN";
@Inject
BundleContext bundleContext = null;
@@ -72,8 +71,6 @@
public static Option[] configure()
{
ArrayList<Option> options = new ArrayList<Option>();
- TestOSGiUtil.addMoreOSGiContainers(options);
-
options.add(CoreOptions.junitBundles());
options.addAll(configureJettyHomeAndPort("jetty-selector.xml"));
options.add(CoreOptions.bootDelegationPackages("org.xml.sax", "org.xml.*", "org.w3c.*", "javax.xml.*"));
@@ -82,19 +79,9 @@
"com.sun.org.apache.xpath.internal.jaxp", "com.sun.org.apache.xpath.internal.objects"));
options.addAll(TestJettyOSGiBootCore.coreJettyDependencies());
-
- String logLevel = "WARN";
- if (LOGGING_ENABLED)
- logLevel = "INFO";
-
- options.addAll(Arrays.asList(options(
- // install log service using pax runners profile abstraction (there
- // are more profiles, like DS)
- // logProfile(),
- // this is how you set the default log level when using pax logging
- // (logProfile)
- systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(logLevel),
- systemProperty("org.eclipse.jetty.LEVEL").value(logLevel))));
+ options.addAll(Arrays.asList(options(systemProperty("pax.exam.logging").value("none"))));
+ options.addAll(Arrays.asList(options(systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(LOG_LEVEL))));
+ options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.LEVEL").value(LOG_LEVEL))));
options.addAll(jspDependencies());
return options.toArray(new Option[options.size()]);
@@ -139,6 +126,7 @@
return res;
}
+ @Ignore
@Test
public void assertAllBundlesActiveOrResolved()
{
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootWithJsp.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootWithJsp.java
index 10b21f5..b2a9be5 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootWithJsp.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootWithJsp.java
@@ -38,25 +38,21 @@
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.Configuration;
-import org.ops4j.pax.exam.junit.JUnit4TestRunner;
-import org.osgi.framework.Bundle;
+import org.ops4j.pax.exam.junit.PaxExam;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
/**
* Pax-Exam to make sure the jetty-osgi-boot can be started along with the
* httpservice web-bundle. Then make sure we can deploy an OSGi service on the
* top of this.
*/
-@RunWith(JUnit4TestRunner.class)
+@RunWith(PaxExam.class)
public class TestJettyOSGiBootWithJsp
{
- private static final boolean LOGGING_ENABLED = false;
-
- private static final boolean REMOTE_DEBUGGING = false;
+ private static final String LOG_LEVEL = "WARN";
@Inject
BundleContext bundleContext = null;
@@ -66,9 +62,6 @@
{
ArrayList<Option> options = new ArrayList<Option>();
-
- TestOSGiUtil.addMoreOSGiContainers(options);
-
options.add(CoreOptions.junitBundles());
options.addAll(configureJettyHomeAndPort("jetty-selector.xml"));
options.add(CoreOptions.bootDelegationPackages("org.xml.sax", "org.xml.*", "org.w3c.*", "javax.xml.*", "javax.activation.*"));
@@ -77,39 +70,11 @@
"com.sun.org.apache.xpath.internal.jaxp", "com.sun.org.apache.xpath.internal.objects"));
options.addAll(TestJettyOSGiBootCore.coreJettyDependencies());
+ options.addAll(Arrays.asList(options(systemProperty("pax.exam.logging").value("none"))));
+ options.addAll(Arrays.asList(options(systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(LOG_LEVEL))));
+ options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.LEVEL").value(LOG_LEVEL))));
- String logLevel = "WARN";
-
- // Enable Logging
- if (LOGGING_ENABLED)
- logLevel = "INFO";
-
- options.addAll(Arrays.asList(options(
- // install log service using pax runners profile abstraction (there
- // are more profiles, like DS)
- // logProfile(),
- // this is how you set the default log level when using pax logging
- // (logProfile)
- systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(logLevel),
- systemProperty("org.eclipse.jetty.annotations.LEVEL").value(logLevel))));
-
options.addAll(jspDependencies());
-
- // Remote JDWP Debugging, this won't work with the forked container.
- // if(REMOTE_DEBUGGING) {
- // options.addAll(Arrays.asList(options(
- // // this just adds all what you write here to java vm argumenents of
- // the (new) osgi process.
- // PaxRunnerOptions.vmOption(
- // "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5006" )
- // )));
- // }
-
- // bug at the moment: this would make the httpservice catch all
- // requests and prevent the webapp at the root context to catch any of
- // them.
- // options.addAll(TestJettyOSGiBootCore.httpServiceJetty());
-
return options.toArray(new Option[options.size()]);
}
@@ -157,7 +122,7 @@
return res;
}
-
+ @Ignore
@Test
public void assertAllBundlesActiveOrResolved()
{
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestOSGiUtil.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestOSGiUtil.java
index d9d63ed..a3f486d 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestOSGiUtil.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestOSGiUtil.java
@@ -33,7 +33,6 @@
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
-import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -46,22 +45,6 @@
public class TestOSGiUtil
{
- /**
- * Note: this will run many more tests. TODO: find a better way to control
- * this and use non-deprecated methods.
- *
- * @param opti
- */
- protected static void addMoreOSGiContainers(List<Option> options)
- {
- //Uncomment to run more containers - these have been commented out
- //to improve speed of builds.
- //options.add(CoreOptions.equinox().version("3.6.1"));
- //options.add(CoreOptions.equinox().version("3.7.0"));
- // options.add(CoreOptions.felix().version("3.2.2"));
- options.add(CoreOptions.felix().version("4.0.2"));
- }
-
protected static Bundle getBundle(BundleContext bundleContext, String symbolicName)
{
Map<String,Bundle> _bundles = new HashMap<String, Bundle>();
@@ -146,7 +129,7 @@
for (Bundle b : bundleContext.getBundles())
{
bundlesIndexedBySymbolicName.put(b.getSymbolicName(), b);
- System.err.println(" " + b.getSymbolicName() + " " + b.getState());
+ System.err.println(" " + b.getSymbolicName() + " " + b.getLocation() + " " + b.getVersion()+ " " + b.getState());
}
}
diff --git a/jetty-plus/pom.xml b/jetty-plus/pom.xml
index 377ea4f..d5485a1 100644
--- a/jetty-plus/pom.xml
+++ b/jetty-plus/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-plus</artifactId>
diff --git a/jetty-proxy/pom.xml b/jetty-proxy/pom.xml
index 8ae47be..b17d0a1 100644
--- a/jetty-proxy/pom.xml
+++ b/jetty-proxy/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-proxy</artifactId>
diff --git a/jetty-quickstart/README.txt b/jetty-quickstart/README.txt
new file mode 100644
index 0000000..43ad7f3
--- /dev/null
+++ b/jetty-quickstart/README.txt
@@ -0,0 +1,6 @@
+mvn exec:java -Dexec.classpathScope=test -Dexec.mainClass="org.eclipse.jetty.quickstart.StartBenchmarkWar"
+
+OR
+
+mvn exec:java -Dexec.classpathScope=test -Dexec.mainClass="org.eclipse.jetty.quickstart.PreconfigureBenchmarkWar"
+mvn exec:java -Dexec.classpathScope=test -Dexec.mainClass="org.eclipse.jetty.quickstart.QuickStartBenchmarkWar"
diff --git a/jetty-quickstart/pom.xml b/jetty-quickstart/pom.xml
new file mode 100644
index 0000000..3a34ba7
--- /dev/null
+++ b/jetty-quickstart/pom.xml
@@ -0,0 +1,170 @@
+<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>9.2.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-quickstart</artifactId>
+ <name>Example :: Jetty Quick Start</name>
+ <description>Jetty Quick Start</description>
+ <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>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jmx</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-plus</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-annotations</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.transaction</groupId>
+ <artifactId>javax.transaction-api</artifactId>
+ <version>1.2</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.tests</groupId>
+ <artifactId>test-mock-resources</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.mail.glassfish</artifactId>
+ <version>1.4.1.v201005082020</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlets</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.websocket</groupId>
+ <artifactId>javax-websocket-server-impl</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.websocket</groupId>
+ <artifactId>websocket-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>apache-jsp</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>apache-jstl</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>appassembler-maven-plugin</artifactId>
+ <version>1.7</version>
+ <configuration>
+ <platforms>
+ <platform>unix</platform>
+ </platforms>
+ <programs>
+ <program>
+ <id>preconfigure</id>
+ <mainClass>org.eclipse.jetty.quickstart.PreconfigureQuickStartWar</mainClass>
+ </program>
+ <program>
+ <mainClass>org.eclipse.jetty.quickstart.QuickStartWar</mainClass>
+ <id>quickstart</id>
+ </program>
+ </programs>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.eclipse.jetty.tests</groupId>
+ <artifactId>test-jndi-webapp</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ <overWrite>true</overWrite>
+ <includes>**</includes>
+ <outputDirectory>${basedir}/target</outputDirectory>
+ <destFileName>test-jndi.war</destFileName>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.eclipse.jetty.tests</groupId>
+ <artifactId>test-spec-webapp</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ <overWrite>true</overWrite>
+ <includes>**</includes>
+ <outputDirectory>${basedir}/target</outputDirectory>
+ <destFileName>test-spec.war</destFileName>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>test-jetty-webapp</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ <overWrite>true</overWrite>
+ <includes>**</includes>
+ <outputDirectory>${basedir}/target</outputDirectory>
+ <destFileName>test-standard.war</destFileName>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </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>
+ </plugins>
+ </build>
+</project>
diff --git a/jetty-quickstart/src/main/config/etc/example-quickstart.xml b/jetty-quickstart/src/main/config/etc/example-quickstart.xml
new file mode 100644
index 0000000..9a012c7
--- /dev/null
+++ b/jetty-quickstart/src/main/config/etc/example-quickstart.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+
+<!-- An example context XML for a quickstart webapp
+A quick started webapp has all the jar scanning and fragment resolution done in a
+Preconfigure phase, with all the discovered configuration encoded into a
+WEB-INF/quickstart-web.xml file.
+
+This allows very rapid and precise starting of a webapp, without the risk of accidental
+deployment of other discovered resources. This is above and beyond what is available
+with web.xml meta-data-complete, as it also prevents scanning for ServletContainer
+initialisers and any annotations/classes they require.
+
+If autoPreconfigure is set to true, then the webapp will be preconfigured the first
+time it is run.
+ -->
+<Configure class="org.eclipse.jetty.quickstart.QuickStartWebApp">
+ <Set name="autoPreconfigure">true</Set>
+ <Set name="contextPath">/</Set>
+ <Set name="war"><Property name="jetty.webapps" default="."/>/application.war</Set>
+</Configure>
diff --git a/jetty-quickstart/src/main/config/modules/quickstart.mod b/jetty-quickstart/src/main/config/modules/quickstart.mod
new file mode 100644
index 0000000..89db9fd
--- /dev/null
+++ b/jetty-quickstart/src/main/config/modules/quickstart.mod
@@ -0,0 +1,12 @@
+#
+# Jetty Quickstart module
+#
+
+[depend]
+server
+plus
+annotations
+
+
+[lib]
+lib/jetty-quickstart-${jetty.version}.jar
diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/PreconfigureDescriptorProcessor.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/PreconfigureDescriptorProcessor.java
new file mode 100644
index 0000000..627277e
--- /dev/null
+++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/PreconfigureDescriptorProcessor.java
@@ -0,0 +1,88 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.quickstart;
+
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.webapp.Descriptor;
+import org.eclipse.jetty.webapp.IterativeDescriptorProcessor;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.xml.XmlParser;
+
+/**
+ * Preconfigure DescriptorProcessor
+ *
+ * Saves literal XML snippets
+ *
+ */
+
+public class PreconfigureDescriptorProcessor extends IterativeDescriptorProcessor
+{
+ private static final Logger LOG = Log.getLogger(PreconfigureDescriptorProcessor.class);
+
+ private final StringBuilder _buffer = new StringBuilder();
+ private final boolean _showOrigin;
+ private String _origin;
+
+ public PreconfigureDescriptorProcessor ()
+ {
+ _showOrigin=LOG.isDebugEnabled();
+ try
+ {
+ registerVisitor("env-entry", getClass().getDeclaredMethod("saveSnippet", __signature));
+ registerVisitor("resource-ref", getClass().getDeclaredMethod("saveSnippet", __signature));
+ registerVisitor("resource-env-ref", getClass().getDeclaredMethod("saveSnippet", __signature));
+ registerVisitor("message-destination-ref", getClass().getDeclaredMethod("saveSnippet", __signature));
+ registerVisitor("data-source", getClass().getDeclaredMethod("saveSnippet", __signature));
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public void start(WebAppContext context, Descriptor descriptor)
+ {
+ LOG.debug("process {}",descriptor);
+ _origin=(" <!-- "+descriptor+" -->\n");
+ }
+
+
+ @Override
+ public void end(WebAppContext context,Descriptor descriptor)
+ {
+ }
+
+
+ public void saveSnippet (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
+ throws Exception
+ {
+ LOG.debug("save {}",node.getTag());
+ if (_showOrigin)
+ _buffer.append(_origin);
+ _buffer.append(" ").append(node.toString()).append("\n");
+ }
+
+ public String getXML()
+ {
+ return _buffer.toString();
+ }
+
+}
diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/PreconfigureQuickStartWar.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/PreconfigureQuickStartWar.java
new file mode 100644
index 0000000..204ad2e
--- /dev/null
+++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/PreconfigureQuickStartWar.java
@@ -0,0 +1,129 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.quickstart;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.resource.JarResource;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.xml.XmlConfiguration;
+
+public class PreconfigureQuickStartWar
+{
+ private static final Logger LOG = Log.getLogger(PreconfigureQuickStartWar.class);
+ static final boolean ORIGIN=LOG.isDebugEnabled();
+
+
+ public static void main(String... args) throws Exception
+ {
+ Resource war = null;
+ Resource dir = null;
+ Resource xml = null;
+
+ switch (args.length)
+ {
+ case 0:
+ error("No WAR file or directory given");
+ break;
+
+ case 1:
+ dir = Resource.newResource(args[0]);
+
+ case 2:
+ war = Resource.newResource(args[0]);
+ if (war.isDirectory())
+ {
+ dir = war;
+ war = null;
+ xml = Resource.newResource(args[1]);
+ }
+ else
+ {
+ dir = Resource.newResource(args[1]);
+ }
+
+ break;
+
+ case 3:
+ war = Resource.newResource(args[0]);
+ dir = Resource.newResource(args[1]);
+ xml = Resource.newResource(args[2]);
+ break;
+
+ default:
+ error("Too many args");
+ break;
+ }
+
+
+ preconfigure(war,dir,xml);
+ }
+
+ /**
+ * @param war The war (or directory) to preconfigure
+ * @param dir The directory to expand the war into (or null if war is a directory)
+ * @param xml A context XML to apply (or null if none)
+ * @throws Exception
+ */
+ public static void preconfigure(Resource war, Resource dir, Resource xml) throws Exception
+ {
+ // Do we need to unpack a war?
+ if (war != null)
+ {
+ if (war.isDirectory())
+ error("war file is directory");
+
+ if (!dir.exists())
+ dir.getFile().mkdirs();
+ JarResource.newJarResource(war).copyTo(dir.getFile());
+ }
+
+ final Server server = new Server();
+
+ QuickStartWebApp webapp = new QuickStartWebApp();
+
+ if (xml != null)
+ {
+ if (xml.isDirectory() || !xml.toString().toLowerCase().endsWith(".xml"))
+ error("Bad context.xml: "+xml);
+ XmlConfiguration xmlConfiguration = new XmlConfiguration(xml.getURL());
+ xmlConfiguration.configure(webapp);
+ }
+ webapp.setResourceBase(dir.getFile().getAbsolutePath());
+ webapp.setPreconfigure(true);
+ server.setHandler(webapp);
+ server.start();
+ server.stop();
+ }
+
+
+
+
+ private static void error(String message)
+ {
+ System.err.println("ERROR: " + message);
+ System.err.println("Usage: java -jar PreconfigureQuickStartWar.jar <war-directory>");
+ System.err.println(" java -jar PreconfigureQuickStartWar.jar <war-directory> <context-xml-file>");
+ System.err.println(" java -jar PreconfigureQuickStartWar.jar <war-file> <target-war-directory>");
+ System.err.println(" java -jar PreconfigureQuickStartWar.jar <war-file> <target-war-directory> <context-xml-file>");
+ System.exit(1);
+ }
+
+}
diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java
new file mode 100644
index 0000000..313c5c0
--- /dev/null
+++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java
@@ -0,0 +1,139 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.quickstart;
+
+import org.eclipse.jetty.annotations.AnnotationConfiguration;
+import org.eclipse.jetty.annotations.AnnotationDecorator;
+import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.webapp.StandardDescriptorProcessor;
+import org.eclipse.jetty.webapp.WebAppClassLoader;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.webapp.WebInfConfiguration;
+
+/**
+ * QuickStartConfiguration
+ *
+ * Re-inflate a deployable webapp from a saved effective-web.xml
+ * which combines all pre-parsed web xml descriptors and annotations.
+ *
+ */
+public class QuickStartConfiguration extends WebInfConfiguration
+{
+ private static final Logger LOG = Log.getLogger(QuickStartConfiguration.class);
+
+ /**
+ * @see org.eclipse.jetty.webapp.AbstractConfiguration#preConfigure(org.eclipse.jetty.webapp.WebAppContext)
+ */
+ @Override
+ public void preConfigure(WebAppContext context) throws Exception
+ {
+ //check that webapp is suitable for quick start - it is not a packed war
+ String war = context.getWar();
+ if (war == null || war.length()<=0)
+ throw new IllegalStateException ("No location for webapp");
+
+ //Make a temp directory for the webapp if one is not already set
+ resolveTempDirectory(context);
+
+ Resource webApp = context.newResource(war);
+
+ // Accept aliases for WAR files
+ if (webApp.getAlias() != null)
+ {
+ LOG.debug(webApp + " anti-aliased to " + webApp.getAlias());
+ webApp = context.newResource(webApp.getAlias());
+ }
+
+ // Is the WAR usable directly?
+ if (!webApp.exists() || !webApp.isDirectory() || webApp.toString().startsWith("jar:"))
+ throw new IllegalStateException("Webapp does not exist or is not unpacked");
+
+ context.setBaseResource(webApp);
+
+ LOG.debug("webapp={}",webApp);
+
+
+ //look for effective-web.xml in WEB-INF of webapp
+ Resource webInf = context.getWebInf();
+ if (webInf == null || !webInf.exists())
+ throw new IllegalStateException("No WEB-INF");
+ LOG.debug("webinf={}",webInf);
+
+ Resource quickStartWebXml = webInf.addPath("quickstart-web.xml");
+ if (!quickStartWebXml.exists())
+ throw new IllegalStateException ("No WEB-INF/quickstart-web.xml");
+ LOG.debug("quickStartWebXml={}",quickStartWebXml);
+
+ context.getMetaData().setWebXml(quickStartWebXml);
+ }
+
+
+ /**
+ * @see org.eclipse.jetty.webapp.AbstractConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)
+ */
+ @Override
+ public void configure(WebAppContext context) throws Exception
+ {
+ LOG.debug("configure {}",this);
+ if (context.isStarted())
+ {
+ LOG.warn("Cannot configure webapp after it is started");
+ return;
+ }
+
+ //Temporary: set up the classpath here. This should be handled by the QuickStartDescriptorProcessor
+ Resource webInf = context.getWebInf();
+
+ if (webInf != null && webInf.isDirectory() && context.getClassLoader() instanceof WebAppClassLoader)
+ {
+ // Look for classes directory
+ Resource classes= webInf.addPath("classes/");
+ if (classes.exists())
+ ((WebAppClassLoader)context.getClassLoader()).addClassPath(classes);
+
+ // Look for jars
+ Resource lib= webInf.addPath("lib/");
+ if (lib.exists() || lib.isDirectory())
+ ((WebAppClassLoader)context.getClassLoader()).addJars(lib);
+ }
+
+ //add the processor to handle normal web.xml content
+ context.getMetaData().addDescriptorProcessor(new StandardDescriptorProcessor());
+
+ //add a processor to handle extended web.xml format
+ context.getMetaData().addDescriptorProcessor(new QuickStartDescriptorProcessor());
+
+ //add a decorator that will find introspectable annotations
+ context.addDecorator(new AnnotationDecorator(context)); //this must be the last Decorator because they are run in reverse order!
+
+ //add a context bean that will run ServletContainerInitializers as the context starts
+ ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZER_STARTER);
+ if (starter != null)
+ throw new IllegalStateException("ServletContainerInitializersStarter already exists");
+ starter = new ServletContainerInitializersStarter(context);
+ context.setAttribute(AnnotationConfiguration.CONTAINER_INITIALIZER_STARTER, starter);
+ context.addBean(starter, true);
+
+ LOG.debug("configured {}",this);
+ }
+
+}
diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorProcessor.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorProcessor.java
new file mode 100644
index 0000000..7e5a6c8
--- /dev/null
+++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorProcessor.java
@@ -0,0 +1,218 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.quickstart;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+
+import org.eclipse.jetty.annotations.AnnotationConfiguration;
+import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
+import org.eclipse.jetty.plus.annotation.ContainerInitializer;
+import org.eclipse.jetty.util.QuotedStringTokenizer;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.util.resource.ResourceCollection;
+import org.eclipse.jetty.webapp.Descriptor;
+import org.eclipse.jetty.webapp.IterativeDescriptorProcessor;
+import org.eclipse.jetty.webapp.MetaInfConfiguration;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.xml.XmlParser;
+
+/**
+ * QuickStartDescriptorProcessor
+ *
+ * Handle extended elements for quickstart-web.xml
+ */
+public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor
+{
+ /**
+ *
+ */
+ public QuickStartDescriptorProcessor()
+ {
+ try
+ {
+ registerVisitor("context-param", this.getClass().getDeclaredMethod("visitContextParam", __signature));
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * @see org.eclipse.jetty.webapp.IterativeDescriptorProcessor#start(org.eclipse.jetty.webapp.WebAppContext, org.eclipse.jetty.webapp.Descriptor)
+ */
+ @Override
+ public void start(WebAppContext context, Descriptor descriptor)
+ {
+ }
+
+ /**
+ * @see org.eclipse.jetty.webapp.IterativeDescriptorProcessor#end(org.eclipse.jetty.webapp.WebAppContext, org.eclipse.jetty.webapp.Descriptor)
+ */
+ @Override
+ public void end(WebAppContext context, Descriptor descriptor)
+ {
+ }
+
+
+ /**
+ * @param context
+ * @param descriptor
+ * @param node
+ */
+ public void visitContextParam (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
+ throws Exception
+ {
+ String name = node.getString("param-name", false, true);
+ String value = node.getString("param-value", false, true);
+ List<String> values = new ArrayList<>();
+
+ // extract values
+ switch(name)
+ {
+ case ServletContext.ORDERED_LIBS:
+ case AnnotationConfiguration.CONTAINER_INITIALIZERS:
+ case MetaInfConfiguration.METAINF_TLDS:
+ case MetaInfConfiguration.METAINF_RESOURCES:
+
+ context.removeAttribute(name);
+
+ QuotedStringTokenizer tok = new QuotedStringTokenizer(value,",");
+ while(tok.hasMoreElements())
+ values.add(tok.nextToken().trim());
+
+ break;
+
+ default:
+ values.add(value);
+ }
+
+ // handle values
+ switch(name)
+ {
+ case ServletContext.ORDERED_LIBS:
+ {
+ List<Object> libs = new ArrayList<>();
+ Object o=context.getAttribute(ServletContext.ORDERED_LIBS);
+ if (o instanceof Collection<?>)
+ libs.addAll((Collection<?>)o);
+ libs.addAll(values);
+ if (libs.size()>0)
+ context.setAttribute(ServletContext.ORDERED_LIBS,libs);
+
+ break;
+ }
+
+ case AnnotationConfiguration.CONTAINER_INITIALIZERS:
+ {
+ for (String i : values)
+ visitContainerInitializer(context, new ContainerInitializer(Thread.currentThread().getContextClassLoader(), i));
+ break;
+ }
+
+ case MetaInfConfiguration.METAINF_TLDS:
+ {
+ List<Object> tlds = new ArrayList<>();
+ String war=context.getBaseResource().getURI().toString();
+ Object o=context.getAttribute(MetaInfConfiguration.METAINF_TLDS);
+ if (o instanceof Collection<?>)
+ tlds.addAll((Collection<?>)o);
+ for (String i : values)
+ {
+ Resource r = Resource.newResource(i.replace("${WAR}/",war));
+ if (r.exists())
+ tlds.add(r.getURL());
+ else
+ throw new IllegalArgumentException("TLD not found: "+r);
+ }
+
+ if (tlds.size()>0)
+ context.setAttribute(MetaInfConfiguration.METAINF_TLDS,tlds);
+ break;
+ }
+
+ case MetaInfConfiguration.METAINF_RESOURCES:
+ {
+ String war=context.getBaseResource().getURI().toString();
+ for (String i : values)
+ {
+ Resource r = Resource.newResource(i.replace("${WAR}/",war));
+ if (r.exists())
+ visitMetaInfResource(context,r);
+ else
+ throw new IllegalArgumentException("Resource not found: "+r);
+ }
+ break;
+ }
+
+ default:
+
+ }
+ }
+
+
+ public void visitContainerInitializer (WebAppContext context, ContainerInitializer containerInitializer)
+ {
+ if (containerInitializer == null)
+ return;
+
+ //add the ContainerInitializer to the list of container initializers
+ List<ContainerInitializer> containerInitializers = (List<ContainerInitializer>)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
+ if (containerInitializers == null)
+ {
+ containerInitializers = new ArrayList<ContainerInitializer>();
+ context.setAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS, containerInitializers);
+ }
+
+ containerInitializers.add(containerInitializer);
+
+ //Ensure a bean is set up on the context that will invoke the ContainerInitializers as the context starts
+ ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZER_STARTER);
+ if (starter == null)
+ {
+ starter = new ServletContainerInitializersStarter(context);
+ context.setAttribute(AnnotationConfiguration.CONTAINER_INITIALIZER_STARTER, starter);
+ context.addBean(starter, true);
+ }
+ }
+
+
+ public void visitMetaInfResource (WebAppContext context, Resource dir)
+ {
+ Collection<Resource> metaInfResources = (Collection<Resource>)context.getAttribute(MetaInfConfiguration.METAINF_RESOURCES);
+ if (metaInfResources == null)
+ {
+ metaInfResources = new HashSet<Resource>();
+ context.setAttribute(MetaInfConfiguration.METAINF_RESOURCES, metaInfResources);
+ }
+ metaInfResources.add(dir);
+ //also add to base resource of webapp
+ Resource[] collection=new Resource[metaInfResources.size()+1];
+ int i=0;
+ collection[i++]=context.getBaseResource();
+ for (Resource resource : metaInfResources)
+ collection[i++]=resource;
+ context.setBaseResource(new ResourceCollection(collection));
+ }
+}
diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartWebApp.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartWebApp.java
new file mode 100644
index 0000000..bcbcab8
--- /dev/null
+++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartWebApp.java
@@ -0,0 +1,720 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.quickstart;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.MultipartConfigElement;
+import javax.servlet.ServletContext;
+import javax.servlet.SessionCookieConfig;
+import javax.servlet.SessionTrackingMode;
+import javax.servlet.descriptor.JspPropertyGroupDescriptor;
+import javax.servlet.descriptor.TaglibDescriptor;
+
+import org.eclipse.jetty.annotations.AnnotationConfiguration;
+import org.eclipse.jetty.http.MimeTypes;
+import org.eclipse.jetty.plus.annotation.LifeCycleCallback;
+import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
+import org.eclipse.jetty.security.ConstraintAware;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.SecurityHandler;
+import org.eclipse.jetty.security.authentication.FormAuthenticator;
+import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
+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.QuotedStringTokenizer;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.resource.JarResource;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.util.security.Constraint;
+import org.eclipse.jetty.webapp.MetaData;
+import org.eclipse.jetty.webapp.MetaData.OriginInfo;
+import org.eclipse.jetty.webapp.MetaInfConfiguration;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.xml.XmlAppendable;
+
+/**
+ * QuickStartWar
+ *
+ */
+public class QuickStartWebApp extends WebAppContext
+{
+ private static final Logger LOG = Log.getLogger(QuickStartWebApp.class);
+
+ public static final String[] __configurationClasses = new String[]
+ {
+ org.eclipse.jetty.quickstart.QuickStartConfiguration.class.getCanonicalName(),
+ org.eclipse.jetty.plus.webapp.EnvConfiguration.class.getCanonicalName(),
+ org.eclipse.jetty.plus.webapp.PlusConfiguration.class.getCanonicalName(),
+ org.eclipse.jetty.webapp.JettyWebXmlConfiguration.class.getCanonicalName()
+ };
+
+
+ private boolean _preconfigure=false;
+ private boolean _autoPreconfigure=false;
+ private boolean _startWebapp=false;
+ private PreconfigureDescriptorProcessor _preconfigProcessor;
+
+
+ public static final String[] __preconfigurationClasses = new String[]
+ {
+ org.eclipse.jetty.webapp.WebInfConfiguration.class.getCanonicalName(),
+ org.eclipse.jetty.webapp.WebXmlConfiguration.class.getCanonicalName(),
+ org.eclipse.jetty.webapp.MetaInfConfiguration.class.getCanonicalName(),
+ org.eclipse.jetty.webapp.FragmentConfiguration.class.getCanonicalName(),
+ org.eclipse.jetty.plus.webapp.EnvConfiguration.class.getCanonicalName(),
+ org.eclipse.jetty.plus.webapp.PlusConfiguration.class.getCanonicalName(),
+ org.eclipse.jetty.annotations.AnnotationConfiguration.class.getCanonicalName(),
+ };
+
+ public QuickStartWebApp()
+ {
+ super();
+ setConfigurationClasses(__preconfigurationClasses);
+ setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",".*\\.jar");
+ }
+
+ public boolean isPreconfigure()
+ {
+ return _preconfigure;
+ }
+
+ /* ------------------------------------------------------------ */
+ /** Preconfigure webapp
+ * @param preconfigure If true, then starting the webapp will generate
+ * the WEB-INF/quickstart-web.xml rather than start the webapp.
+ */
+ public void setPreconfigure(boolean preconfigure)
+ {
+ _preconfigure = preconfigure;
+ }
+
+ public boolean isAutoPreconfigure()
+ {
+ return _autoPreconfigure;
+ }
+
+ public void setAutoPreconfigure(boolean autoPrecompile)
+ {
+ _autoPreconfigure = autoPrecompile;
+ }
+
+ @Override
+ protected void startWebapp() throws Exception
+ {
+ if (isPreconfigure())
+ generateQuickstartWebXml(_preconfigProcessor.getXML());
+
+ if (_startWebapp)
+ super.startWebapp();
+ }
+
+ @Override
+ protected void doStart() throws Exception
+ {
+ // unpack and Adjust paths.
+ Resource war = null;
+ Resource dir = null;
+
+ Resource base = getBaseResource();
+ if (base==null)
+ base=Resource.newResource(getWar());
+
+ if (base.isDirectory())
+ dir=base;
+ else if (base.toString().toLowerCase().endsWith(".war"))
+ {
+ war=base;
+ String w=war.toString();
+ dir=Resource.newResource(w.substring(0,w.length()-4));
+
+ if (!dir.exists())
+ {
+ LOG.info("Quickstart Extract " + war + " to " + dir);
+ dir.getFile().mkdirs();
+ JarResource.newJarResource(war).copyTo(dir.getFile());
+ }
+
+ setWar(null);
+ setBaseResource(dir);
+ }
+ else
+ throw new IllegalArgumentException();
+
+
+ Resource qswebxml=dir.addPath("/WEB-INF/quickstart-web.xml");
+
+ if (isPreconfigure())
+ {
+ _preconfigProcessor = new PreconfigureDescriptorProcessor();
+ getMetaData().addDescriptorProcessor(_preconfigProcessor);
+ _startWebapp=false;
+ }
+ else if (qswebxml.exists())
+ {
+ setConfigurationClasses(__configurationClasses);
+ _startWebapp=true;
+ }
+ else if (_autoPreconfigure)
+ {
+ LOG.info("Quickstart preconfigure: {}(war={},dir={})",this,war,dir);
+
+ _preconfigProcessor = new PreconfigureDescriptorProcessor();
+
+ getMetaData().addDescriptorProcessor(_preconfigProcessor);
+ setPreconfigure(true);
+ _startWebapp=true;
+ }
+ else
+ _startWebapp=true;
+
+ super.doStart();
+ }
+
+
+ public void generateQuickstartWebXml(String extraXML) throws IOException
+ {
+ getMetaData().getOrigins();
+ // dumpStdErr();
+
+ if (getBaseResource()==null)
+ throw new IllegalArgumentException("No base resource for "+this);
+
+ File webxml = new File(getWebInf().getFile(),"quickstart-web.xml");
+
+ LOG.info("Quickstart generate {}",webxml);
+
+ XmlAppendable out = new XmlAppendable(new FileOutputStream(webxml),"UTF-8");
+ MetaData md = getMetaData();
+
+ Map<String, String> webappAttr = new HashMap<>();
+ webappAttr.put("xmlns","http://xmlns.jcp.org/xml/ns/javaee");
+ webappAttr.put("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ webappAttr.put("xsi:schemaLocation","http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd");
+ webappAttr.put("metadata-complete","true");
+ webappAttr.put("version","3.1");
+
+ out.open("web-app",webappAttr);
+
+ if (getDisplayName() != null)
+ out.tag("display-name",getDisplayName());
+
+ // Set some special context parameters
+
+ // The location of the war file on disk
+ String resourceBase=getBaseResource().getFile().getCanonicalFile().getAbsoluteFile().toURI().toString();
+
+ // The library order
+ addContextParamFromAttribute(out,ServletContext.ORDERED_LIBS);
+ //the servlet container initializers
+ addContextParamFromAttribute(out,AnnotationConfiguration.CONTAINER_INITIALIZERS);
+ //the tlds discovered
+ addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_TLDS,resourceBase);
+ //the META-INF/resources discovered
+ addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_RESOURCES,resourceBase);
+
+
+ // init params
+ for (String p : getInitParams().keySet())
+ out.open("context-param",origin(md,"context-param." + p))
+ .tag("param-name",p)
+ .tag("param-value",getInitParameter(p))
+ .close();
+
+ if (getEventListeners() != null)
+ for (EventListener e : getEventListeners())
+ out.open("listener",origin(md,e.getClass().getCanonicalName() + ".listener"))
+ .tag("listener-class",e.getClass().getCanonicalName())
+ .close();
+
+ ServletHandler servlets = getServletHandler();
+
+ if (servlets.getFilters() != null)
+ {
+ for (FilterHolder holder : servlets.getFilters())
+ outholder(out,md,"filter",holder);
+ }
+
+ if (servlets.getFilterMappings() != null)
+ {
+ for (FilterMapping mapping : servlets.getFilterMappings())
+ {
+ out.open("filter-mapping");
+ out.tag("filter-name",mapping.getFilterName());
+ if (mapping.getPathSpecs() != null)
+ for (String s : mapping.getPathSpecs())
+ out.tag("url-pattern",s);
+ if (mapping.getServletNames() != null)
+ for (String n : mapping.getServletNames())
+ out.tag("servlet-name",n);
+
+ if (!mapping.isDefaultDispatches())
+ {
+ if (mapping.appliesTo(DispatcherType.REQUEST))
+ out.tag("dispatcher","REQUEST");
+ if (mapping.appliesTo(DispatcherType.ASYNC))
+ out.tag("dispatcher","ASYNC");
+ if (mapping.appliesTo(DispatcherType.ERROR))
+ out.tag("dispatcher","ERROR");
+ if (mapping.appliesTo(DispatcherType.FORWARD))
+ out.tag("dispatcher","FORWARD");
+ if (mapping.appliesTo(DispatcherType.INCLUDE))
+ out.tag("dispatcher","INCLUDE");
+ }
+ out.close();
+ }
+ }
+
+ if (servlets.getServlets() != null)
+ {
+ for (ServletHolder holder : servlets.getServlets())
+ outholder(out,md,"servlet",holder);
+ }
+
+ if (servlets.getServletMappings() != null)
+ {
+ for (ServletMapping mapping : servlets.getServletMappings())
+ {
+ out.open("servlet-mapping",origin(md,mapping.getServletName() + ".servlet.mappings"));
+ out.tag("servlet-name",mapping.getServletName());
+ if (mapping.getPathSpecs() != null)
+ for (String s : mapping.getPathSpecs())
+ out.tag("url-pattern",s);
+ out.close();
+ }
+ }
+
+ // Security elements
+ SecurityHandler security = getSecurityHandler();
+
+ if (security!=null && (security.getRealmName()!=null || security.getAuthMethod()!=null))
+ {
+ out.open("login-config");
+ if (security.getAuthMethod()!=null)
+ out.tag("auth-method",origin(md,"auth-method"),security.getAuthMethod());
+ if (security.getRealmName()!=null)
+ out.tag("realm-name",origin(md,"realm-name"),security.getRealmName());
+
+
+ if (Constraint.__FORM_AUTH.equalsIgnoreCase(security.getAuthMethod()))
+ {
+ out.open("form-login-config");
+ out.tag("form-login-page",origin(md,"form-login-page"),security.getInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE));
+ out.tag("form-error-page",origin(md,"form-error-page"),security.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE));
+ out.close();
+ }
+
+ out.close();
+ }
+
+ if (security instanceof ConstraintAware)
+ {
+ ConstraintAware ca = (ConstraintAware)security;
+ for (String r:ca.getRoles())
+ out.open("security-role")
+ .tag("role-name",r)
+ .close();
+
+ for (ConstraintMapping m : ca.getConstraintMappings())
+ {
+ out.open("security-constraint");
+
+ if (m.getConstraint().getAuthenticate())
+ {
+ out.open("auth-constraint");
+ if (m.getConstraint().getRoles()!=null)
+ for (String r : m.getConstraint().getRoles())
+ out.tag("role-name",r);
+
+ out.close();
+ }
+
+ switch (m.getConstraint().getDataConstraint())
+ {
+ case Constraint.DC_NONE:
+ out.open("user-data-constraint").tag("transport-guarantee","NONE").close();
+ break;
+
+ case Constraint.DC_INTEGRAL:
+ out.open("user-data-constraint").tag("transport-guarantee","INTEGRAL").close();
+ break;
+
+ case Constraint.DC_CONFIDENTIAL:
+ out.open("user-data-constraint").tag("transport-guarantee","CONFIDENTIAL").close();
+ break;
+
+ default:
+ break;
+
+ }
+
+ out.open("web-resource-collection");
+ {
+ if (m.getConstraint().getName()!=null)
+ out.tag("web-resource-name",m.getConstraint().getName());
+ if (m.getPathSpec()!=null)
+ out.tag("url-pattern",origin(md,"constraint.url."+m.getPathSpec()),m.getPathSpec());
+ if (m.getMethod()!=null)
+ out.tag("http-method",m.getMethod());
+
+ if (m.getMethodOmissions()!=null)
+ for (String o:m.getMethodOmissions())
+ out.tag("http-method-omission",o);
+
+ out.close();
+ }
+
+ out.close();
+
+ }
+ }
+
+ if (getWelcomeFiles() != null)
+ {
+ out.open("welcome-file-list");
+ for (String welcomeFile:getWelcomeFiles())
+ {
+ out.tag("welcome-file", welcomeFile);
+ }
+ out.close();
+ }
+
+ Map<String,String> localeEncodings = getLocaleEncodings();
+ if (localeEncodings != null && !localeEncodings.isEmpty())
+ {
+ out.open("locale-encoding-mapping-list");
+ for (Map.Entry<String, String> entry:localeEncodings.entrySet())
+ {
+ out.open("locale-encoding-mapping", origin(md,"locale-encoding."+entry.getKey()));
+ out.tag("locale", entry.getKey());
+ out.tag("encoding", entry.getValue());
+ out.close();
+ }
+ out.close();
+ }
+
+ //session-config
+ if (getSessionHandler().getSessionManager() != null)
+ {
+ out.open("session-config");
+ int maxInactiveSec = getSessionHandler().getSessionManager().getMaxInactiveInterval();
+ out.tag("session-timeout", (maxInactiveSec==0?"0":Integer.toString(maxInactiveSec/60)));
+
+ Set<SessionTrackingMode> modes = getSessionHandler().getSessionManager().getEffectiveSessionTrackingModes();
+ if (modes != null)
+ {
+ for (SessionTrackingMode mode:modes)
+ out.tag("tracking-mode", mode.toString());
+ }
+
+ //cookie-config
+ SessionCookieConfig cookieConfig = getSessionHandler().getSessionManager().getSessionCookieConfig();
+ if (cookieConfig != null)
+ {
+ out.open("cookie-config");
+ if (cookieConfig.getName() != null)
+ out.tag("name", origin(md,"cookie-config.name"), cookieConfig.getName());
+
+ if (cookieConfig.getDomain() != null)
+ out.tag("domain", origin(md, "cookie-config.domain"), cookieConfig.getDomain());
+
+ if (cookieConfig.getPath() != null)
+ out.tag("path", origin(md, "cookie-config.path"), cookieConfig.getPath());
+
+ if (cookieConfig.getComment() != null)
+ out.tag("comment", origin(md, "cookie-config.comment"), cookieConfig.getComment());
+
+ out.tag("http-only", origin(md, "cookie-config.http-only"), Boolean.toString(cookieConfig.isHttpOnly()));
+ out.tag("secure", origin(md, "cookie-config.secure"), Boolean.toString(cookieConfig.isSecure()));
+ out.tag("max-age", origin(md, "cookie-config.max-age"), Integer.toString(cookieConfig.getMaxAge()));
+ out.close();
+ }
+ out.close();
+ }
+
+ //error-pages
+ Map<String,String> errorPages = ((ErrorPageErrorHandler)getErrorHandler()).getErrorPages();
+ if (errorPages != null)
+ {
+ for (Map.Entry<String, String> entry:errorPages.entrySet())
+ {
+ out.open("error-page", origin(md, "error."+entry.getKey()));
+ //a global or default error page has no code or exception
+ if (!ErrorPageErrorHandler.GLOBAL_ERROR_PAGE.equals(entry.getKey()))
+ {
+ if (entry.getKey().matches("\\d{3}"))
+ out.tag("error-code", entry.getKey());
+ else
+ out.tag("exception-type", entry.getKey());
+ }
+ out.tag("location", entry.getValue());
+ out.close();
+ }
+ }
+
+ //mime-types
+ MimeTypes mimeTypes = getMimeTypes();
+ if (mimeTypes != null)
+ {
+ for (Map.Entry<String, String> entry:mimeTypes.getMimeMap().entrySet())
+ {
+ out.open("mime-mapping");
+ out.tag("extension", origin(md, "extension."+entry.getKey()), entry.getKey());
+ out.tag("mime-type", entry.getValue());
+ out.close();
+ }
+ }
+
+ //jsp-config
+ JspConfig jspConfig = (JspConfig)getServletContext().getJspConfigDescriptor();
+ if (jspConfig != null)
+ {
+ out.open("jsp-config");
+ Collection<TaglibDescriptor> tlds = jspConfig.getTaglibs();
+ if (tlds != null && !tlds.isEmpty())
+ {
+ for (TaglibDescriptor tld:tlds)
+ {
+ out.open("taglib");
+ out.tag("taglib-uri", tld.getTaglibURI());
+ out.tag("taglib-location", tld.getTaglibLocation());
+ out.close();
+ }
+ }
+
+ Collection<JspPropertyGroupDescriptor> jspPropertyGroups = jspConfig.getJspPropertyGroups();
+ if (jspPropertyGroups != null && !jspPropertyGroups.isEmpty())
+ {
+ for (JspPropertyGroupDescriptor jspPropertyGroup:jspPropertyGroups)
+ {
+ out.open("jsp-property-group");
+ Collection<String> strings = jspPropertyGroup.getUrlPatterns();
+ if (strings != null && !strings.isEmpty())
+ {
+ for (String urlPattern:strings)
+ out.tag("url-pattern", urlPattern);
+ }
+
+ if (jspPropertyGroup.getElIgnored() != null)
+ out.tag("el-ignored", jspPropertyGroup.getElIgnored());
+
+ if (jspPropertyGroup.getPageEncoding() != null)
+ out.tag("page-encoding", jspPropertyGroup.getPageEncoding());
+
+ if (jspPropertyGroup.getScriptingInvalid() != null)
+ out.tag("scripting-invalid", jspPropertyGroup.getScriptingInvalid());
+
+ if (jspPropertyGroup.getIsXml() != null)
+ out.tag("is-xml", jspPropertyGroup.getIsXml());
+
+ if (jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral() != null)
+ out.tag("deferred-syntax-allowed-as-literal", jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral());
+
+ if (jspPropertyGroup.getTrimDirectiveWhitespaces() != null)
+ out.tag("trim-directive-whitespaces", jspPropertyGroup.getTrimDirectiveWhitespaces());
+
+ if (jspPropertyGroup.getDefaultContentType() != null)
+ out.tag("default-content-type", jspPropertyGroup.getDefaultContentType());
+
+ if (jspPropertyGroup.getBuffer() != null)
+ out.tag("buffer", jspPropertyGroup.getBuffer());
+
+ if (jspPropertyGroup.getErrorOnUndeclaredNamespace() != null)
+ out.tag("error-on-undeclared-namespace", jspPropertyGroup.getErrorOnUndeclaredNamespace());
+
+ strings = jspPropertyGroup.getIncludePreludes();
+ if (strings != null && !strings.isEmpty())
+ {
+ for (String prelude:strings)
+ out.tag("include-prelude", prelude);
+ }
+
+ strings = jspPropertyGroup.getIncludeCodas();
+ if (strings != null && !strings.isEmpty())
+ {
+ for (String coda:strings)
+ out.tag("include-coda", coda);
+ }
+
+ out.close();
+ }
+ }
+
+ out.close();
+ }
+
+ //lifecycle: post-construct, pre-destroy
+ LifeCycleCallbackCollection lifecycles = ((LifeCycleCallbackCollection)getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION));
+ if (lifecycles != null)
+ {
+ Collection<LifeCycleCallback> tmp = lifecycles.getPostConstructCallbacks();
+
+ for (LifeCycleCallback c:tmp)
+ {
+ out.open("post-construct");
+ out.tag("lifecycle-callback-class", c.getTargetClassName());
+ out.tag("lifecycle-callback-method", c.getMethodName());
+ out.close();
+ }
+
+ tmp = lifecycles.getPreDestroyCallbacks();
+ for (LifeCycleCallback c:tmp)
+ {
+ out.open("pre-destroy");
+ out.tag("lifecycle-callback-class", c.getTargetClassName());
+ out.tag("lifecycle-callback-method", c.getMethodName());
+ out.close();
+ }
+ }
+
+ out.literal(extraXML);
+
+ out.close();
+ }
+
+ private void addContextParamFromAttribute(XmlAppendable out, String attribute) throws IOException
+ {
+ addContextParamFromAttribute(out,attribute,null);
+ }
+
+ private void addContextParamFromAttribute(XmlAppendable out, String attribute, String resourceBase) throws IOException
+ {
+ Object o=getAttribute(attribute);
+ if (o==null)
+ return;
+
+ Collection<?> c = (o instanceof Collection)? (Collection<?>)o:Collections.singletonList(o);
+ StringBuilder v=new StringBuilder();
+ for (Object i:c)
+ {
+ if (i!=null)
+ {
+ if (v.length()>0)
+ v.append(",\n ");
+ else
+ v.append("\n ");
+ if (resourceBase==null)
+ QuotedStringTokenizer.quote(v,i.toString());
+ else
+ QuotedStringTokenizer.quote(v,i.toString().replace(resourceBase,"${WAR}/"));
+ }
+ }
+ out.open("context-param")
+ .tag("param-name",attribute)
+ .tagCDATA("param-value",v.toString())
+ .close();
+ }
+
+ private static void outholder(XmlAppendable out, MetaData md, String tag, Holder<?> holder) throws IOException
+ {
+ out.open(tag,Collections.singletonMap("source",holder.getSource().toString()));
+ String n = holder.getName();
+ out.tag(tag + "-name",n);
+
+ String ot = n + "." + tag + ".";
+
+ out.tag(tag + "-class",origin(md,ot + tag + "-class"),holder.getClassName());
+
+ for (String p : holder.getInitParameters().keySet())
+ {
+ if ("scratchdir".equalsIgnoreCase(p)) //don't preconfigure the temp dir for jsp output
+ continue;
+ out.open("init-param",origin(md,ot + "init-param." + p))
+ .tag("param-name",p)
+ .tag("param-value",holder.getInitParameter(p))
+ .close();
+ }
+
+ if (holder instanceof ServletHolder)
+ {
+ ServletHolder s = (ServletHolder)holder;
+ if (s.getForcedPath() != null)
+ out.tag("jsp-file",s.getForcedPath());
+
+ if (s.getInitOrder() != 0)
+ out.tag("load-on-startup",Integer.toString(s.getInitOrder()));
+
+ if (s.getRunAsRole() != null)
+ out.open("run-as",origin(md,ot + "run-as"))
+ .tag("role-name",s.getRunAsRole())
+ .close();
+
+ Map<String,String> roles = s.getRoleRefMap();
+ if (roles!=null)
+ {
+ for (Map.Entry<String, String> e : roles.entrySet())
+ {
+ out.open("security-role-ref",origin(md,ot+"role-name."+e.getKey()))
+ .tag("role-name",e.getKey())
+ .tag("role-link",e.getValue())
+ .close();
+ }
+ }
+
+ if (!s.isEnabled())
+ out.tag("enabled",origin(md,ot + "enabled"),"false");
+
+ //multipart-config
+ MultipartConfigElement multipartConfig = ((ServletHolder.Registration)s.getRegistration()).getMultipartConfig();
+ if (multipartConfig != null)
+ {
+ out.open("multipart-config", origin(md, s.getName()+".servlet.multipart-config"));
+ if (multipartConfig.getLocation() != null)
+ out.tag("location", multipartConfig.getLocation());
+ out.tag("max-file-size", Long.toString(multipartConfig.getMaxFileSize()));
+ out.tag("max-request-size", Long.toString(multipartConfig.getMaxRequestSize()));
+ out.tag("file-size-threshold", Long.toString(multipartConfig.getFileSizeThreshold()));
+ out.close();
+ }
+ }
+
+ out.tag("async-supported",origin(md,ot + "async-supported"),holder.isAsyncSupported()?"true":"false");
+ out.close();
+ }
+
+ public static Map<String, String> origin(MetaData md, String name)
+ {
+ if (!LOG.isDebugEnabled())
+ return Collections.emptyMap();
+ if (name == null)
+ return Collections.emptyMap();
+ OriginInfo origin = md.getOriginInfo(name);
+ // System.err.println("origin of "+name+" is "+origin);
+ if (origin == null)
+ return Collections.emptyMap();
+ return Collections.singletonMap("origin",origin.toString());
+
+ }
+
+}
diff --git a/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureJNDIWar.java b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureJNDIWar.java
new file mode 100644
index 0000000..570b724
--- /dev/null
+++ b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureJNDIWar.java
@@ -0,0 +1,49 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.quickstart;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+public class PreconfigureJNDIWar
+{
+ private static final long __start=System.nanoTime();
+ private static final Logger LOG = Log.getLogger(Server.class);
+
+ public static void main(String[] args) throws Exception
+ {
+ String target="target/test-jndi-preconfigured";
+ File file = new File(target);
+ if (file.exists())
+ IO.delete(file);
+
+ PreconfigureQuickStartWar.main("target/test-jndi.war",target, "src/test/resources/test-jndi.xml");
+
+ LOG.info("Preconfigured in {}ms",TimeUnit.NANOSECONDS.toMillis(System.nanoTime()-__start));
+
+ IO.copy(new FileInputStream("target/test-jndi-preconfigured/WEB-INF/quickstart-web.xml"),System.out);
+ }
+
+}
diff --git a/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureSpecWar.java b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureSpecWar.java
new file mode 100644
index 0000000..f8b49c7
--- /dev/null
+++ b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureSpecWar.java
@@ -0,0 +1,58 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.quickstart;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.resource.Resource;
+
+public class PreconfigureSpecWar
+{
+ private static final long __start=System.nanoTime();
+ private static final Logger LOG = Log.getLogger(Server.class);
+
+ public static void main(String[] args) throws Exception
+ {
+ String target="target/test-spec-preconfigured";
+ File file = new File(target);
+ if (file.exists())
+ IO.delete(file);
+
+ File realmPropertiesDest = new File ("target/test-spec-realm.properties");
+ if (realmPropertiesDest.exists())
+ IO.delete(realmPropertiesDest);
+
+ Resource realmPropertiesSrc = Resource.newResource("src/test/resources/realm.properties");
+ realmPropertiesSrc.copyTo(realmPropertiesDest);
+ System.setProperty("jetty.home", "target");
+
+ PreconfigureQuickStartWar.main("target/test-spec.war",target, "src/test/resources/test-spec.xml");
+
+ LOG.info("Preconfigured in {}ms",TimeUnit.NANOSECONDS.toMillis(System.nanoTime()-__start));
+
+ IO.copy(new FileInputStream("target/test-spec-preconfigured/WEB-INF/quickstart-web.xml"),System.out);
+ }
+
+}
diff --git a/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureStandardTestWar.java b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureStandardTestWar.java
new file mode 100644
index 0000000..91e4241
--- /dev/null
+++ b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureStandardTestWar.java
@@ -0,0 +1,62 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.quickstart;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.resource.Resource;
+
+/**
+ * PreconfigureStandardTestWar
+ *
+ */
+public class PreconfigureStandardTestWar
+{
+
+ private static final long __start=System.nanoTime();
+ private static final Logger LOG = Log.getLogger(Server.class);
+
+ public static void main(String[] args) throws Exception
+ {
+ String target="target/test-standard-preconfigured";
+ File file = new File(target);
+ if (file.exists())
+ IO.delete(file);
+
+ File realmPropertiesDest = new File ("target/test-standard-realm.properties");
+ if (realmPropertiesDest.exists())
+ IO.delete(realmPropertiesDest);
+
+ Resource realmPropertiesSrc = Resource.newResource("src/test/resources/realm.properties");
+ realmPropertiesSrc.copyTo(realmPropertiesDest);
+ System.setProperty("jetty.home", "target");
+
+ PreconfigureQuickStartWar.main("target/test-standard.war",target, "src/test/resources/test.xml");
+
+ LOG.info("Preconfigured in {}ms",TimeUnit.NANOSECONDS.toMillis(System.nanoTime()-__start));
+
+ IO.copy(new FileInputStream("target/test-standard-preconfigured/WEB-INF/quickstart-web.xml"),System.out);
+ }
+}
diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartJNDIWar.java
similarity index 60%
copy from jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java
copy to jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartJNDIWar.java
index 50a1e5b..07bc1b6 100644
--- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java
+++ b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartJNDIWar.java
@@ -16,21 +16,16 @@
// ========================================================================
//
-package org.eclipse.jetty.spdy.client;
+package org.eclipse.jetty.quickstart;
-import org.eclipse.jetty.io.ClientConnectionFactory;
+public class QuickStartJNDIWar
+{
-public abstract class NegotiatingClientConnectionFactory implements ClientConnectionFactory
-{
- private final ClientConnectionFactory connectionFactory;
-
- protected NegotiatingClientConnectionFactory(ClientConnectionFactory connectionFactory)
- {
- this.connectionFactory = connectionFactory;
+ public static void main(String... args) throws Exception
+ {
+ // Log.getRootLogger().setDebugEnabled(true);
+ Quickstart.main("target/test-jndi-preconfigured", "src/test/resources/test-jndi.xml");
}
-
- public ClientConnectionFactory getClientConnectionFactory()
- {
- return connectionFactory;
- }
+
+
}
diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartSpecWar.java
similarity index 60%
copy from jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java
copy to jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartSpecWar.java
index 50a1e5b..b84a12f 100644
--- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java
+++ b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartSpecWar.java
@@ -16,21 +16,15 @@
// ========================================================================
//
-package org.eclipse.jetty.spdy.client;
+package org.eclipse.jetty.quickstart;
-import org.eclipse.jetty.io.ClientConnectionFactory;
-public abstract class NegotiatingClientConnectionFactory implements ClientConnectionFactory
-{
- private final ClientConnectionFactory connectionFactory;
-
- protected NegotiatingClientConnectionFactory(ClientConnectionFactory connectionFactory)
- {
- this.connectionFactory = connectionFactory;
- }
-
- public ClientConnectionFactory getClientConnectionFactory()
- {
- return connectionFactory;
+public class QuickStartSpecWar
+{
+ public static void main(String... args) throws Exception
+ {
+ // Log.getRootLogger().setDebugEnabled(true);
+ System.setProperty("jetty.home", "target");
+ Quickstart.main("target/test-spec-preconfigured", "src/test/resources/test-spec.xml");
}
}
diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartStandardTestWar.java
similarity index 60%
copy from jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java
copy to jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartStandardTestWar.java
index 50a1e5b..7da8b23 100644
--- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java
+++ b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartStandardTestWar.java
@@ -16,21 +16,15 @@
// ========================================================================
//
-package org.eclipse.jetty.spdy.client;
+package org.eclipse.jetty.quickstart;
-import org.eclipse.jetty.io.ClientConnectionFactory;
-
-public abstract class NegotiatingClientConnectionFactory implements ClientConnectionFactory
+public class QuickStartStandardTestWar
{
- private final ClientConnectionFactory connectionFactory;
- protected NegotiatingClientConnectionFactory(ClientConnectionFactory connectionFactory)
- {
- this.connectionFactory = connectionFactory;
- }
-
- public ClientConnectionFactory getClientConnectionFactory()
- {
- return connectionFactory;
+ public static void main(String... args) throws Exception
+ {
+ // Log.getRootLogger().setDebugEnabled(true);
+ System.setProperty("jetty.home", "target");
+ Quickstart.main("target/test-standard-preconfigured", "src/test/resources/test.xml");
}
}
diff --git a/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/Quickstart.java b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/Quickstart.java
new file mode 100644
index 0000000..75dc114
--- /dev/null
+++ b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/Quickstart.java
@@ -0,0 +1,73 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.quickstart;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.xml.XmlConfiguration;
+
+public class Quickstart
+{
+
+ public static void main(String... args) throws Exception
+ {
+ if (args.length<1)
+ error("No WAR file or directory given");
+
+ //war file or dir to start
+ String war = args[0];
+
+ //optional jetty context xml file to configure the webapp
+ Resource contextXml = null;
+ if (args.length > 1)
+ contextXml = Resource.newResource(args[1]);
+
+ Server server = new Server(8080);
+
+ QuickStartWebApp webapp = new QuickStartWebApp();
+ webapp.setAutoPreconfigure(true);
+ webapp.setWar(war);
+ webapp.setContextPath("/");
+
+ //apply context xml file
+ if (contextXml != null)
+ {
+ // System.err.println("Applying "+contextXml);
+ XmlConfiguration xmlConfiguration = new XmlConfiguration(contextXml.getURL());
+ xmlConfiguration.configure(webapp);
+ }
+
+ server.setHandler(webapp);
+
+ server.start();
+
+
+
+ server.join();
+ }
+
+
+ private static void error(String message)
+ {
+ System.err.println("ERROR: "+message);
+ System.err.println("Usage: java -jar QuickStartWar.jar <war-directory> <context-xml>");
+ System.err.println(" java -jar QuickStartWar.jar <war-file> <context-xml>");
+ System.exit(1);
+ }
+}
diff --git a/jetty-quickstart/src/test/resources/realm.properties b/jetty-quickstart/src/test/resources/realm.properties
new file mode 100644
index 0000000..9d88b85
--- /dev/null
+++ b/jetty-quickstart/src/test/resources/realm.properties
@@ -0,0 +1,21 @@
+#
+# This file defines users passwords and roles for a HashUserRealm
+#
+# The format is
+# <username>: <password>[,<rolename> ...]
+#
+# Passwords may be clear text, obfuscated or checksummed. The class
+# org.eclipse.util.Password should be used to generate obfuscated
+# passwords or password checksums
+#
+# If DIGEST Authentication is used, the password must be in a recoverable
+# format, either plain text or OBF:.
+#
+jetty: MD5:164c88b302622e17050af52c89945d44,user
+admin: CRYPT:adpexzg3FUZAk,server-administrator,content-administrator,admin,user
+other: OBF:1xmk1w261u9r1w1c1xmq,user
+plain: plain,user
+user: password,user
+
+# This entry is for digest auth. The credential is a MD5 hash of username:realmname:password
+digest: MD5:6e120743ad67abfbc385bc2bb754e297,user
diff --git a/jetty-quickstart/src/test/resources/test-jndi.xml b/jetty-quickstart/src/test/resources/test-jndi.xml
new file mode 100644
index 0000000..14c0934
--- /dev/null
+++ b/jetty-quickstart/src/test/resources/test-jndi.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+
+<!-- =============================================================== -->
+<!-- Configure the test-jndi webapp -->
+<!-- =============================================================== -->
+<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
+
+ <New id="tx" class="org.eclipse.jetty.plus.jndi.Transaction">
+ <Arg>
+ <New class="com.acme.MockUserTransaction"/>
+ </Arg>
+ </New>
+
+ <!-- Define an env entry with Server scope for java:comp/env -->
+ <New id="woggle" class="org.eclipse.jetty.plus.jndi.EnvEntry">
+ <Arg><Property name='server'/></Arg>
+ <Arg>woggle</Arg>
+ <Arg type="java.lang.Integer">4000</Arg>
+ <Arg type="boolean">false</Arg>
+ </New>
+
+ <!-- Define an env entry with webapp scope for java:comp/env -->
+ <New id="wiggle" class="org.eclipse.jetty.plus.jndi.EnvEntry">
+ <Arg><Ref refid='wac'/></Arg>
+ <Arg>wiggle</Arg>
+ <Arg type="java.lang.Double">100</Arg>
+ <Arg type="boolean">true</Arg>
+ </New>
+
+ <!-- Mail Session setup -->
+ <New id="xxxmail" class="org.eclipse.jetty.plus.jndi.Resource">
+ <Arg><Ref refid='wac'/></Arg>
+ <Arg>mail/Session</Arg>
+ <Arg>
+ <New class="org.eclipse.jetty.jndi.factories.MailSessionReference">
+ <Set name="user">CHANGE-ME</Set>
+ <Set name="password">CHANGE-ME</Set>
+ <Set name="properties">
+ <New class="java.util.Properties">
+ <Put name="mail.smtp.auth">false</Put> <!-- change to true if you want to authenticate -->
+ <Put name="mail.smtp.host">CHANGE-ME</Put>
+ <Put name="mail.from">CHANGE-ME</Put>
+ <Put name="mail.debug">false</Put>
+ </New>
+ </Set>
+ </New>
+ </Arg>
+ </New>
+
+ <!-- A mock DataSource -->
+ <New id="mydatasource" class="org.eclipse.jetty.plus.jndi.Resource">
+ <Arg><Ref refid='wac'/></Arg>
+ <Arg>jdbc/mydatasource</Arg>
+ <Arg>
+ <New class="com.acme.MockDataSource"/>
+ </Arg>
+ </New>
+
+</Configure>
diff --git a/jetty-quickstart/src/test/resources/test-spec.xml b/jetty-quickstart/src/test/resources/test-spec.xml
new file mode 100644
index 0000000..99fc577
--- /dev/null
+++ b/jetty-quickstart/src/test/resources/test-spec.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+
+<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
+
+ <New id="tx" class="org.eclipse.jetty.plus.jndi.Transaction">
+ <Arg>
+ <New class="com.acme.MockUserTransaction"/>
+ </Arg>
+ </New>
+
+ <Get name="securityHandler">
+ <Set name="loginService">
+ <New class="org.eclipse.jetty.security.HashLoginService">
+ <Set name="name">Test Realm</Set>
+ <Set name="config"><SystemProperty name="jetty.home" default="."/>/test-spec-realm.properties</Set>
+ </New>
+ </Set>
+ </Get>
+
+
+ <New id="maxAmount" class="org.eclipse.jetty.plus.jndi.EnvEntry">
+ <Arg><Ref refid='wac'/></Arg>
+ <Arg>maxAmount</Arg>
+ <Arg type="java.lang.Double">100</Arg>
+ <Arg type="boolean">true</Arg>
+ </New>
+
+
+ <New id="mydatasource" class="org.eclipse.jetty.plus.jndi.Resource">
+ <Arg><Ref refid='wac'/></Arg>
+ <Arg>jdbc/mydatasource</Arg>
+ <Arg>
+ <New class="com.acme.MockDataSource">
+ </New>
+ </Arg>
+ </New>
+
+</Configure>
diff --git a/jetty-quickstart/src/test/resources/test.xml b/jetty-quickstart/src/test/resources/test.xml
new file mode 100644
index 0000000..bbdf08a
--- /dev/null
+++ b/jetty-quickstart/src/test/resources/test.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+
+<!-- ==================================================================
+Configure and deploy the test web application in $(jetty.home)/webapps/test
+
+Note. If this file did not exist or used a context path other that /test
+then the default configuration of jetty.xml would discover the test
+webapplication with a WebAppDeployer. By specifying a context in this
+directory, additional configuration may be specified and hot deployments
+detected.
+===================================================================== -->
+
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+
+ <Set name="contextPath">/test</Set>
+
+ <Get name="securityHandler">
+ <Set name="loginService">
+ <New class="org.eclipse.jetty.security.HashLoginService">
+ <Set name="name">Test Realm</Set>
+ <Set name="config"><SystemProperty name="jetty.home" default="."/>/test-standard-realm.properties</Set>
+ </New>
+ </Set>
+ <Set name="authenticator">
+ <New class="org.eclipse.jetty.security.authentication.FormAuthenticator">
+ <Set name="alwaysSaveUri">true</Set>
+ </New>
+ </Set>
+ <Set name="checkWelcomeFiles">true</Set>
+ </Get>
+
+ <!-- Non standard error page mapping -->
+ <!--
+ <Get name="errorHandler">
+ <Call name="addErrorPage">
+ <Arg type="int">500</Arg>
+ <Arg type="int">599</Arg>
+ <Arg type="String">/dump/errorCodeRangeMapping</Arg>
+ </Call>
+ </Get>
+ -->
+
+
+</Configure>
diff --git a/jetty-rewrite/pom.xml b/jetty-rewrite/pom.xml
index ef63744..6b611c3 100644
--- a/jetty-rewrite/pom.xml
+++ b/jetty-rewrite/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-rewrite</artifactId>
diff --git a/jetty-runner/pom.xml b/jetty-runner/pom.xml
index 4c98ff3..950f3b5 100644
--- a/jetty-runner/pom.xml
+++ b/jetty-runner/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-runner</artifactId>
diff --git a/jetty-security/pom.xml b/jetty-security/pom.xml
index 6dbc0e1..e4071d2 100644
--- a/jetty-security/pom.xml
+++ b/jetty-security/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-security</artifactId>
diff --git a/jetty-server/pom.xml b/jetty-server/pom.xml
index d7d2a18..f860621 100644
--- a/jetty-server/pom.xml
+++ b/jetty-server/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-server</artifactId>
diff --git a/jetty-server/src/main/config/modules/ext.mod b/jetty-server/src/main/config/modules/ext.mod
index 1207bdd..56b10f7 100644
--- a/jetty-server/src/main/config/modules/ext.mod
+++ b/jetty-server/src/main/config/modules/ext.mod
@@ -1,9 +1,9 @@
#
-# Module to add all lib/ext/*.jar files to classpath
+# Module to add all lib/ext/**.jar files to classpath
#
[lib]
-regex:lib/ext/.*\.jar$
+lib/ext/**.jar
[files]
lib/
diff --git a/jetty-server/src/main/config/modules/server.mod b/jetty-server/src/main/config/modules/server.mod
index b0c3d08..3cdac35 100644
--- a/jetty-server/src/main/config/modules/server.mod
+++ b/jetty-server/src/main/config/modules/server.mod
@@ -4,7 +4,6 @@
[optional]
jvm
-jmx
ext
resources
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 9d8b0ae..cd4a169 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
@@ -68,7 +68,7 @@
* HttpTransport.completed().
*
*/
-public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
+public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, HttpParser.ProxyHandler
{
private static final Logger LOG = Log.getLogger(HttpChannel.class);
private static final ThreadLocal<HttpChannel<?>> __currentChannel = new ThreadLocal<>();
@@ -478,6 +478,15 @@
}
@Override
+ public void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort)
+ {
+ _request.setAttribute("PROXY", protocol);
+ _request.setServerName(sAddr);
+ _request.setServerPort(dPort);
+ _request.setRemoteAddr(InetSocketAddress.createUnresolved(sAddr,sPort));
+ }
+
+ @Override
public boolean startRequest(HttpMethod httpMethod, String method, ByteBuffer uri, HttpVersion version)
{
_expect = false;
@@ -842,4 +851,5 @@
}
}
+
}
diff --git a/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NegotiatingServerConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/NegotiatingServerConnection.java
similarity index 98%
rename from jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NegotiatingServerConnection.java
rename to jetty-server/src/main/java/org/eclipse/jetty/server/NegotiatingServerConnection.java
index b1fb87e..3d01069 100644
--- a/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NegotiatingServerConnection.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/NegotiatingServerConnection.java
@@ -16,7 +16,7 @@
// ========================================================================
//
-package org.eclipse.jetty.spdy.server;
+package org.eclipse.jetty.server;
import java.io.IOException;
import java.util.List;
diff --git a/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NegotiatingServerConnectionFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/NegotiatingServerConnectionFactory.java
similarity index 98%
rename from jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NegotiatingServerConnectionFactory.java
rename to jetty-server/src/main/java/org/eclipse/jetty/server/NegotiatingServerConnectionFactory.java
index 4ec3e91..f826d71 100644
--- a/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NegotiatingServerConnectionFactory.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/NegotiatingServerConnectionFactory.java
@@ -16,7 +16,7 @@
// ========================================================================
//
-package org.eclipse.jetty.spdy.server;
+package org.eclipse.jetty.server;
import java.util.Arrays;
import java.util.Iterator;
diff --git a/jetty-servlet/pom.xml b/jetty-servlet/pom.xml
index 46325d6..b9542c9 100644
--- a/jetty-servlet/pom.xml
+++ b/jetty-servlet/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlet</artifactId>
diff --git a/jetty-servlets/pom.xml b/jetty-servlets/pom.xml
index 3c8210c..8f3d5af 100644
--- a/jetty-servlets/pom.xml
+++ b/jetty-servlets/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlets</artifactId>
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 dc2a9c6..ba56bc7 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
@@ -47,32 +47,33 @@
//-----------------------------------------------------------------------------
/**
* CGI Servlet.
- * <p/>
- * The cgi bin directory can be set with the "cgibinResourceBase" init parameter or it will default to the resource base of the context. If the
- * "cgibinResourceBaseIsRelative" init parameter is set the resource base is relative to the webapp. For example "WEB-INF/cgi" would work.
- * <br/>
- * Not that this only works for extracted war files as "jar cf" will not reserve the execute permissions on the cgi files.
- * <p/>
- * The "commandPrefix" init parameter may be used to set a prefix to all commands passed to exec. This can be used on systems that need assistance to execute a
- * particular file type. For example on windows this can be set to "perl" so that perl scripts are executed.
- * <p/>
- * The "Path" init param is passed to the exec environment as PATH. Note: Must be run unpacked somewhere in the filesystem.
- * <p/>
- * Any initParameter that starts with ENV_ is used to set an environment variable with the name stripped of the leading ENV_ and using the init parameter value.
+ * <p>
+ *
+ * The following init parameters are used to configure this servlet:
+ * <dl>
+ * <dt>cgibinResourceBase</dt><dd>Path to the cgi bin directory if set or it will default to the resource base of the context.</dd>
+ * <dt>resourceBase</dt><dd>An alias for cgibinResourceBase.</dd>
+ * <dt>cgibinResourceBaseIsRelative</dt><dd>If true then cgibinResourceBase is relative to the webapp (eg "WEB-INF/cgi")</dd>
+ * <dt>commandPrefix</dt><dd>may be used to set a prefix to all commands passed to exec. This can be used on systems that need assistance to execute a
+ * particular file type. For example on windows this can be set to "perl" so that perl scripts are executed.</dd>
+ * <dt>Path</dt><dd>passed to the exec environment as PATH.</dd>
+ * <dt>ENV_*</dt><dd>used to set an arbitrary environment variable with the name stripped of the leading ENV_ and using the init parameter value</dd>
+ * <dt>useFullPath</dt><dd>If true, the full URI path within the context is used for the exec command, otherwise a search is done for a partial URL that matches an exec Command</dd>
+ * </dl>
+ *
*/
public class CGI extends HttpServlet
{
- /**
- *
- */
- private static final long serialVersionUID = -6182088932884791073L;
+ private static final long serialVersionUID = -6182088932884791074L;
private static final Logger LOG = Log.getLogger(CGI.class);
private boolean _ok;
private File _docRoot;
+ private boolean _cgiBinProvided;
private String _path;
private String _cmdPrefix;
+ private boolean _useFullPath;
private EnvList _env;
private boolean _ignoreExitState;
private boolean _relative;
@@ -83,16 +84,22 @@
{
_env = new EnvList();
_cmdPrefix = getInitParameter("commandPrefix");
+ _useFullPath = Boolean.parseBoolean(getInitParameter("useFullPath"));
_relative = Boolean.parseBoolean(getInitParameter("cgibinResourceBaseIsRelative"));
String tmp = getInitParameter("cgibinResourceBase");
- if (tmp == null)
+ if (tmp != null)
+ _cgiBinProvided = true;
+ else
{
tmp = getInitParameter("resourceBase");
- if (tmp == null)
+ if (tmp != null)
+ _cgiBinProvided = true;
+ else
tmp = getServletContext().getRealPath("/");
}
- else if (_relative)
+
+ if (_relative && _cgiBinProvided)
{
tmp = getServletContext().getRealPath(tmp);
}
@@ -137,10 +144,10 @@
_env.set("PATH",_path);
_ignoreExitState = "true".equalsIgnoreCase(getInitParameter("ignoreExitState"));
- Enumeration e = getInitParameterNames();
+ Enumeration<String> e = getInitParameterNames();
while (e.hasMoreElements())
{
- String n = (String)e.nextElement();
+ String n = e.nextElement();
if (n != null && n.startsWith("ENV_"))
_env.set(n.substring(4),getInitParameter(n));
}
@@ -166,7 +173,6 @@
return;
}
- String pathInContext = (_relative?"":StringUtil.nonNull(req.getServletPath())) + StringUtil.nonNull(req.getPathInfo());
if (LOG.isDebugEnabled())
{
LOG.debug("CGI: ContextPath : " + req.getContextPath());
@@ -180,63 +186,69 @@
// pathInContext may actually comprises scriptName/pathInfo...We will
// walk backwards up it until we find the script - the rest must
// be the pathInfo;
+ String pathInContext = (_relative ? "" : StringUtil.nonNull(req.getServletPath())) + StringUtil.nonNull(req.getPathInfo());
+ File execCmd = new File(_docRoot, pathInContext);
+ String pathInfo = pathInContext;
- String both = pathInContext;
- String first = both;
- String last = "";
-
- File exe = new File(_docRoot,first);
-
- while ((first.endsWith("/") || !exe.exists()) && first.length() >= 0)
+ if(!_useFullPath)
{
- int index = first.lastIndexOf('/');
+ String path = pathInContext;
+ String info = "";
- first = first.substring(0,index);
- last = both.substring(index,both.length());
- exe = new File(_docRoot,first);
- }
-
- if (first.length() == 0 || !exe.exists() || exe.isDirectory() || !exe.getCanonicalPath().equals(exe.getAbsolutePath()))
- {
- res.sendError(404);
- }
- else
- {
- if (LOG.isDebugEnabled())
+ // Search docroot for a matching execCmd
+ while (path.endsWith("/") && path.length() >= 0)
{
- LOG.debug("CGI: script is " + exe);
- LOG.debug("CGI: pathInfo is " + last);
+ if(!execCmd.exists())
+ break;
+
+ int index = path.lastIndexOf('/');
+
+ path = path.substring(0,index);
+ info = pathInContext.substring(index,pathInContext.length());
+ execCmd = new File(_docRoot,path);
}
- exec(exe,last,req,res);
+
+ if (path.length() == 0 || !execCmd.exists() || execCmd.isDirectory() || !execCmd.getCanonicalPath().equals(execCmd.getAbsolutePath()))
+ {
+ res.sendError(404);
+ }
+
+ pathInfo = info;
}
+ exec(execCmd,pathInfo,req,res);
}
- /* ------------------------------------------------------------ */
+ /** executes the CGI process
/*
- * @param root @param path @param req @param res @exception IOException
+ * @param command the command to execute, this command is prefixed by
+ * the context parameter "commandPrefix".
+ * @param pathInfo The PATH_INFO to process,
+ * see http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getPathInfo%28%29. Cannot be null
+ * @param req
+ * @param res
+ * @exception IOException
*/
private void exec(File command, String pathInfo, HttpServletRequest req, HttpServletResponse res) throws IOException
{
- String path = command.getAbsolutePath();
- File dir = command.getParentFile();
- String scriptName = req.getRequestURI().substring(0,req.getRequestURI().length() - pathInfo.length());
- String scriptPath = getServletContext().getRealPath(scriptName);
- String pathTranslated = req.getPathTranslated();
+ assert req != null;
+ assert res != null;
+ assert pathInfo != null;
+ assert command != null;
- int len = req.getContentLength();
- if (len < 0)
- len = 0;
- if ((pathTranslated == null) || (pathTranslated.length() == 0))
- pathTranslated = path;
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("CGI: script is " + command);
+ LOG.debug("CGI: pathInfo is " + pathInfo);
+ }
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();
+ Enumeration<String> names = req.getParameterNames();
while (names.hasMoreElements())
{
- String parameterName = (String)names.nextElement();
+ String parameterName = names.nextElement();
parameterMap.addValues(parameterName, req.getParameterValues(parameterName));
}
bodyFormEncoded = UrlEncoded.encode(parameterMap, Charset.forName(req.getCharacterEncoding()), true);
@@ -247,24 +259,33 @@
// look at :
// http://Web.Golux.Com/coar/cgi/draft-coar-cgi-v11-03-clean.html#6.1.1
env.set("AUTH_TYPE", req.getAuthType());
+
+ int contentLen = req.getContentLength();
+ if (contentLen < 0)
+ contentLen = 0;
if (bodyFormEncoded != null)
{
env.set("CONTENT_LENGTH", Integer.toString(bodyFormEncoded.length()));
}
else
{
- env.set("CONTENT_LENGTH", Integer.toString(len));
+ env.set("CONTENT_LENGTH", Integer.toString(contentLen));
}
env.set("CONTENT_TYPE", req.getContentType());
env.set("GATEWAY_INTERFACE", "CGI/1.1");
- if ((pathInfo != null) && (pathInfo.length() > 0))
+ if (pathInfo.length() > 0)
{
env.set("PATH_INFO", pathInfo);
}
+
+ String pathTranslated = req.getPathTranslated();
+ if ((pathTranslated == null) || (pathTranslated.length() == 0))
+ pathTranslated = pathInfo;
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
@@ -272,17 +293,33 @@
// "REMOTE_IDENT" => "NYI"
env.set("REMOTE_USER", req.getRemoteUser());
env.set("REQUEST_METHOD", req.getMethod());
- env.set("SCRIPT_NAME", scriptName);
+
+ String scriptPath;
+ String scriptName;
+ // use docRoot for scriptPath, too
+ if(_cgiBinProvided)
+ {
+ scriptPath = command.getAbsolutePath();
+ scriptName = scriptPath.substring(_docRoot.getAbsolutePath().length());
+ }
+ else
+ {
+ String requestURI = req.getRequestURI();
+ scriptName = requestURI.substring(0,requestURI.length() - pathInfo.length());
+ scriptPath = getServletContext().getRealPath(scriptName);
+ }
env.set("SCRIPT_FILENAME", scriptPath);
+ env.set("SCRIPT_NAME", scriptName);
+
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();
+ Enumeration<String> enm = req.getHeaderNames();
while (enm.hasMoreElements())
{
- String name = (String)enm.nextElement();
+ String name = enm.nextElement();
String value = req.getHeader(name);
env.set("HTTP_" + name.toUpperCase(Locale.ENGLISH).replace('-','_'),value);
}
@@ -293,29 +330,30 @@
// "SERVER_URL" => "NYI - http://us0245",
// "TZ" => System.getProperty("user.timezone"),
- // are we meant to decode args here ? or does the script get them
- // via PATH_INFO ? if we are, they should be decoded and passed
+ // are we meant to decode args here? or does the script get them
+ // via PATH_INFO? if we are, they should be decoded and passed
// into exec here...
- String execCmd = path;
- if ((execCmd.charAt(0) != '"') && (execCmd.indexOf(" ") >= 0))
+ String absolutePath = command.getAbsolutePath();
+ String execCmd = absolutePath;
+
+ // escape the execCommand
+ if (execCmd.length() > 0 && execCmd.charAt(0) != '"' && execCmd.indexOf(" ") >= 0)
execCmd = "\"" + execCmd + "\"";
+
if (_cmdPrefix != null)
execCmd = _cmdPrefix + " " + execCmd;
+ assert execCmd != null;
LOG.debug("Environment: " + env.getExportString());
LOG.debug("Command: " + execCmd);
- final Process p;
- if (dir == null)
- p = Runtime.getRuntime().exec(execCmd, env.getEnvArray());
- else
- p = Runtime.getRuntime().exec(execCmd, env.getEnvArray(), dir);
+ final Process p = Runtime.getRuntime().exec(execCmd, env.getEnvArray(), _docRoot);
// hook processes input to browser's output (async)
if (bodyFormEncoded != null)
writeProcessInput(p, bodyFormEncoded);
- else if (len > 0)
- writeProcessInput(p, req.getInputStream(), len);
+ else if (contentLen > 0)
+ writeProcessInput(p, req.getInputStream(), contentLen);
// hook processes output to browser's input (sync)
// if browser closes stream, we should detect it and kill process...
@@ -336,9 +374,9 @@
{
LOG.warn(e);
}
- }
+ }
});
-
+
// read any headers off the top of our input stream
// NOTE: Multiline header items not supported!
String line = null;
@@ -383,7 +421,7 @@
int exitValue = p.exitValue();
if (0 != exitValue)
{
- LOG.warn("Non-zero exit status (" + exitValue + ") from CGI program: " + path);
+ LOG.warn("Non-zero exit status (" + exitValue + ") from CGI program: " + absolutePath);
if (!res.isCommitted())
res.sendError(500,"Failed to exec CGI");
}
@@ -393,7 +431,7 @@
{
// browser has probably closed its input stream - we
// terminate and clean up...
- LOG.debug("CGI: Client closed connection!");
+ LOG.debug("CGI: Client closed connection!", e);
}
catch (InterruptedException ie)
{
@@ -422,6 +460,7 @@
{
new Thread(new Runnable()
{
+ @Override
public void run()
{
try
@@ -445,6 +484,7 @@
new Thread(new Runnable()
{
+ @Override
public void run()
{
try
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/GzipHttpOutput.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/GzipHttpOutput.java
index 53931e4..3151ab8 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/GzipHttpOutput.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/GzipHttpOutput.java
@@ -115,37 +115,13 @@
private void gzip(ByteBuffer content, boolean complete, final Callback callback)
{
- if (content.hasRemaining())
+ if (content.hasRemaining() || complete)
{
if (content.hasArray())
new GzipArrayCB(content,complete,callback).iterate();
else
new GzipBufferCB(content,complete,callback).iterate();
}
- else if (complete)
- {
- _deflater.finish();
-
- int produced=_deflater.deflate(_buffer.array(),_buffer.arrayOffset()+_buffer.limit(),_buffer.capacity()-_buffer.limit(),Deflater.NO_FLUSH);
- _buffer.limit(_buffer.limit()+produced);
- addTrailer();
- superWrite(_buffer,complete,new Callback()
- {
- @Override
- public void succeeded()
- {
- getHttpChannel().getByteBufferPool().release(_buffer);
- _buffer=null;
- callback.succeeded();
- }
-
- @Override
- public void failed(Throwable x)
- {
- callback.failed(x);
- }
- });
- }
}
protected void commit(ByteBuffer content, boolean complete, Callback callback)
diff --git a/jetty-spdy/pom.xml b/jetty-spdy/pom.xml
index 5027233..716ea6c 100644
--- a/jetty-spdy/pom.xml
+++ b/jetty-spdy/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -21,18 +21,19 @@
<module>spdy-http-server</module>
<module>spdy-http-client-transport</module>
<module>spdy-example-webapp</module>
+ <module>spdy-alpn-tests</module>
</modules>
<profiles>
- <profile>
- <id>jdk7-npn</id>
- <activation>
- <jdk>[1.7,1.8)</jdk>
- </activation>
- <modules>
- <module>spdy-npn-tests</module>
- </modules>
- </profile>
+ <profile>
+ <id>npn</id>
+ <activation>
+ <jdk>1.7</jdk>
+ </activation>
+ <modules>
+ <module>spdy-npn-tests</module>
+ </modules>
+ </profile>
</profiles>
<build>
diff --git a/jetty-spdy/spdy-alpn-tests/pom.xml b/jetty-spdy/spdy-alpn-tests/pom.xml
new file mode 100644
index 0000000..393532c
--- /dev/null
+++ b/jetty-spdy/spdy-alpn-tests/pom.xml
@@ -0,0 +1,95 @@
+<?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/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.eclipse.jetty.spdy</groupId>
+ <artifactId>spdy-parent</artifactId>
+ <version>9.2.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>spdy-alpn-tests</artifactId>
+ <name>Jetty :: SPDY :: ALPN Tests</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.mortbay.jetty.alpn</groupId>
+ <artifactId>alpn-boot</artifactId>
+ <version>${alpn.version}</version>
+ <type>jar</type>
+ <overWrite>false</overWrite>
+ <outputDirectory>${project.build.directory}/alpn</outputDirectory>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <argLine>-Xbootclasspath/p:${project.build.directory}/alpn/alpn-boot-${alpn.version}.jar</argLine>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty.alpn</groupId>
+ <artifactId>alpn-api</artifactId>
+ <version>${alpn.api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-alpn-server</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.spdy</groupId>
+ <artifactId>spdy-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.spdy</groupId>
+ <artifactId>spdy-http-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.spdy</groupId>
+ <artifactId>spdy-http-server</artifactId>
+ <version>${project.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/jetty-spdy/spdy-alpn-tests/src/test/java/org/eclipse/jetty/spdy/server/ALPNNegotiationTest.java b/jetty-spdy/spdy-alpn-tests/src/test/java/org/eclipse/jetty/spdy/server/ALPNNegotiationTest.java
new file mode 100644
index 0000000..0f3c4be
--- /dev/null
+++ b/jetty-spdy/spdy-alpn-tests/src/test/java/org/eclipse/jetty/spdy/server/ALPNNegotiationTest.java
@@ -0,0 +1,216 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.spdy.server;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.List;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+
+import org.eclipse.jetty.alpn.ALPN;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ALPNNegotiationTest extends AbstractALPNTest
+{
+ @Test
+ public void testClientAdvertisingHTTPServerSpeaksHTTP() throws Exception
+ {
+ InetSocketAddress address = prepare();
+ connector.addConnectionFactory(new HttpConnectionFactory());
+
+ SslContextFactory sslContextFactory = newSslContextFactory();
+ sslContextFactory.start();
+ SSLContext sslContext = sslContextFactory.getSslContext();
+
+ try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket(address.getAddress(), address.getPort()))
+ {
+ client.setUseClientMode(true);
+ client.setSoTimeout(5000);
+
+ ALPN.put(client, new ALPN.ClientProvider()
+ {
+ @Override
+ public boolean supports()
+ {
+ return true;
+ }
+
+ @Override
+ public void unsupported()
+ {
+ }
+
+ @Override
+ public List<String> protocols()
+ {
+ return Arrays.asList("http/1.1");
+ }
+
+ @Override
+ public void selected(String protocol)
+ {
+ Assert.assertEquals("http/1.1", protocol);
+ }
+ });
+
+ client.startHandshake();
+
+ // Verify that the server really speaks http/1.1
+
+ OutputStream output = client.getOutputStream();
+ output.write(("" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + address.getPort() + "\r\n" +
+ "\r\n" +
+ "").getBytes(StandardCharsets.UTF_8));
+ output.flush();
+
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
+ String line = reader.readLine();
+ Assert.assertTrue(line.contains(" 404 "));
+ }
+ }
+
+ @Test
+ public void testClientAdvertisingMultipleProtocolsServerSpeaksHTTPWhenNegotiated() throws Exception
+ {
+ InetSocketAddress address = prepare();
+ connector.addConnectionFactory(new HttpConnectionFactory());
+
+ SslContextFactory sslContextFactory = newSslContextFactory();
+ sslContextFactory.start();
+ SSLContext sslContext = sslContextFactory.getSslContext();
+ try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket(address.getAddress(), address.getPort()))
+ {
+ client.setUseClientMode(true);
+ client.setSoTimeout(5000);
+
+ ALPN.put(client, new ALPN.ClientProvider()
+ {
+ @Override
+ public boolean supports()
+ {
+ return true;
+ }
+
+ @Override
+ public void unsupported()
+ {
+ }
+
+ @Override
+ public List<String> protocols()
+ {
+ return Arrays.asList("unknown/1.0", "http/1.1");
+ }
+
+ @Override
+ public void selected(String protocol)
+ {
+ Assert.assertEquals("http/1.1", protocol);
+ }
+ });
+
+ client.startHandshake();
+
+ // Verify that the server really speaks http/1.1
+
+ OutputStream output = client.getOutputStream();
+ output.write(("" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + address.getPort() + "\r\n" +
+ "\r\n" +
+ "").getBytes(StandardCharsets.UTF_8));
+ output.flush();
+
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
+ String line = reader.readLine();
+ Assert.assertTrue(line.contains(" 404 "));
+ }
+ }
+
+ @Test
+ public void testClientNotSupportingALPNServerSpeaksDefaultProtocol() throws Exception
+ {
+ InetSocketAddress address = prepare();
+ connector.addConnectionFactory(new HttpConnectionFactory());
+
+ SslContextFactory sslContextFactory = newSslContextFactory();
+ sslContextFactory.start();
+ SSLContext sslContext = sslContextFactory.getSslContext();
+ try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket(address.getAddress(), address.getPort()))
+ {
+ client.setUseClientMode(true);
+ client.setSoTimeout(5000);
+
+ ALPN.put(client, new ALPN.ClientProvider()
+ {
+ @Override
+ public boolean supports()
+ {
+ return false;
+ }
+
+ @Override
+ public void unsupported()
+ {
+ }
+
+ @Override
+ public List<String> protocols()
+ {
+ return null;
+ }
+
+ @Override
+ public void selected(String s)
+ {
+ }
+ });
+
+ client.startHandshake();
+
+ // Verify that the server really speaks http/1.1
+
+ OutputStream output = client.getOutputStream();
+ output.write(("" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + address.getPort() + "\r\n" +
+ "\r\n" +
+ "").getBytes(StandardCharsets.UTF_8));
+ output.flush();
+
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
+ String line = reader.readLine();
+ Assert.assertTrue(line.contains(" 404 "));
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-alpn-tests/src/test/java/org/eclipse/jetty/spdy/server/ALPNSynReplyTest.java b/jetty-spdy/spdy-alpn-tests/src/test/java/org/eclipse/jetty/spdy/server/ALPNSynReplyTest.java
new file mode 100644
index 0000000..d9f9270
--- /dev/null
+++ b/jetty-spdy/spdy-alpn-tests/src/test/java/org/eclipse/jetty/spdy/server/ALPNSynReplyTest.java
@@ -0,0 +1,160 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.spdy.server;
+
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.util.List;
+import javax.net.ssl.SSLEngine;
+
+import org.eclipse.jetty.alpn.ALPN;
+import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ALPNSynReplyTest extends AbstractALPNTest
+{
+ @Test
+ public void testGentleCloseDuringHandshake() throws Exception
+ {
+ InetSocketAddress address = prepare();
+ SslContextFactory sslContextFactory = newSslContextFactory();
+ sslContextFactory.start();
+ SSLEngine sslEngine = sslContextFactory.newSSLEngine(address);
+ sslEngine.setUseClientMode(true);
+ ALPN.put(sslEngine, new ALPN.ClientProvider()
+ {
+ @Override
+ public boolean supports()
+ {
+ return true;
+ }
+
+ @Override
+ public void unsupported()
+ {
+ }
+
+ @Override
+ public List<String> protocols()
+ {
+ return null;
+ }
+
+ @Override
+ public void selected(String protocol)
+ {
+ }
+ });
+ sslEngine.beginHandshake();
+
+ ByteBuffer encrypted = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize());
+ sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted);
+ encrypted.flip();
+
+ try (SocketChannel channel = SocketChannel.open(address))
+ {
+ // Send ClientHello, immediately followed by TLS Close Alert and then by FIN
+ channel.write(encrypted);
+ sslEngine.closeOutbound();
+ encrypted.clear();
+ sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted);
+ encrypted.flip();
+ channel.write(encrypted);
+ channel.shutdownOutput();
+
+ // Read ServerHello from server
+ encrypted.clear();
+ int read = channel.read(encrypted);
+ encrypted.flip();
+ Assert.assertTrue(read > 0);
+ // Cannot decrypt, as the SSLEngine has been already closed
+
+ // Now if we read more, we should either read the TLS Close Alert, or directly -1
+ encrypted.clear();
+ read = channel.read(encrypted);
+ // Sending a TLS Close Alert during handshake results in an exception when
+ // unwrapping that the server react to by closing the connection abruptly.
+ Assert.assertTrue(read < 0);
+ }
+ }
+
+ @Test
+ public void testAbruptCloseDuringHandshake() throws Exception
+ {
+ InetSocketAddress address = prepare();
+ SslContextFactory sslContextFactory = newSslContextFactory();
+ sslContextFactory.start();
+ SSLEngine sslEngine = sslContextFactory.newSSLEngine(address);
+ sslEngine.setUseClientMode(true);
+ ALPN.put(sslEngine, new ALPN.ClientProvider()
+ {
+ @Override
+ public boolean supports()
+ {
+ return true;
+ }
+
+ @Override
+ public void unsupported()
+ {
+ }
+
+ @Override
+ public List<String> protocols()
+ {
+ return null;
+ }
+
+ @Override
+ public void selected(String s)
+ {
+ }
+ });
+ sslEngine.beginHandshake();
+
+ ByteBuffer encrypted = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize());
+ sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted);
+ encrypted.flip();
+
+ try (SocketChannel channel = SocketChannel.open(address))
+ {
+ // Send ClientHello, immediately followed by FIN (no TLS Close Alert)
+ channel.write(encrypted);
+ channel.shutdownOutput();
+
+ // Read ServerHello from server
+ encrypted.clear();
+ int read = channel.read(encrypted);
+ encrypted.flip();
+ Assert.assertTrue(read > 0);
+ ByteBuffer decrypted = ByteBuffer.allocate(sslEngine.getSession().getApplicationBufferSize());
+ sslEngine.unwrap(encrypted, decrypted);
+
+ // Now if we read more, we should either read the TLS Close Alert, or directly -1
+ encrypted.clear();
+ read = channel.read(encrypted);
+ // Since we have close the connection abruptly, the server also does so
+ Assert.assertTrue(read < 0);
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-alpn-tests/src/test/java/org/eclipse/jetty/spdy/server/AbstractALPNTest.java b/jetty-spdy/spdy-alpn-tests/src/test/java/org/eclipse/jetty/spdy/server/AbstractALPNTest.java
new file mode 100644
index 0000000..652d887
--- /dev/null
+++ b/jetty-spdy/spdy-alpn-tests/src/test/java/org/eclipse/jetty/spdy/server/AbstractALPNTest.java
@@ -0,0 +1,78 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.spdy.server;
+
+import java.net.InetSocketAddress;
+
+import org.eclipse.jetty.alpn.ALPN;
+import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.spdy.client.SPDYClient;
+import org.eclipse.jetty.toolchain.test.TestTracker;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.junit.After;
+import org.junit.Rule;
+
+public class AbstractALPNTest
+{
+ @Rule
+ public final TestTracker tracker = new TestTracker();
+ protected Server server;
+ protected SPDYServerConnector connector;
+ protected SPDYClient.Factory clientFactory;
+
+ protected InetSocketAddress prepare() throws Exception
+ {
+ server = new Server();
+ connector = new SPDYServerConnector(server, newSslContextFactory(), null, new ALPNServerConnectionFactory("spdy/3", "spdy/2", "http/1.1"));
+ connector.setPort(0);
+ connector.setIdleTimeout(30000);
+ server.addConnector(connector);
+ server.start();
+
+ QueuedThreadPool threadPool = new QueuedThreadPool();
+ threadPool.setName(threadPool.getName() + "-client");
+ clientFactory = new SPDYClient.Factory(threadPool);
+ clientFactory.start();
+
+ ALPN.debug = true;
+
+ return new InetSocketAddress("localhost", connector.getLocalPort());
+ }
+
+ protected SslContextFactory newSslContextFactory()
+ {
+ SslContextFactory sslContextFactory = new SslContextFactory();
+ sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
+ sslContextFactory.setKeyStorePassword("storepwd");
+ sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks");
+ sslContextFactory.setTrustStorePassword("storepwd");
+ sslContextFactory.setProtocol("TLSv1");
+ sslContextFactory.setIncludeProtocols("TLSv1");
+ return sslContextFactory;
+ }
+
+ @After
+ public void dispose() throws Exception
+ {
+ clientFactory.stop();
+ server.stop();
+ }
+}
diff --git a/jetty-spdy/spdy-alpn-tests/src/test/resources/jetty-logging.properties b/jetty-spdy/spdy-alpn-tests/src/test/resources/jetty-logging.properties
new file mode 100644
index 0000000..ead13ec
--- /dev/null
+++ b/jetty-spdy/spdy-alpn-tests/src/test/resources/jetty-logging.properties
@@ -0,0 +1,2 @@
+org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
+#org.eclipse.jetty.spdy.LEVEL=DEBUG
diff --git a/jetty-spdy/spdy-alpn-tests/src/test/resources/keystore.jks b/jetty-spdy/spdy-alpn-tests/src/test/resources/keystore.jks
new file mode 100644
index 0000000..428ba54
--- /dev/null
+++ b/jetty-spdy/spdy-alpn-tests/src/test/resources/keystore.jks
Binary files differ
diff --git a/jetty-spdy/spdy-alpn-tests/src/test/resources/truststore.jks b/jetty-spdy/spdy-alpn-tests/src/test/resources/truststore.jks
new file mode 100644
index 0000000..839cb8c
--- /dev/null
+++ b/jetty-spdy/spdy-alpn-tests/src/test/resources/truststore.jks
Binary files differ
diff --git a/jetty-spdy/spdy-client/pom.xml b/jetty-spdy/spdy-client/pom.xml
index f3e2ed1..5bbfd33 100644
--- a/jetty-spdy/spdy-client/pom.xml
+++ b/jetty-spdy/spdy-client/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -29,7 +29,7 @@
<configuration>
<instructions>
<Export-Package>org.eclipse.jetty.spdy.client;version="9.1"</Export-Package>
- <Import-Package>!org.eclipse.jetty.npn,org.eclipse.jetty.*;version="[9.0,10.0)",*</Import-Package>
+ <Import-Package>!org.eclipse.jetty.npn,!org.eclipse.jetty.alpn,org.eclipse.jetty.*;version="[9.0,10.0)",*</Import-Package>
</instructions>
</configuration>
</execution>
@@ -45,6 +45,17 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-alpn-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.alpn</groupId>
+ <artifactId>alpn-api</artifactId>
+ <version>${alpn.api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>org.eclipse.jetty.npn</groupId>
<artifactId>npn-api</artifactId>
<version>${npn.api.version}</version>
diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnection.java b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnection.java
index c8e85f2..69c11d8 100644
--- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnection.java
+++ b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnection.java
@@ -25,6 +25,7 @@
import org.eclipse.jetty.io.ClientConnectionFactory;
import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.io.NegotiatingClientConnection;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnectionFactory.java b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnectionFactory.java
index d045801..2a7d332 100644
--- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnectionFactory.java
+++ b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NPNClientConnectionFactory.java
@@ -26,6 +26,7 @@
import org.eclipse.jetty.io.ClientConnectionFactory;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.io.NegotiatingClientConnectionFactory;
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
public class NPNClientConnectionFactory extends NegotiatingClientConnectionFactory
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 d30bc99..786833d 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
@@ -37,6 +37,7 @@
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.MappedByteBufferPool;
+import org.eclipse.jetty.io.NegotiatingClientConnectionFactory;
import org.eclipse.jetty.io.SelectChannelEndPoint;
import org.eclipse.jetty.io.SelectorManager;
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
diff --git a/jetty-spdy/spdy-core/pom.xml b/jetty-spdy/spdy-core/pom.xml
index db39f06..8154ab7 100644
--- a/jetty-spdy/spdy-core/pom.xml
+++ b/jetty-spdy/spdy-core/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-spdy/spdy-example-webapp/pom.xml b/jetty-spdy/spdy-example-webapp/pom.xml
index 5cd47a6..6cfb0d8 100644
--- a/jetty-spdy/spdy-example-webapp/pom.xml
+++ b/jetty-spdy/spdy-example-webapp/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spdy-example-webapp</artifactId>
diff --git a/jetty-spdy/spdy-http-client-transport/pom.xml b/jetty-spdy/spdy-http-client-transport/pom.xml
index e428e24..2d1d1d0 100644
--- a/jetty-spdy/spdy-http-client-transport/pom.xml
+++ b/jetty-spdy/spdy-http-client-transport/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-spdy/spdy-http-common/pom.xml b/jetty-spdy/spdy-http-common/pom.xml
index 0184925..61fa901 100644
--- a/jetty-spdy/spdy-http-common/pom.xml
+++ b/jetty-spdy/spdy-http-common/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-spdy/spdy-http-server/pom.xml b/jetty-spdy/spdy-http-server/pom.xml
index af685e8..dea1bf5 100644
--- a/jetty-spdy/spdy-http-server/pom.xml
+++ b/jetty-spdy/spdy-http-server/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spdy-http-server</artifactId>
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 41bfb86..b094d7c 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
@@ -9,12 +9,6 @@
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
- <!-- Enables NPN debugging on System.err -->
- <!-- ===========================================================
- <Set class="org.eclipse.jetty.npn.NextProtoNego" name="debug" type="boolean">true</Set>
- -->
-
- <!-- =========================================================== -->
<!-- Create a push strategy which can be used by reference by -->
<!-- individual connection factories below. -->
<!-- -->
@@ -53,16 +47,17 @@
<!-- =========================================================== -->
<!-- Add a SPDY/HTTPS Connector. -->
<!-- Configure an o.e.j.server.ServerConnector with connection -->
- <!-- factories for TLS (aka SSL), NPN, SPDY and HTTP to provide -->
- <!-- a connector that can accept HTTPS or SPDY connections. -->
+ <!-- factories for TLS (aka SSL), ProtoNego, SPDY and HTTP to -->
+ <!-- provide a connector that can accept HTTPS or SPDY -->
+ <!-- connections. -->
<!-- -->
- <!-- All accepted TLS connections are initially wired to a NPN -->
- <!-- connection, which attempts to use a TLS extension to -->
- <!-- negotiation the protocol. If NPN is not supported by -->
- <!-- the client, then the NPN connection is replaced by a HTTP -->
+ <!-- All accepted TLS connections are initially wired to a -->
+ <!-- Protonego connection, which attempts to use a TLS extension -->
+ <!-- to negotiation the protocol. If it is not supported by -->
+ <!-- the client, then the connection is replaced by a HTTP -->
<!-- connection. If a specific protocol version (eg spdy/3) is -->
- <!-- negotiated by NPN, then the appropriate connection factory -->
- <!-- is used to create a connection to replace the NPN connection-->
+ <!-- negotiated, then the appropriate connection factory -->
+ <!-- is used to create a connection to replace the connection -->
<!-- -->
<!-- The final result is a SPDY or HTTP connection wired behind -->
<!-- a TLS (aka SSL) connection. -->
@@ -80,10 +75,10 @@
<Arg name="factories">
<Array type="org.eclipse.jetty.server.ConnectionFactory">
- <!-- SSL Connection factory with NPN as next protocol -->
+ <!-- SSL Connection factory with Protonego as next protocol -->
<Item>
<New class="org.eclipse.jetty.server.SslConnectionFactory">
- <Arg name="next">npn</Arg>
+ <Arg name="next"><Property name="protonego"/></Arg>
<Arg name="sslContextFactory">
<Ref refid="sslContextFactory"/>
</Arg>
@@ -92,16 +87,7 @@
<!-- NPN Connection factory with HTTP as default protocol -->
<Item>
- <New class="org.eclipse.jetty.spdy.server.NPNServerConnectionFactory">
- <Arg name="protocols">
- <Array type="String">
- <Item>spdy/3</Item>
- <Item>spdy/2</Item>
- <Item>http/1.1</Item>
- </Array>
- </Arg>
- <Set name="defaultProtocol">http/1.1</Set>
- </New>
+ <Ref refid="protonego"/>
</Item>
<!-- SPDY/3 Connection factory -->
diff --git a/jetty-spdy/spdy-http-server/src/main/config/etc/protonego-npn.xml b/jetty-spdy/spdy-http-server/src/main/config/etc/protonego-npn.xml
new file mode 100644
index 0000000..6e30f39
--- /dev/null
+++ b/jetty-spdy/spdy-http-server/src/main/config/etc/protonego-npn.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+
+<Configure id="protonego" class="org.eclipse.jetty.spdy.server.NPNServerConnectionFactory">
+ <Arg name="protocols">
+ <Array type="String">
+ <Item>spdy/3</Item>
+ <Item>spdy/2</Item>
+ <Item>http/1.1</Item>
+ </Array>
+ </Arg>
+
+ <Set name="defaultProtocol">http/1.1</Set>
+
+ <!-- =========================================================== -->
+ <!-- Enables NPN debugging on System.err -->
+ <!-- ===========================================================
+ <Set class="org.eclipse.jetty.npn.NextProtoNego" name="debug" type="boolean">true</Set>
+ -->
+
+</Configure>
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_04.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_04.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_04.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_04.mod
index 7a6b0ca..3d1312b 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_04.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_04.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.0.v20120525/npn-boot-1.1.0.v20120525.jar:lib/npn/npn-boot-1.1.0.v20120525.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.0.v20120525.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_05.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_05.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_05.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_05.mod
index 7a6b0ca..3d1312b 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_05.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_05.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.0.v20120525/npn-boot-1.1.0.v20120525.jar:lib/npn/npn-boot-1.1.0.v20120525.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.0.v20120525.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_06.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_06.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_06.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_06.mod
index fb258e1..8ae3b1c 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_06.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_06.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.1.v20121030/npn-boot-1.1.1.v20121030.jar:lib/npn/npn-boot-1.1.1.v20121030.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.1.v20121030.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_07.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_07.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_07.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_07.mod
index fb258e1..8ae3b1c 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_07.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_07.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.1.v20121030/npn-boot-1.1.1.v20121030.jar:lib/npn/npn-boot-1.1.1.v20121030.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.1.v20121030.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_09.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_09.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_09.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_09.mod
index b2d4780..b4415d2 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_09.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_09.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.3.v20130313/npn-boot-1.1.3.v20130313.jar:lib/npn/npn-boot-1.1.3.v20130313.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.3.v20130313.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_10.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_10.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_10.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_10.mod
index b2d4780..b4415d2 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_10.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_10.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.3.v20130313/npn-boot-1.1.3.v20130313.jar:lib/npn/npn-boot-1.1.3.v20130313.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.3.v20130313.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_11.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_11.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_11.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_11.mod
index b2d4780..b4415d2 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_11.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_11.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.3.v20130313/npn-boot-1.1.3.v20130313.jar:lib/npn/npn-boot-1.1.3.v20130313.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.3.v20130313.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_13.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_13.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_13.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_13.mod
index d177c20..c557a7c 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_13.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_13.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.4.v20130313/npn-boot-1.1.4.v20130313.jar:lib/npn/npn-boot-1.1.4.v20130313.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.4.v20130313.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_15.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_15.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_15.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_15.mod
index 0c1bc8e..98ddbe7 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_15.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_15.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.5.v20130313/npn-boot-1.1.5.v20130313.jar:lib/npn/npn-boot-1.1.5.v20130313.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.5.v20130313.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_17.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_17.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_17.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_17.mod
index 0c1bc8e..98ddbe7 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_17.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_17.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.5.v20130313/npn-boot-1.1.5.v20130313.jar:lib/npn/npn-boot-1.1.5.v20130313.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.5.v20130313.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_21.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_21.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_21.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_21.mod
index 0c1bc8e..98ddbe7 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_21.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_21.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.5.v20130313/npn-boot-1.1.5.v20130313.jar:lib/npn/npn-boot-1.1.5.v20130313.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.5.v20130313.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_25.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_25.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_25.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_25.mod
index 0c1bc8e..98ddbe7 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_25.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_25.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.5.v20130313/npn-boot-1.1.5.v20130313.jar:lib/npn/npn-boot-1.1.5.v20130313.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.5.v20130313.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_40.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_40.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_40.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_40.mod
index a067626..a7e47a5 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_40.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_40.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.6.v20130911/npn-boot-1.1.6.v20130911.jar:lib/npn/npn-boot-1.1.6.v20130911.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.6.v20130911.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_45.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_45.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_45.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_45.mod
index a067626..a7e47a5 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_45.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_45.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.6.v20130911/npn-boot-1.1.6.v20130911.jar:lib/npn/npn-boot-1.1.6.v20130911.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.6.v20130911.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_51.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_51.mod
similarity index 87%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_51.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_51.mod
index a067626..a7e47a5 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn/npn-1.7.0_51.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_51.mod
@@ -1,9 +1,8 @@
[name]
-npn-boot
+protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.6.v20130911/npn-boot-1.1.6.v20130911.jar:lib/npn/npn-boot-1.1.6.v20130911.jar
-[ini-template]
---exec
+[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.6.v20130911.jar
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/npn.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn.mod
similarity index 83%
rename from jetty-spdy/spdy-http-server/src/main/config/modules/npn.mod
rename to jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn.mod
index 36681ee..040aad1 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/npn.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn.mod
@@ -1,20 +1,8 @@
-#
-# NPN Module
-#
-
-[depend]
-npn/npn-${java.version}
-
-[files]
-lib/
-lib/npn/
-
-[ini-template]
# NPN is provided via a -Xbootclasspath that modifies the secure connections
# in java to support the NPN layer needed for SPDY.
#
# This modification has a tight dependency on specific updates of Java 1.7.
-# (No support for Java 8 currently exists for npn / npn-boot)
+# (No support for Java 8 exists for npn / npn-boot, use alpn instead)
#
# The npn module will use an appropriate npn-boot jar for your specific
# version of Java.
@@ -29,4 +17,15 @@
# http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/
+[name]
+protonego-impl
+[depend]
+protonego-impl/npn-${java.version}
+
+[xml]
+etc/protonego-npn.xml
+
+[files]
+lib/
+lib/npn/
diff --git a/jetty-spdy/spdy-http-server/src/main/config/modules/spdy.mod b/jetty-spdy/spdy-http-server/src/main/config/modules/spdy.mod
index eab614b..cf79dfa 100644
--- a/jetty-spdy/spdy-http-server/src/main/config/modules/spdy.mod
+++ b/jetty-spdy/spdy-http-server/src/main/config/modules/spdy.mod
@@ -4,7 +4,7 @@
[depend]
ssl
-npn
+protonego
[lib]
lib/spdy/*.jar
@@ -15,9 +15,12 @@
[ini-template]
## SPDY Configuration
+
# Port for SPDY connections
spdy.port=8443
+
# SPDY idle timeout in milliseconds
spdy.timeout=30000
+
# Initial Window Size for SPDY
#spdy.initialWindowSize=65536
diff --git a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/HTTPSPDYProxyServerConnector.java b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/HTTPSPDYProxyServerConnector.java
index 4c3015e..65d16e2 100644
--- a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/HTTPSPDYProxyServerConnector.java
+++ b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/HTTPSPDYProxyServerConnector.java
@@ -22,11 +22,11 @@
import java.util.Objects;
import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.server.NPNServerConnectionFactory;
-import org.eclipse.jetty.spdy.server.NegotiatingServerConnectionFactory;
import org.eclipse.jetty.spdy.server.SPDYServerConnectionFactory;
import org.eclipse.jetty.util.ssl.SslContextFactory;
diff --git a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToHTTPLoadTest.java b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToHTTPLoadTest.java
index 94e481b..9e72303 100644
--- a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToHTTPLoadTest.java
+++ b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/proxy/ProxySPDYToHTTPLoadTest.java
@@ -40,6 +40,7 @@
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
@@ -53,7 +54,6 @@
import org.eclipse.jetty.spdy.api.StringDataInfo;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.client.SPDYClient;
-import org.eclipse.jetty.spdy.server.NegotiatingServerConnectionFactory;
import org.eclipse.jetty.spdy.server.http.SPDYTestUtils;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.Callback;
diff --git a/jetty-spdy/spdy-npn-tests/pom.xml b/jetty-spdy/spdy-npn-tests/pom.xml
index 8fc12c2..23464c5 100644
--- a/jetty-spdy/spdy-npn-tests/pom.xml
+++ b/jetty-spdy/spdy-npn-tests/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-spdy/spdy-npn-tests/src/test/java/org/eclipse/jetty/spdy/server/NPNModuleTest.java b/jetty-spdy/spdy-npn-tests/src/test/java/org/eclipse/jetty/spdy/server/NPNModuleTest.java
index 8464832..b9c74a6 100644
--- a/jetty-spdy/spdy-npn-tests/src/test/java/org/eclipse/jetty/spdy/server/NPNModuleTest.java
+++ b/jetty-spdy/spdy-npn-tests/src/test/java/org/eclipse/jetty/spdy/server/NPNModuleTest.java
@@ -18,6 +18,9 @@
package org.eclipse.jetty.spdy.server;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -26,8 +29,10 @@
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
+import java.util.regex.Pattern;
import org.eclipse.jetty.start.BaseHome;
import org.eclipse.jetty.start.FileArg;
@@ -42,12 +47,6 @@
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
@RunWith(Parameterized.class)
public class NPNModuleTest
{
@@ -70,11 +69,11 @@
@Parameters(name = "{index}: mod:{0}")
public static List<Object[]> data()
{
- File npnBootModDir = MavenTestingUtils.getProjectDir("../spdy-http-server/src/main/config/modules/npn");
+ File npnBootModDir = MavenTestingUtils.getProjectDir("../spdy-http-server/src/main/config/modules/protonego-impl");
List<Object[]> data = new ArrayList<>();
for (File file : npnBootModDir.listFiles())
{
- if (file.getName().endsWith(".mod"))
+ if (Pattern.matches("npn-.*\\.mod",file.getName()))
{
data.add(new Object[] { file.getName() });
}
@@ -88,12 +87,14 @@
private static BaseHome basehome;
@BeforeClass
- public static void initBaseHome()
+ public static void initBaseHome() throws IOException
{
File homeDir = MavenTestingUtils.getProjectDir("../spdy-http-server/src/main/config");
File baseDir = MavenTestingUtils.getTargetTestingDir(NPNModuleTest.class.getName());
FS.ensureEmpty(baseDir);
- basehome = new BaseHome(homeDir,baseDir);
+
+ String cmdLine[] = { "jetty.home="+homeDir.getAbsolutePath(),"jetty.base="+baseDir.getAbsolutePath() };
+ basehome = new BaseHome(cmdLine);
}
/**
@@ -102,12 +103,12 @@
@Test
public void testModuleValues() throws IOException
{
- File modFile = basehome.getFile("modules/npn/" + modBootFile);
+ Path modFile = basehome.getPath("modules/protonego-impl/" + modBootFile);
Module mod = new Module(basehome,modFile);
assertNotNull("module",mod);
// Validate logical name
- assertThat("Module name",mod.getName(),is("npn-boot"));
+ assertThat("Module name",mod.getName(),is("protonego-boot"));
List<String> expectedBootClasspath = new ArrayList<>();
@@ -121,7 +122,7 @@
}
}
- for (String line : mod.getInitialise())
+ for (String line : mod.getJvmArgs())
{
expectedBootClasspath.remove(line);
}
@@ -129,10 +130,10 @@
if (expectedBootClasspath.size() > 0)
{
StringBuilder err = new StringBuilder();
- err.append("XBootClasspath mismatch between [files] and [ini-template]");
+ err.append("XBootClasspath mismatch between [files] and [exec]");
err.append("\nThe following are inferred from your [files] definition in ");
- err.append(modFile.getAbsolutePath());
- err.append("\nbut are not referenced in your [ini-template] section");
+ err.append(modFile.toAbsolutePath().toString());
+ err.append("\nbut are not referenced in your [exec] section");
for (String entry : expectedBootClasspath)
{
err.append("\n").append(entry);
diff --git a/jetty-spdy/spdy-server/pom.xml b/jetty-spdy/spdy-server/pom.xml
index 8266726..a67c838 100644
--- a/jetty-spdy/spdy-server/pom.xml
+++ b/jetty-spdy/spdy-server/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -29,7 +29,7 @@
<configuration>
<instructions>
<Export-Package>org.eclipse.jetty.spdy.server;version="9.1"</Export-Package>
- <Import-Package>org.eclipse.jetty.npn,org.eclipse.jetty.*;version="[9.0,10.0)",*</Import-Package>
+ <Import-Package>org.eclipse.jetty.alpn;resolution:=optional,org.eclipse.jetty.alpn.server;resolution:=optional, org.eclipse.jetty.npn;resolution:=optional,org.eclipse.jetty.*;version="[9.0,10.0)",*</Import-Package>
<_nouses>true</_nouses>
</instructions>
</configuration>
@@ -61,6 +61,12 @@
<version>${npn.api.version}</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.alpn</groupId>
+ <artifactId>alpn-api</artifactId>
+ <version>${alpn.api.version}</version>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NPNServerConnection.java b/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NPNServerConnection.java
index b58a01e..1a9e291 100644
--- a/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NPNServerConnection.java
+++ b/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NPNServerConnection.java
@@ -24,6 +24,7 @@
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.NegotiatingServerConnection;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
diff --git a/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NPNServerConnectionFactory.java b/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NPNServerConnectionFactory.java
index f0e9e01..c69f0fc 100644
--- a/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NPNServerConnectionFactory.java
+++ b/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/NPNServerConnectionFactory.java
@@ -25,6 +25,7 @@
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
diff --git a/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/SPDYServerConnector.java b/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/SPDYServerConnector.java
index 35dd6ff..cf73fe9 100644
--- a/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/SPDYServerConnector.java
+++ b/jetty-spdy/spdy-server/src/main/java/org/eclipse/jetty/spdy/server/SPDYServerConnector.java
@@ -21,6 +21,7 @@
import java.util.Objects;
import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.spdy.api.SPDY;
diff --git a/jetty-spring/pom.xml b/jetty-spring/pom.xml
index 01e1448..f467399 100644
--- a/jetty-spring/pom.xml
+++ b/jetty-spring/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-spring</artifactId>
diff --git a/jetty-start/pom.xml b/jetty-start/pom.xml
index d0d01b0..9704036 100644
--- a/jetty-start/pom.xml
+++ b/jetty-start/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-start</artifactId>
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/BaseHome.java b/jetty-start/src/main/java/org/eclipse/jetty/start/BaseHome.java
index 8fb7842..70ca6be 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/BaseHome.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/BaseHome.java
@@ -19,20 +19,24 @@
package org.eclipse.jetty.start;
import java.io.File;
-import java.io.FileFilter;
import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
+import java.nio.file.FileVisitOption;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
+import java.util.EnumSet;
import java.util.List;
+import java.util.ListIterator;
import java.util.Objects;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.eclipse.jetty.start.FS.RelativeRegexFilter;
+import org.eclipse.jetty.start.config.CommandLineConfigSource;
+import org.eclipse.jetty.start.config.ConfigSource;
+import org.eclipse.jetty.start.config.ConfigSources;
+import org.eclipse.jetty.start.config.DirConfigSource;
+import org.eclipse.jetty.start.config.JettyBaseConfigSource;
+import org.eclipse.jetty.start.config.JettyHomeConfigSource;
/**
* File access for <code>${jetty.home}</code>, <code>${jetty.base}</code>, directories.
@@ -45,45 +49,129 @@
*/
public class BaseHome
{
- private File homeDir;
- private File baseDir;
-
- public BaseHome()
+ public static class SearchDir
{
- try
- {
- this.baseDir = new File(System.getProperty("jetty.base",System.getProperty("user.dir",".")));
- URL jarfile = this.getClass().getClassLoader().getResource("org/eclipse/jetty/start/BaseHome.class");
- if (jarfile != null)
- {
- Matcher m = Pattern.compile("jar:(file:.*)!/org/eclipse/jetty/start/BaseHome.class").matcher(jarfile.toString());
- if (m.matches())
- {
- homeDir = new File(new URI(m.group(1))).getParentFile();
- }
- }
- homeDir = new File(System.getProperty("jetty.home",(homeDir == null?baseDir:homeDir).getAbsolutePath()));
+ private Path dir;
+ private String name;
- baseDir = baseDir.getAbsoluteFile().getCanonicalFile();
- homeDir = homeDir.getAbsoluteFile().getCanonicalFile();
- }
- catch (IOException | URISyntaxException e)
+ public SearchDir(String name)
{
- throw new RuntimeException(e);
+ this.name = name;
+ }
+
+ public Path getDir()
+ {
+ return dir;
+ }
+
+ public Path resolve(Path subpath)
+ {
+ return dir.resolve(subpath);
+ }
+
+ public Path resolve(String subpath)
+ {
+ return dir.resolve(FS.separators(subpath));
+ }
+
+ public SearchDir setDir(File path)
+ {
+ if (path != null)
+ {
+ return setDir(path.toPath());
+ }
+ return this;
+ }
+
+ public SearchDir setDir(Path path)
+ {
+ if (path != null)
+ {
+ this.dir = path.toAbsolutePath();
+ }
+ return this;
+ }
+
+ public SearchDir setDir(String path)
+ {
+ if (path != null)
+ {
+ return setDir(FS.toPath(path));
+ }
+ return this;
+ }
+
+ public String toShortForm(Path path)
+ {
+ Path relative = dir.relativize(path);
+ return String.format("${%s}%c%s",name,File.separatorChar,relative.toString());
}
}
- public BaseHome(File homeDir, File baseDir)
+ public static final String JETTY_BASE = "jetty.base";
+ public static final String JETTY_HOME = "jetty.home";
+ private final static EnumSet<FileVisitOption> SEARCH_VISIT_OPTIONS = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
+
+ private final static int MAX_SEARCH_DEPTH = Integer.getInteger("org.eclipse.jetty.start.searchDepth",10);
+
+ private final ConfigSources sources;
+ private final Path homeDir;
+ private final Path baseDir;
+
+ public BaseHome() throws IOException
{
- try
+ this(new String[0]);
+ }
+
+ public BaseHome(String cmdLine[]) throws IOException
+ {
+ this(new CommandLineConfigSource(cmdLine));
+ }
+
+ public BaseHome(CommandLineConfigSource cmdLineSource) throws IOException
+ {
+ StartLog.getInstance().initialize(this,cmdLineSource);
+
+ sources = new ConfigSources();
+ sources.add(cmdLineSource);
+ this.homeDir = cmdLineSource.getHomePath();
+ this.baseDir = cmdLineSource.getBasePath();
+ sources.add(new JettyBaseConfigSource(cmdLineSource.getBasePath()));
+ sources.add(new JettyHomeConfigSource(cmdLineSource.getHomePath()));
+
+ System.setProperty(JETTY_HOME,homeDir.toAbsolutePath().toString());
+ System.setProperty(JETTY_BASE,baseDir.toAbsolutePath().toString());
+ }
+
+ public BaseHome(ConfigSources sources)
+ {
+ this.sources = sources;
+ Path home = null;
+ Path base = null;
+ for (ConfigSource source : sources)
{
- this.homeDir = homeDir.getCanonicalFile();
- this.baseDir = baseDir == null?this.homeDir:baseDir.getCanonicalFile();
+ if (source instanceof CommandLineConfigSource)
+ {
+ CommandLineConfigSource cmdline = (CommandLineConfigSource)source;
+ home = cmdline.getHomePath();
+ base = cmdline.getBasePath();
+ }
+ else if (source instanceof JettyBaseConfigSource)
+ {
+ base = ((JettyBaseConfigSource)source).getDir();
+ }
+ else if (source instanceof JettyHomeConfigSource)
+ {
+ home = ((JettyHomeConfigSource)source).getDir();
+ }
}
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
+
+ Objects.requireNonNull(home,"jetty.home cannot be null");
+ this.homeDir = home;
+ this.baseDir = (base != null)?base:home;
+
+ System.setProperty(JETTY_HOME,homeDir.toAbsolutePath().toString());
+ System.setProperty(JETTY_BASE,baseDir.toAbsolutePath().toString());
}
public String getBase()
@@ -92,120 +180,227 @@
{
return null;
}
- return baseDir.getAbsolutePath();
+ return baseDir.toString();
}
- public File getBaseDir()
+ public Path getBasePath()
{
return baseDir;
}
/**
- * Create a file reference to some content in <code>"${jetty.base}"</code>
+ * Create a {@link Path} reference to some content in <code>"${jetty.base}"</code>
*
* @param path
* the path to reference
* @return the file reference
*/
- public File getBaseFile(String path)
+ public Path getBasePath(String path)
{
- return new File(baseDir,FS.separators(path));
+ return baseDir.resolve(path);
}
- /**
- * Get a specific file reference.
- * <p>
- * File references go through 3 possibly scenarios.
- * <ol>
- * <li>If exists relative to <code>${jetty.base}</code>, return that reference</li>
- * <li>If exists relative to <code>${jetty.home}</code>, return that reference</li>
- * <li>Otherwise return absolute path reference</li>
- * </ol>
- *
- * @param path
- * the path to get.
- * @return the file reference.
- */
- public File getFile(String path)
+ public ConfigSources getConfigSources()
{
- String rpath = FS.separators(path);
-
- // Relative to Base Directory First
- if (isBaseDifferent())
- {
- File file = new File(baseDir,rpath);
- if (file.exists())
- {
- return file;
- }
- }
-
- // Then relative to Home Directory
- File file = new File(homeDir,rpath);
- if (file.exists())
- {
- return file;
- }
-
- // Finally, as an absolute path
- return new File(rpath);
+ return this.sources;
}
public String getHome()
{
- return homeDir.getAbsolutePath();
+ return homeDir.toString();
}
- public File getHomeDir()
+ public Path getHomePath()
{
return homeDir;
}
- public void initialize(StartArgs args)
+ /**
+ * Get a specific path reference.
+ * <p>
+ * Path references are searched based on the config source search order.
+ * <ol>
+ * <li>If provided path is an absolute reference., and exists, return that reference</li>
+ * <li>If exists relative to <code>${jetty.base}</code>, return that reference</li>
+ * <li>If exists relative to and <code>extra-start-dir</code> locations, return that reference</li>
+ * <li>If exists relative to <code>${jetty.home}</code>, return that reference</li>
+ * <li>Return standard {@link Path} reference obtained from {@link java.nio.file.FileSystem#getPath(String, String...)} (no exists check performed)</li>
+ * </ol>
+ *
+ * @param path
+ * the path to get.
+ * @return the path reference.
+ */
+ public Path getPath(final String path)
{
- Pattern jetty_home = Pattern.compile("(-D)?jetty.home=(.*)");
- Pattern jetty_base = Pattern.compile("(-D)?jetty.base=(.*)");
+ Path apath = FS.toPath(path);
- File homePath = null;
- File basePath = null;
-
- for (String arg : args.getCommandLine())
+ if (apath.isAbsolute())
{
- Matcher home_match = jetty_home.matcher(arg);
- if (home_match.matches())
+ if (FS.exists(apath))
{
- homePath = new File(home_match.group(2));
- }
- Matcher base_match = jetty_base.matcher(arg);
- if (base_match.matches())
- {
- basePath = new File(base_match.group(2));
+ return apath;
}
}
- if (homePath != null)
+ for (ConfigSource source : sources)
{
- // logic if home is specified
- this.homeDir = homePath.getAbsoluteFile();
- if (basePath == null)
+ if (source instanceof DirConfigSource)
{
- this.baseDir = homePath.getAbsoluteFile();
- args.getProperties().setProperty("jetty.base",this.baseDir.toString(),"<internal-fallback>");
+ DirConfigSource dirsource = (DirConfigSource)source;
+ Path file = dirsource.getDir().resolve(apath);
+ if (FS.exists(file))
+ {
+ return file;
+ }
}
- else
- {
- this.baseDir = basePath.getAbsoluteFile();
- }
- }
- else if (basePath != null)
- {
- // logic if home is undeclared
- this.baseDir = basePath.getAbsoluteFile();
}
- // Update System Properties
- args.addSystemProperty("jetty.home",this.homeDir.getAbsolutePath());
- args.addSystemProperty("jetty.base",this.baseDir.getAbsolutePath());
+ // Finally, as an anonymous path
+ return FS.toPath(path);
+ }
+
+ /**
+ * Search specified Path with pattern and return hits
+ *
+ * @param dir
+ * the path to a directory to start search from
+ * @param searchDepth
+ * the number of directories deep to perform the search
+ * @param pattern
+ * the raw pattern to use for the search (must be relative)
+ * @return the list of Paths found
+ * @throws IOException
+ * if unable to search the path
+ */
+ public List<Path> getPaths(Path dir, int searchDepth, String pattern) throws IOException
+ {
+ if (PathMatchers.isAbsolute(pattern))
+ {
+ throw new RuntimeException("Pattern cannot be absolute: " + pattern);
+ }
+
+ List<Path> hits = new ArrayList<>();
+ if (FS.isValidDirectory(dir))
+ {
+ PathMatcher matcher = PathMatchers.getMatcher(pattern);
+ PathFinder finder = new PathFinder();
+ finder.setFileMatcher(matcher);
+ finder.setBase(dir);
+ Files.walkFileTree(dir,SEARCH_VISIT_OPTIONS,searchDepth,finder);
+ hits.addAll(finder.getHits());
+ Collections.sort(hits,new NaturalSort.Paths());
+ }
+ return hits;
+ }
+
+ /**
+ * Get a List of {@link Path}s from a provided pattern.
+ * <p>
+ * Resolution Steps:
+ * <ol>
+ * <li>If the pattern starts with "regex:" or "glob:" then a standard {@link PathMatcher} is built using
+ * {@link java.nio.file.FileSystem#getPathMatcher(String)} as a file search.</li>
+ * <li>If pattern starts with a known filesystem root (using information from {@link java.nio.file.FileSystem#getRootDirectories()}) then this is assumed to
+ * be a absolute file system pattern.</li>
+ * <li>All other patterns are treated as relative to BaseHome information:
+ * <ol>
+ * <li>Search ${jetty.home} first</li>
+ * <li>Search ${jetty.base} for overrides</li>
+ * </ol>
+ * </li>
+ * </ol>
+ * <p>
+ * Pattern examples:
+ * <dl>
+ * <dt><code>lib/logging/*.jar</code></dt>
+ * <dd>Relative pattern, not recursive, search <code>${jetty.home}</code> then <code>${jetty.base}</code> for lib/logging/*.jar content</dd>
+ *
+ * <dt><code>lib/**/*-dev.jar</code></dt>
+ * <dd>Relative pattern, recursive search <code>${jetty.home}</code> then <code>${jetty.base}</code> for files under <code>lib</code> ending in
+ * <code>-dev.jar</code></dd>
+ * </dl>
+ *
+ * <dt><code>etc/jetty.xml</code></dt>
+ * <dd>Relative pattern, no glob, search for <code>${jetty.home}/etc/jetty.xml</code> then <code>${jetty.base}/etc/jetty.xml</code></dd>
+ *
+ * <dt><code>glob:/opt/app/common/*-corp.jar</code></dt>
+ * <dd>PathMapper pattern, glob, search <code>/opt/app/common/</code> for <code>*-corp.jar</code></code></dd>
+ *
+ * </dl>
+ *
+ * <p>
+ * Notes:
+ * <ul>
+ * <li>FileSystem case sensitivity is implementation specific (eg: linux is case-sensitive, windows is case-insensitive).<br/>
+ * See {@link java.nio.file.FileSystem#getPathMatcher(String)} for more details</li>
+ * <li>Pattern slashes are implementation neutral (use '/' always and you'll be fine)</li>
+ * <li>Recursive searching is limited to 30 levels deep (not configurable)</li>
+ * <li>File System loops are detected and skipped</li>
+ * </ul>
+ *
+ * @param pattern
+ * the pattern to search.
+ * @return the collection of paths found
+ * @throws IOException
+ * if error during search operation
+ */
+ public List<Path> getPaths(String pattern) throws IOException
+ {
+ StartLog.debug("getPaths('%s')",pattern);
+ List<Path> hits = new ArrayList<>();
+
+ if (PathMatchers.isAbsolute(pattern))
+ {
+ // Perform absolute path pattern search
+
+ // The root to start search from
+ Path root = PathMatchers.getSearchRoot(pattern);
+ // The matcher for file hits
+ PathMatcher matcher = PathMatchers.getMatcher(pattern);
+
+ if (FS.isValidDirectory(root))
+ {
+ PathFinder finder = new PathFinder();
+ finder.setIncludeDirsInResults(true);
+ finder.setFileMatcher(matcher);
+ finder.setBase(root);
+ Files.walkFileTree(root,SEARCH_VISIT_OPTIONS,MAX_SEARCH_DEPTH,finder);
+ hits.addAll(finder.getHits());
+ }
+ }
+ else
+ {
+ // Perform relative path pattern search
+ Path relativePath = PathMatchers.getSearchRoot(pattern);
+ PathMatcher matcher = PathMatchers.getMatcher(pattern);
+ PathFinder finder = new PathFinder();
+ finder.setIncludeDirsInResults(true);
+ finder.setFileMatcher(matcher);
+
+ // walk config sources backwards ...
+ ListIterator<ConfigSource> iter = sources.reverseListIterator();
+ while (iter.hasPrevious())
+ {
+ ConfigSource source = iter.previous();
+ if (source instanceof DirConfigSource)
+ {
+ DirConfigSource dirsource = (DirConfigSource)source;
+ Path dir = dirsource.getDir();
+ Path deepDir = dir.resolve(relativePath);
+ if (FS.isValidDirectory(deepDir))
+ {
+ finder.setBase(dir);
+ Files.walkFileTree(deepDir,SEARCH_VISIT_OPTIONS,MAX_SEARCH_DEPTH,finder);
+ }
+ }
+ }
+
+ hits.addAll(finder.getHits());
+ }
+
+ Collections.sort(hits,new NaturalSort.Paths());
+ return hits;
}
public boolean isBaseDifferent()
@@ -214,228 +409,11 @@
}
/**
- * Get all of the files that are in a specific relative directory.
- * <p>
- * If the same found path exists in both <code>${jetty.base}</code> and <code>${jetty.home}</code>, then the one in <code>${jetty.base}</code> is returned
- * (it overrides the one in ${jetty.home})
- *
- * @param relPathToDirectory
- * the relative path to the directory
- * @return the list of files found.
+ * Convenience method for <code>toShortForm(file.toPath())</code>
*/
- public List<File> listFiles(String relPathToDirectory)
+ public String toShortForm(final File path)
{
- return listFiles(relPathToDirectory,FS.AllFilter.INSTANCE);
- }
-
- /**
- * Get all of the files that are in a specific relative directory, with applied {@link FileFilter}
- * <p>
- * If the same found path exists in both <code>${jetty.base}</code> and <code>${jetty.home}</code>, then the one in <code>${jetty.base}</code> is returned
- * (it overrides the one in ${jetty.home})
- *
- * @param relPathToDirectory
- * the relative path to the directory
- * @param filter
- * the filter to use
- * @return the list of files found.
- */
- public List<File> listFiles(String relPathToDirectory, FileFilter filter)
- {
- Objects.requireNonNull(filter,"FileFilter cannot be null");
-
- File homePath = new File(homeDir,FS.separators(relPathToDirectory));
- List<File> homeFiles = new ArrayList<>();
- if (FS.canReadDirectory(homePath))
- {
- homeFiles.addAll(Arrays.asList(homePath.listFiles(filter)));
- }
-
- if (isBaseDifferent())
- {
- // merge
- File basePath = new File(baseDir,FS.separators(relPathToDirectory));
- List<File> ret = new ArrayList<>();
- if (FS.canReadDirectory(basePath))
- {
- File baseFiles[] = basePath.listFiles(filter);
-
- if (baseFiles != null)
- {
- for (File base : baseFiles)
- {
- String relpath = toRelativePath(baseDir,base);
- File home = new File(homeDir,FS.separators(relpath));
- if (home.exists())
- {
- homeFiles.remove(home);
- }
- ret.add(base);
- }
- }
- }
-
- // add any remaining home files.
- ret.addAll(homeFiles);
-
- Collections.sort(ret,new NaturalSort.Files());
- return ret;
- }
- else
- {
- // simple return
- Collections.sort(homeFiles,new NaturalSort.Files());
- return homeFiles;
- }
- }
-
- /**
- * Get all of the files that are in a specific relative directory, with applied regex.
- * <p>
- * If the same found path exists in both <code>${jetty.base}</code> and <code>${jetty.home}</code>, then the one in <code>${jetty.base}</code> is returned
- * (it overrides the one in ${jetty.home})
- * <p>
- * All regex paths are assumed to be in unix notation (use of <code>"/"</code> to separate paths, as <code>"\"</code> is used to escape in regex)
- *
- * @param regex
- * the regex to use to match against the found files.
- * @return the list of files found.
- */
- public List<File> listFilesRegex(String regex)
- {
- Objects.requireNonNull(regex,"Glob cannot be null");
-
- Pattern pattern = Pattern.compile(regex);
-
- List<File> homeFiles = new ArrayList<>();
- if (FS.canReadDirectory(homeDir))
- {
- StartLog.debug("Finding files in ${jetty.home} that match: %s",regex);
- recurseDir(homeFiles,homeDir,new FS.RelativeRegexFilter(homeDir,pattern));
- StartLog.debug("Found %,d files",homeFiles.size());
- }
-
- if (isBaseDifferent())
- {
- // merge
- List<File> ret = new ArrayList<>();
- if (FS.canReadDirectory(baseDir))
- {
- List<File> baseFiles = new ArrayList<>();
- StartLog.debug("Finding files in ${jetty.base} that match: %s",regex);
- recurseDir(baseFiles,baseDir,new FS.RelativeRegexFilter(baseDir,pattern));
- StartLog.debug("Found %,d files",baseFiles.size());
-
- for (File base : baseFiles)
- {
- String relpath = toRelativePath(baseDir,base);
- File home = new File(homeDir,FS.separators(relpath));
- if (home.exists())
- {
- homeFiles.remove(home);
- }
- ret.add(base);
- }
- }
-
- // add any remaining home files.
- ret.addAll(homeFiles);
- StartLog.debug("Merged Files: %,d files%n",ret.size());
-
- Collections.sort(ret,new NaturalSort.Files());
- return ret;
- }
- else
- {
- // simple return
- Collections.sort(homeFiles,new NaturalSort.Files());
- return homeFiles;
- }
- }
-
- private void recurseDir(List<File> files, File dir, RelativeRegexFilter filter)
- {
- // find matches first
- files.addAll(Arrays.asList(dir.listFiles(filter)));
-
- // now dive down into sub-directories
- for (File subdir : dir.listFiles(FS.DirFilter.INSTANCE))
- {
- recurseDir(files,subdir,filter);
- }
- }
-
- /**
- * Collect the list of files in both <code>${jetty.base}</code> and <code>${jetty.home}</code>, even if the same file shows up in both places.
- */
- public List<File> rawListFiles(String relPathToDirectory, FileFilter filter)
- {
- Objects.requireNonNull(filter,"FileFilter cannot be null");
-
- List<File> ret = new ArrayList<>();
-
- // Home Dir
- File homePath = new File(homeDir,FS.separators(relPathToDirectory));
- ret.addAll(Arrays.asList(homePath.listFiles(filter)));
-
- if (isBaseDifferent())
- {
- // Base Dir
- File basePath = new File(baseDir,FS.separators(relPathToDirectory));
- ret.addAll(Arrays.asList(basePath.listFiles(filter)));
- }
-
- // Sort
- Collections.sort(ret,new NaturalSort.Files());
- return ret;
- }
-
- public void setBaseDir(File dir)
- {
- try
- {
- this.baseDir = dir.getCanonicalFile();
- System.setProperty("jetty.base",dir.getCanonicalPath());
- }
- catch (IOException e)
- {
- e.printStackTrace(System.err);
- }
- }
-
- public void setHomeDir(File dir)
- {
- try
- {
- this.homeDir = dir.getCanonicalFile();
- System.setProperty("jetty.home",dir.getCanonicalPath());
- }
- catch (IOException e)
- {
- e.printStackTrace(System.err);
- }
- }
-
- // TODO - inline
- private String toRelativePath(File dir, File path)
- {
- return FS.toRelativePath(dir,path);
- }
-
- /**
- * Convenience method for <code>toShortForm(file.getCanonicalPath())</code>
- */
- public String toShortForm(File path)
- {
- try
- {
- return toShortForm(path.getCanonicalPath());
- }
- catch (IOException ignore)
- {
- /* ignore */
- }
- return toShortForm(path.getAbsolutePath());
+ return toShortForm(path.toPath());
}
/**
@@ -445,32 +423,48 @@
* the path to shorten
* @return the potentially shortened path
*/
- public String toShortForm(String path)
+ public String toShortForm(final Path path)
+ {
+ Path apath = path.toAbsolutePath();
+
+ for (ConfigSource source : sources)
+ {
+ if (source instanceof DirConfigSource)
+ {
+ DirConfigSource dirsource = (DirConfigSource)source;
+ Path dir = dirsource.getDir();
+ if (apath.startsWith(dir))
+ {
+ if (dirsource.isPropertyBased())
+ {
+ Path relative = dir.relativize(apath);
+ return String.format("%s%c%s",dirsource.getId(),File.separatorChar,relative.toString());
+ }
+ else
+ {
+ return apath.toString();
+ }
+ }
+ }
+ }
+
+ return apath.toString();
+ }
+
+ /**
+ * Replace/Shorten arbitrary path with property strings <code>"${jetty.home}"</code> or <code>"${jetty.base}"</code> where appropriate.
+ *
+ * @param path
+ * the path to shorten
+ * @return the potentially shortened path
+ */
+ public String toShortForm(final String path)
{
if (path == null)
{
return path;
}
- String value;
-
- if (isBaseDifferent())
- {
- value = baseDir.getAbsolutePath();
- if (path.startsWith(value))
- {
- return "${jetty.base}" + path.substring(value.length());
- }
- }
-
- value = homeDir.getAbsolutePath();
-
- if (path.startsWith(value))
- {
- return "${jetty.home}" + path.substring(value.length());
- }
-
- return path;
+ return toShortForm(FS.toPath(path));
}
-
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/CommandLineBuilder.java b/jetty-start/src/main/java/org/eclipse/jetty/start/CommandLineBuilder.java
index ccf127e..8f4fd8c 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/CommandLineBuilder.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/CommandLineBuilder.java
@@ -192,4 +192,19 @@
return buf.toString();
}
+
+ public void debug()
+ {
+ if (!StartLog.isDebugEnabled())
+ {
+ return;
+ }
+
+ int len = args.size();
+ StartLog.debug("Command Line: %,d entries",args.size());
+ for (int i = 0; i < len; i++)
+ {
+ StartLog.debug(" [%d]: \"%s\"",i,args.get(i));
+ }
+ }
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java b/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java
index 5fd41b9..9b55b45 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java
@@ -20,124 +20,28 @@
import java.io.Closeable;
import java.io.File;
-import java.io.FileFilter;
import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileTime;
import java.util.Locale;
-import java.util.regex.Pattern;
public class FS
{
- public static class AllFilter implements FileFilter
+ public static boolean canReadDirectory(Path path)
{
- public static final AllFilter INSTANCE = new AllFilter();
-
- @Override
- public boolean accept(File pathname)
- {
- return true;
- }
- }
-
- public static class DirFilter implements FileFilter
- {
- public static final DirFilter INSTANCE = new DirFilter();
-
- @Override
- public boolean accept(File path)
- {
- return path.isDirectory();
- }
- }
-
- public static class RelativeRegexFilter implements FileFilter
- {
- private final File baseDir;
- private final Pattern pattern;
-
- public RelativeRegexFilter(File baseDir, Pattern pattern)
- {
- this.baseDir = baseDir;
- this.pattern = pattern;
- }
-
- @Override
- public boolean accept(File path)
- {
- // get relative path
- String relativePath = FS.toRelativePath(baseDir,path);
-
- // see if it matches
- return (pattern.matcher(relativePath).matches());
- }
+ return Files.exists(path) && Files.isDirectory(path) && Files.isReadable(path);
}
- public static class FilenameRegexFilter implements FileFilter
+ public static boolean canReadFile(Path path)
{
- private final Pattern pattern;
-
- public FilenameRegexFilter(String regex)
- {
- pattern = Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
- }
-
- @Override
- public boolean accept(File path)
- {
- return path.isFile() && pattern.matcher(path.getName()).matches();
- }
+ return Files.exists(path) && Files.isRegularFile(path) && Files.isReadable(path);
}
- public static class FileNamesFilter implements FileFilter
+ public static boolean canWrite(Path path)
{
- private final String filenames[];
-
- public FileNamesFilter(String... names)
- {
- this.filenames = names;
- }
-
- @Override
- public boolean accept(File path)
- {
- if (!path.isFile())
- {
- return false;
- }
- for (String name : filenames)
- {
- if (name.equalsIgnoreCase(path.getName()))
- {
- return true;
- }
- }
- return false;
- }
- }
-
- public static class IniFilter extends FilenameRegexFilter
- {
- public IniFilter()
- {
- super("^.*\\.ini$");
- }
- }
-
- public static class XmlFilter extends FilenameRegexFilter
- {
- public XmlFilter()
- {
- super("^.*\\.xml$");
- }
- }
-
- public static boolean canReadDirectory(File path)
- {
- return (path.exists() && path.isDirectory() && path.canRead());
- }
-
- public static boolean canReadFile(File path)
- {
- return (path.exists() && path.isFile() && path.canRead());
+ return Files.isWritable(path);
}
public static void close(Closeable c)
@@ -157,48 +61,65 @@
}
}
- public static void ensureDirectoryExists(File dir) throws IOException
+ public static boolean createNewFile(Path path) throws IOException
{
- if (dir.exists())
+ Path ret = Files.createFile(path);
+ return Files.exists(ret);
+ }
+
+ public static void ensureDirectoryExists(Path dir) throws IOException
+ {
+ if (exists(dir))
{
+ // exists already, nothing to do
return;
}
- if (!dir.mkdirs())
- {
- throw new IOException("Unable to create directory: " + dir.getAbsolutePath());
- }
+ Files.createDirectories(dir);
}
-
- public static void ensureDirectoryWritable(File dir) throws IOException
+
+ public static void ensureDirectoryWritable(Path dir) throws IOException
{
- if (!dir.exists())
+ if (!Files.exists(dir))
{
- throw new IOException("Directory does not exist: " + dir.getAbsolutePath());
+ throw new IOException("Path does not exist: " + dir.toAbsolutePath());
}
- if (!dir.canWrite())
+ if (!Files.isDirectory(dir))
{
- throw new IOException("Unable to write to directory: " + dir.getAbsolutePath());
+ throw new IOException("Directory does not exist: " + dir.toAbsolutePath());
+ }
+ if (!Files.isWritable(dir))
+ {
+ throw new IOException("Unable to write to directory: " + dir.toAbsolutePath());
}
}
- public static boolean isFile(File file)
+ public static boolean exists(Path path)
{
- if (file == null)
+ return Files.exists(path);
+ }
+
+ public static boolean isValidDirectory(Path path)
+ {
+ if (!Files.exists(path))
{
+ // doesn't exist, not a valid directory
return false;
}
- return file.exists() && file.isFile();
+
+ if (!Files.isDirectory(path))
+ {
+ // not a directory (as expected)
+ StartLog.warn("Not a directory: " + path);
+ return false;
+ }
+
+ return true;
}
public static boolean isXml(String filename)
{
return filename.toLowerCase(Locale.ENGLISH).endsWith(".xml");
}
-
- public static String toRelativePath(File baseDir, File path)
- {
- return baseDir.toURI().relativize(path.toURI()).toASCIIString();
- }
public static String separators(String path)
{
@@ -216,4 +137,20 @@
}
return ret.toString();
}
+
+ public static Path toPath(String path)
+ {
+ return FileSystems.getDefault().getPath(FS.separators(path));
+ }
+
+ public static void touch(Path path) throws IOException
+ {
+ FileTime now = FileTime.fromMillis(System.currentTimeMillis());
+ Files.setLastModifiedTime(path,now);
+ }
+
+ public static Path toRealPath(Path path) throws IOException
+ {
+ return path.toRealPath();
+ }
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
index c196aff..9e46100 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
@@ -18,14 +18,11 @@
package org.eclipse.jetty.start;
-import static org.eclipse.jetty.start.UsageException.ERR_INVOKE_MAIN;
-import static org.eclipse.jetty.start.UsageException.ERR_NOT_STOPPED;
-import static org.eclipse.jetty.start.UsageException.ERR_UNKNOWN;
+import static org.eclipse.jetty.start.UsageException.*;
import java.io.BufferedReader;
+import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -39,14 +36,22 @@
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.eclipse.jetty.start.config.CommandLineConfigSource;
+
/**
* Main start class.
* <p>
@@ -130,11 +135,10 @@
System.exit(exit);
}
- private final BaseHome baseHome;
+ private BaseHome baseHome;
Main() throws IOException
{
- baseHome = new BaseHome();
}
private void copyInThread(final InputStream in, final OutputStream out)
@@ -167,11 +171,12 @@
{
try
{
- File file = baseHome.getBaseFile(arg.location);
+ Path file = baseHome.getBasePath(arg.location);
- StartLog.debug("Module file %s %s",file.getAbsolutePath(),(file.exists()?"[Exists!]":""));
- if (file.exists())
+ StartLog.debug("Module file %s %s",file.toAbsolutePath(),(FS.exists(file)?"[Exists!]":""));
+ if (FS.exists(file))
{
+ // file already initialized / downloaded, skip it
return;
}
@@ -181,10 +186,11 @@
System.err.println("DOWNLOAD: " + url + " to " + arg.location);
- FS.ensureDirectoryExists(file.getParentFile());
+ FS.ensureDirectoryExists(file.getParent());
byte[] buf = new byte[8192];
- try (InputStream in = url.openStream(); OutputStream out = new FileOutputStream(file);)
+ try (InputStream in = url.openStream();
+ OutputStream out = Files.newOutputStream(file,StandardOpenOption.CREATE_NEW,StandardOpenOption.WRITE))
{
while (true)
{
@@ -204,11 +210,12 @@
else if (arg.location.endsWith("/"))
{
System.err.println("MKDIR: " + baseHome.toShortForm(file));
- file.mkdirs();
+ FS.ensureDirectoryExists(file);
}
else
+ {
StartLog.warn("MISSING: required file "+ baseHome.toShortForm(file));
-
+ }
}
catch (Exception e)
{
@@ -300,7 +307,7 @@
public void listConfig(StartArgs args)
{
// Dump Jetty Home / Base
- args.dumpEnvironment();
+ args.dumpEnvironment(baseHome);
// Dump JVM Args
args.dumpJvmArgs();
@@ -333,10 +340,23 @@
modules.dumpEnabledTree();
}
- private void moduleIni(StartArgs args, String name, boolean topLevel, boolean appendStartIni) throws IOException
- {
+ /**
+ * Build out INI file.
+ * <p>
+ * This applies equally for either <code>${jetty.base}/start.ini</code> or
+ * <code>${jetty.base}/start.d/${name}.ini</code>
+ *
+ * @param args the arguments of what modules are enabled
+ * @param name the name of the module to based the build of the ini
+ * @param topLevel
+ * @param appendStartIni true to append to <code>${jetty.base}/start.ini</code>,
+ * false to create a <code>${jetty.base}/start.d/${name}.ini</code> entry instead.
+ * @throws IOException
+ */
+ private void buildIni(StartArgs args, String name, boolean topLevel, boolean appendStartIni) throws IOException
+ {
// Find the start.d relative to the base directory only.
- File start_d = baseHome.getBaseFile("start.d");
+ Path start_d = baseHome.getBasePath("start.d");
// Is this a module?
Modules modules = args.getAllModules();
@@ -348,12 +368,12 @@
}
// Find any named ini file and check it follows the convention
- File start_ini = baseHome.getBaseFile("start.ini");
+ Path start_ini = baseHome.getBasePath("start.ini");
String short_start_ini = baseHome.toShortForm(start_ini);
- File ini = new File(start_d,name + ".ini");
+ Path ini = start_d.resolve(name + ".ini");
String short_ini = baseHome.toShortForm(ini);
StartIni module_ini = null;
- if (ini.exists())
+ if (FS.exists(ini))
{
module_ini = new StartIni(ini);
if (module_ini.getLineMatches(Pattern.compile("--module=(.*, *)*" + name)).size() == 0)
@@ -367,46 +387,30 @@
boolean has_ini_lines = module.getInitialise().size() > 0;
// If it is not enabled or is transitive with ini template lines or toplevel and doesn't exist
- if (!module.isEnabled() || (transitive && has_ini_lines) || (topLevel && !ini.exists() && !appendStartIni))
+ if (!module.isEnabled() || (transitive && has_ini_lines) || (topLevel && !FS.exists(ini) && !appendStartIni))
{
+ // File BufferedWriter
+ BufferedWriter writer = null;
String source = null;
PrintWriter out = null;
try
{
if (appendStartIni)
{
- if ((!start_ini.exists() && !start_ini.createNewFile()) || !start_ini.canWrite())
- {
- StartLog.warn("ERROR: Bad %s! ",start_ini);
- return;
- }
source = short_start_ini;
StartLog.info("%-15s initialised in %s (appended)",name,source);
- out = new PrintWriter(new FileWriter(start_ini,true));
+ writer = Files.newBufferedWriter(start_ini,StandardCharsets.UTF_8,StandardOpenOption.CREATE,StandardOpenOption.APPEND);
+ out = new PrintWriter(writer);
}
else
{
// Create the directory if needed
FS.ensureDirectoryExists(start_d);
FS.ensureDirectoryWritable(start_d);
- try
- {
- // Create a new ini file for it
- if (!ini.createNewFile())
- {
- StartLog.warn("ERROR: %s cannot be initialised in %s! ",name,short_ini);
- return;
- }
- }
- catch (IOException e)
- {
- StartLog.warn("ERROR: Unable to create %s!",ini);
- StartLog.warn(e);
- return;
- }
source = short_ini;
StartLog.info("%-15s initialised in %s (created)",name,source);
- out = new PrintWriter(ini);
+ writer = Files.newBufferedWriter(ini,StandardCharsets.UTF_8,StandardOpenOption.CREATE_NEW,StandardOpenOption.WRITE);
+ out = new PrintWriter(writer);
}
if (appendStartIni)
@@ -454,11 +458,15 @@
}
}
}
- else if (ini.exists())
+ else if (FS.exists(ini))
{
StartLog.info("%-15s initialised in %s",name,short_ini);
}
-
+ else
+ {
+ StartLog.info("%-15s initialised transitively",name);
+ }
+
// Also list other places this module is enabled
for (String source : module.getSources())
{
@@ -474,23 +482,57 @@
initFile(new FileArg(file));
}
- // Process dependencies from top level only
+ // Process dependencies
+ module.expandProperties(args.getProperties());
+ modules.registerParentsIfMissing(baseHome,args,module);
+ modules.buildGraph();
+
+
+ // process new ini modules
if (topLevel)
{
- List<Module> parents = new ArrayList<>();
- for (String parent : modules.resolveParentModulesOf(name))
+ List<Module> depends = new ArrayList<>();
+ for (String depend : modules.resolveParentModulesOf(name))
{
- if (!name.equals(parent))
+ if (!name.equals(depend))
{
- Module m = modules.get(parent);
+ Module m = modules.get(depend);
m.setEnabled(true);
- parents.add(m);
+ depends.add(m);
}
}
- Collections.sort(parents,Collections.reverseOrder(new Module.DepthComparator()));
- for (Module m : parents)
+ Collections.sort(depends,Collections.reverseOrder(new Module.DepthComparator()));
+
+ Set<String> done = new HashSet<>(0);
+ while (true)
{
- moduleIni(args,m.getName(),false,appendStartIni);
+ // initialize known dependencies
+ boolean complete=true;
+ for (Module m : depends)
+ {
+ if (!done.contains(m.getName()))
+ {
+ complete=false;
+ buildIni(args,m.getName(),false,appendStartIni);
+ done.add(m.getName());
+ }
+ }
+
+ if (complete)
+ break;
+
+ // look for any new ones resolved via expansion
+ depends.clear();
+ for (String depend : modules.resolveParentModulesOf(name))
+ {
+ if (!name.equals(depend))
+ {
+ Module m = modules.get(depend);
+ m.setEnabled(true);
+ depends.add(m);
+ }
+ }
+ Collections.sort(depends,Collections.reverseOrder(new Module.DepthComparator()));
}
}
}
@@ -505,66 +547,36 @@
public StartArgs processCommandLine(String[] cmdLine) throws Exception
{
- StartArgs args = new StartArgs(cmdLine);
-
// Processing Order is important!
// ------------------------------------------------------------
- // 1) Directory Locations
-
- // Set Home and Base at the start, as all other paths encountered
- // will be based off of them.
- baseHome.initialize(args);
-
- // ------------------------------------------------------------
- // 2) Start Logging
- StartLog.getInstance().initialize(baseHome,args);
+ // 1) Configuration Locations
+ CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
+ baseHome = new BaseHome(cmdLineSource);
StartLog.debug("jetty.home=%s",baseHome.getHome());
StartLog.debug("jetty.base=%s",baseHome.getBase());
// ------------------------------------------------------------
- // 3) Load Inis
- File start_ini = baseHome.getBaseFile("start.ini");
- if (FS.canReadFile(start_ini))
- {
- StartLog.debug("Reading ${jetty.base}/start.ini - %s",start_ini);
- args.parse(baseHome,new StartIni(start_ini));
- }
-
- File start_d = baseHome.getBaseFile("start.d");
- if (FS.canReadDirectory(start_d))
- {
- List<File> files = new ArrayList<>();
- for (File file : start_d.listFiles(new FS.IniFilter()))
- {
- files.add(file);
- }
-
- Collections.sort(files,new NaturalSort.Files());
- for (File file : files)
- {
- StartLog.debug("Reading ${jetty.base}/start.d/%s - %s",file.getName(),file);
- args.parse(baseHome,new StartIni(file));
- }
- }
-
- // 4) Parse everything provided.
+ // 2) Parse everything provided.
// This would be the directory information +
// the various start inis
// and then the raw command line arguments
StartLog.debug("Parsing collected arguments");
- args.parseCommandLine();
+ StartArgs args = new StartArgs();
+ args.parse(baseHome.getConfigSources());
- // 5) Module Registration
+ // ------------------------------------------------------------
+ // 3) Module Registration
Modules modules = new Modules();
StartLog.debug("Registering all modules");
modules.registerAll(baseHome, args);
- // 6) Active Module Resolution
+ // ------------------------------------------------------------
+ // 4) Active Module Resolution
for (String enabledModule : args.getEnabledModules())
{
- List<String> sources = args.getSources(enabledModule);
- modules.enable(enabledModule,sources);
+ List<String> msources = args.getSources(enabledModule);
+ modules.enable(enabledModule,msources);
}
StartLog.debug("Building Module Graph");
@@ -573,10 +585,13 @@
args.setAllModules(modules);
List<Module> activeModules = modules.resolveEnabled();
- // 7) Lib & XML Expansion / Resolution
+ // ------------------------------------------------------------
+ // 5) Lib & XML Expansion / Resolution
+ args.expandLibs(baseHome);
args.expandModules(baseHome,activeModules);
- // 8) Resolve Extra XMLs
+ // ------------------------------------------------------------
+ // 6) Resolve Extra XMLs
args.resolveExtraXmls(baseHome);
return args;
@@ -618,7 +633,7 @@
// Generate Module Graph File
if (args.getModuleGraphFilename() != null)
{
- File outputFile = baseHome.getBaseFile(args.getModuleGraphFilename());
+ Path outputFile = baseHome.getBasePath(args.getModuleGraphFilename());
System.out.printf("Generating GraphViz Graph of Jetty Modules at %s%n",baseHome.toShortForm(outputFile));
ModuleGraphWriter writer = new ModuleGraphWriter();
writer.config(args.getProperties());
@@ -649,26 +664,28 @@
}
}
- // Initialize
- for (String module : args.getModuleStartIni())
+ // Initialize start.ini
+ for (String module : args.getAddToStartIni())
{
- moduleIni(args,module,true,true);
+ buildIni(args,module,true,true);
}
- // Initialize
- for (String module : args.getModuleStartdIni())
+ // Initialize start.d
+ for (String module : args.getAddToStartdIni())
{
- moduleIni(args,module,true,false);
+ buildIni(args,module,true,false);
}
// Check ini files for download possibilities
for (FileArg arg : args.getFiles())
{
- File file = baseHome.getBaseFile(arg.location);
- if (!file.exists() && args.isDownload())
+ Path file = baseHome.getBasePath(arg.location);
+ if (!FS.exists(file) && args.isDownload())
+ {
initFile(arg);
+ }
- if (!file.exists())
+ if (!FS.exists(file))
{
/* Startup should NEVER fail to run on missing content.
* See Bug #427204
@@ -692,6 +709,7 @@
if (args.isExec())
{
CommandLineBuilder cmd = args.getMainArgs(baseHome,true);
+ cmd.debug();
ProcessBuilder pbuilder = new ProcessBuilder(cmd.getArgs());
final Process process = pbuilder.start();
Runtime.getRuntime().addShutdownHook(new Thread()
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java
index 892f11a..2df1b05 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java
@@ -19,10 +19,11 @@
package org.eclipse.jetty.start;
import java.io.BufferedReader;
-import java.io.File;
import java.io.FileNotFoundException;
-import java.io.FileReader;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.text.CollationKey;
import java.text.Collator;
import java.util.ArrayList;
@@ -75,7 +76,7 @@
}
/** The file of the module */
- private File file;
+ private Path file;
/** The name of this Module (as a filesystem reference) */
private String fileRef;
/**
@@ -100,18 +101,20 @@
private List<String> libs;
/** List of files for this Module */
private List<String> files;
+ /** List of jvm Args */
+ private List<String> jvmArgs;
/** Is this Module enabled via start.jar command line, start.ini, or start.d/*.ini ? */
private boolean enabled = false;
/** List of sources that enabled this module */
private final Set<String> sources = new HashSet<>();
- public Module(BaseHome basehome, File file) throws FileNotFoundException, IOException
+ public Module(BaseHome basehome, Path file) throws FileNotFoundException, IOException
{
this.file = file;
// Strip .mod
- this.fileRef = Pattern.compile(".mod$",Pattern.CASE_INSENSITIVE).matcher(file.getName()).replaceFirst("");
+ this.fileRef = Pattern.compile(".mod$",Pattern.CASE_INSENSITIVE).matcher(file.getFileName().toString()).replaceFirst("");
this.logicalName = fileRef;
init(basehome);
@@ -250,6 +253,11 @@
return xmls;
}
+ public List<String> getJvmArgs()
+ {
+ return jvmArgs;
+ }
+
@Override
public int hashCode()
{
@@ -261,6 +269,16 @@
private void init(BaseHome basehome)
{
+ parentNames = new HashSet<>();
+ optionalParentNames = new HashSet<>();
+ parentEdges = new HashSet<>();
+ childEdges = new HashSet<>();
+ xmls = new ArrayList<>();
+ initialise = new ArrayList<>();
+ libs = new ArrayList<>();
+ files = new ArrayList<>();
+ jvmArgs = new ArrayList<>();
+
String name = basehome.toShortForm(file);
// Find module system name (usually in the form of a filesystem reference)
@@ -272,15 +290,6 @@
}
this.fileRef = mat.group(1).replace('\\','/');
this.logicalName = this.fileRef;
-
- parentNames = new HashSet<>();
- optionalParentNames = new HashSet<>();
- parentEdges = new HashSet<>();
- childEdges = new HashSet<>();
- xmls = new ArrayList<>();
- initialise = new ArrayList<>();
- libs = new ArrayList<>();
- files = new ArrayList<>();
}
public boolean isEnabled()
@@ -298,63 +307,63 @@
return;
}
- try (FileReader reader = new FileReader(file))
+ try (BufferedReader buf = Files.newBufferedReader(file,StandardCharsets.UTF_8))
{
- try (BufferedReader buf = new BufferedReader(reader))
+ String sectionType = "";
+ String line;
+ while ((line = buf.readLine()) != null)
{
- String sectionType = "";
- String line;
- while ((line = buf.readLine()) != null)
+ line = line.trim();
+
+ Matcher sectionMatcher = section.matcher(line);
+
+ if (sectionMatcher.matches())
{
- line = line.trim();
-
- Matcher sectionMatcher = section.matcher(line);
-
- if (sectionMatcher.matches())
+ sectionType = sectionMatcher.group(1).trim().toUpperCase(Locale.ENGLISH);
+ }
+ else
+ {
+ // blank lines and comments are valid for ini-template section
+ if ((line.length() == 0) || line.startsWith("#"))
{
- sectionType = sectionMatcher.group(1).trim().toUpperCase(Locale.ENGLISH);
+ if ("INI-TEMPLATE".equals(sectionType))
+ {
+ initialise.add(line);
+ }
}
else
{
- // blank lines and comments are valid for ini-template section
- if ((line.length() == 0) || line.startsWith("#"))
+ switch (sectionType)
{
- if ("INI-TEMPLATE".equals(sectionType))
- {
+ case "":
+ // ignore (this would be entries before first section)
+ break;
+ case "DEPEND":
+ parentNames.add(line);
+ break;
+ case "FILES":
+ files.add(line);
+ break;
+ case "INI-TEMPLATE":
initialise.add(line);
- }
- }
- else
- {
- switch (sectionType)
- {
- case "":
- // ignore (this would be entries before first section)
- break;
- case "NAME":
- logicalName = line;
- break;
- case "DEPEND":
- parentNames.add(line);
- break;
- case "LIB":
- libs.add(line);
- break;
- case "XML":
- xmls.add(line);
- break;
- case "OPTIONAL":
- optionalParentNames.add(line);
- break;
- case "FILES":
- files.add(line);
- break;
- case "INI-TEMPLATE":
- initialise.add(line);
- break;
- default:
- throw new IOException("Unrecognized Module section: [" + sectionType + "]");
- }
+ break;
+ case "LIB":
+ libs.add(line);
+ break;
+ case "NAME":
+ logicalName = line;
+ break;
+ case "OPTIONAL":
+ optionalParentNames.add(line);
+ break;
+ case "EXEC":
+ jvmArgs.add(line);
+ break;
+ case "XML":
+ xmls.add(line);
+ break;
+ default:
+ throw new IOException("Unrecognized Module section: [" + sectionType + "]");
}
}
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/ModuleGraphWriter.java b/jetty-start/src/main/java/org/eclipse/jetty/start/ModuleGraphWriter.java
index b078f51..7c612a7 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/ModuleGraphWriter.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/ModuleGraphWriter.java
@@ -18,10 +18,13 @@
package org.eclipse.jetty.start;
-import java.io.File;
-import java.io.FileWriter;
+import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
import java.util.Collection;
import java.util.List;
@@ -73,9 +76,10 @@
return val;
}
- public void write(Modules modules, File outputFile) throws IOException
+ public void write(Modules modules, Path outputFile) throws IOException
{
- try (FileWriter writer = new FileWriter(outputFile,false); PrintWriter out = new PrintWriter(writer);)
+ try (BufferedWriter writer = Files.newBufferedWriter(outputFile,StandardCharsets.UTF_8,StandardOpenOption.CREATE_NEW,StandardOpenOption.WRITE);
+ PrintWriter out = new PrintWriter(writer);)
{
writeHeaderMessage(out,outputFile);
@@ -112,7 +116,7 @@
}
}
- private void writeHeaderMessage(PrintWriter out, File outputFile)
+ private void writeHeaderMessage(PrintWriter out, Path outputFile)
{
out.println("/*");
out.println(" * GraphViz Graph of Jetty Modules");
@@ -121,7 +125,7 @@
out.println(" * GraphViz: http://graphviz.org/");
out.println(" * ");
out.println(" * To Generate Graph image using graphviz:");
- String filename = outputFile.getName();
+ String filename = outputFile.getFileName().toString();
String basename = filename.substring(0,filename.indexOf('.'));
out.printf(" * $ dot -Tpng -Goverlap=false -o %s.png %s%n",basename,filename);
out.println(" */");
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java
index 95bd807..61330ac 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java
@@ -18,9 +18,9 @@
package org.eclipse.jetty.start;
-import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -45,7 +45,7 @@
* ex: modules/npn/npn-1.7.0_01.mod (property expansion resolves to non-existent file)
*/
private Set<String> missingModules = new HashSet<String>();
-
+
private int maxDepth = -1;
private Set<String> asNameSet(Set<Module> moduleSet)
@@ -117,7 +117,10 @@
if (parent == null)
{
- StartLog.debug("module not found [%s]%n",parentName);
+ if (parentName.contains("${"))
+ StartLog.debug("module not found [%s]%n",parentName);
+ else
+ StartLog.warn("module not found [%s]%n",parentName);
}
else
{
@@ -196,7 +199,7 @@
}
for (String parent : module.getParentNames())
{
- System.out.printf(" Parent: %s%n",parent);
+ System.out.printf(" Depend: %s%n",parent);
}
for (String lib : module.getLibs())
{
@@ -294,10 +297,10 @@
private void findParents(Module module, Map<String, Module> ret)
{
- ret.put(module.getName(), module);
+ ret.put(module.getName(),module);
for (Module parent : module.getParentEdges())
{
- ret.put(parent.getName(), parent);
+ ret.put(parent.getName(),parent);
findParents(parent,ret);
}
}
@@ -369,15 +372,33 @@
return module;
}
+ public void registerParentsIfMissing(BaseHome basehome, StartArgs args, Module module) throws IOException
+ {
+ Set<String> parents = new HashSet<>(module.getParentNames());
+ for (String name : parents)
+ {
+ if (!modules.containsKey(name))
+ {
+ Path file = basehome.getPath("modules/" + name + ".mod");
+ if (FS.canReadFile(file))
+ {
+ Module parent = registerModule(basehome,args,file);
+ updateParentReferencesTo(parent);
+ registerParentsIfMissing(basehome, args, parent);
+ }
+ }
+ }
+ }
+
public void registerAll(BaseHome basehome, StartArgs args) throws IOException
{
- for (File file : basehome.listFiles("modules",new FS.FilenameRegexFilter("^.*\\.mod$")))
+ for (Path path : basehome.getPaths("modules/*.mod"))
{
- registerModule(basehome,args,file);
+ registerModule(basehome,args,path);
}
// load missing post-expanded dependent modules
- boolean done = false;
+ boolean done = false;
while (!done)
{
done = true;
@@ -398,22 +419,22 @@
for (String missingParent : missingParents)
{
- File file = basehome.getFile("modules/" + missingParent + ".mod");
- if ( FS.canReadFile(file) )
+ Path file = basehome.getPath("modules/" + missingParent + ".mod");
+ if (FS.canReadFile(file))
{
Module module = registerModule(basehome,args,file);
updateParentReferencesTo(module);
}
else
{
- StartLog.debug("Missing module definition: [ Mod: %s | File: %s]", missingParent, file);
+ StartLog.debug("Missing module definition: [ Mod: %s | File: %s]",missingParent,file);
missingModules.add(missingParent);
}
}
}
}
- private Module registerModule(BaseHome basehome, StartArgs args, File file) throws FileNotFoundException, IOException
+ private Module registerModule(BaseHome basehome, StartArgs args, Path file) throws FileNotFoundException, IOException
{
if (!FS.canReadFile(file))
{
@@ -440,7 +461,7 @@
*/
public List<Module> resolveEnabled()
{
- Map<String, Module> active = new HashMap<String,Module>();
+ Map<String, Module> active = new HashMap<String, Module>();
for (Module module : modules.values())
{
@@ -455,20 +476,20 @@
*
* Ex: npn should match anything under npn/
*/
- for ( String missing : missingModules )
+ for (String missing : missingModules)
{
- for (String activeModule: active.keySet())
- {
- if ( missing.startsWith(activeModule) )
+ for (String activeModule : active.keySet())
+ {
+ if (missing.startsWith(activeModule))
{
- StartLog.warn("** Unable to continue, required dependency missing. [%s]", missing);
+ StartLog.warn("** Unable to continue, required dependency missing. [%s]",missing);
StartLog.warn("** As configured, Jetty is unable to start due to a missing enabled module dependency.");
StartLog.warn("** This may be due to a transitive dependency akin to spdy on npn, which resolves based on the JDK in use.");
return Collections.emptyList();
}
}
}
-
+
List<Module> ordered = new ArrayList<>();
ordered.addAll(active.values());
Collections.sort(ordered,new Module.DepthComparator());
@@ -477,7 +498,7 @@
public Set<String> resolveParentModulesOf(String moduleName)
{
- Map<String,Module> ret = new HashMap<>();
+ Map<String, Module> ret = new HashMap<>();
Module module = get(moduleName);
findParents(module,ret);
return ret.keySet();
@@ -524,4 +545,26 @@
m.setParentNames(resolvedParents);
}
}
+
+ @Override
+ public String toString()
+ {
+ StringBuilder str = new StringBuilder();
+ str.append("Modules[");
+ str.append("count=").append(modules.size());
+ str.append(",<");
+ boolean delim = false;
+ for (String name : modules.keySet())
+ {
+ if (delim)
+ {
+ str.append(',');
+ }
+ str.append(name);
+ delim = true;
+ }
+ str.append(">");
+ str.append("]");
+ return str.toString();
+ }
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/NaturalSort.java b/jetty-start/src/main/java/org/eclipse/jetty/start/NaturalSort.java
index 042b326..838a96d 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/NaturalSort.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/NaturalSort.java
@@ -19,6 +19,7 @@
package org.eclipse.jetty.start;
import java.io.File;
+import java.nio.file.Path;
import java.text.CollationKey;
import java.text.Collator;
import java.util.Comparator;
@@ -28,6 +29,19 @@
*/
public class NaturalSort
{
+ public static class Paths implements Comparator<Path>
+ {
+ private final Collator collator = Collator.getInstance();
+
+ @Override
+ public int compare(Path o1, Path o2)
+ {
+ CollationKey key1 = collator.getCollationKey(o1.toString());
+ CollationKey key2 = collator.getCollationKey(o2.toString());
+ return key1.compareTo(key2);
+ }
+ }
+
public static class Files implements Comparator<File>
{
private final Collator collator = Collator.getInstance();
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/PathFinder.java b/jetty-start/src/main/java/org/eclipse/jetty/start/PathFinder.java
new file mode 100644
index 0000000..1f06f06
--- /dev/null
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/PathFinder.java
@@ -0,0 +1,169 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystemLoopException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class PathFinder extends SimpleFileVisitor<Path>
+{
+ // internal tracking of prior notified paths (to avoid repeated notification of same ignored path)
+ private static Set<Path> NOTIFIED_PATHS = new HashSet<>();
+
+ private boolean includeDirsInResults = false;
+ private Map<String, Path> hits = new HashMap<>();
+ private Path basePath = null;
+ private PathMatcher dirMatcher = PathMatchers.getNonHidden();
+ private PathMatcher fileMatcher = PathMatchers.getNonHidden();
+
+ private void addHit(Path path)
+ {
+ String relPath = basePath.relativize(path).toString();
+ StartLog.debug("Found [" + relPath + "] " + path);
+ hits.put(relPath,path);
+ }
+
+ public PathMatcher getDirMatcher()
+ {
+ return dirMatcher;
+ }
+
+ public PathMatcher getFileMatcher()
+ {
+ return fileMatcher;
+ }
+
+ public List<File> getHitList()
+ {
+ List<File> ret = new ArrayList<>();
+ for (Path path : hits.values())
+ {
+ ret.add(path.toFile());
+ }
+ return ret;
+ }
+
+ public Collection<Path> getHits()
+ {
+ return hits.values();
+ }
+
+ public boolean isIncludeDirsInResults()
+ {
+ return includeDirsInResults;
+ }
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException
+ {
+ if (dirMatcher.matches(dir))
+ {
+ StartLog.debug("Following dir: " + dir);
+ if (includeDirsInResults && fileMatcher.matches(dir))
+ {
+ addHit(dir);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ else
+ {
+ StartLog.debug("Skipping dir: " + dir);
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ }
+
+ /**
+ * Set the active basePath, used for resolving relative paths.
+ * <p>
+ * When a hit arrives for a subsequent find that has the same relative path as a prior hit, the new hit overrides the prior path as the active hit.
+ *
+ * @param basePath
+ * the basePath to tag all hits with
+ */
+ public void setBase(Path basePath)
+ {
+ this.basePath = basePath;
+ }
+
+ public void setDirMatcher(PathMatcher dirMatcher)
+ {
+ this.dirMatcher = dirMatcher;
+ }
+
+ public void setFileMatcher(PathMatcher fileMatcher)
+ {
+ this.fileMatcher = fileMatcher;
+ }
+
+ public void setFileMatcher(String pattern)
+ {
+ this.fileMatcher = PathMatchers.getMatcher(pattern);
+ }
+
+ public void setIncludeDirsInResults(boolean includeDirsInResults)
+ {
+ this.includeDirsInResults = includeDirsInResults;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException
+ {
+ if (fileMatcher.matches(file))
+ {
+ addHit(file);
+ }
+ else
+ {
+ StartLog.debug("Ignoring file: " + file);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException
+ {
+ if (exc instanceof FileSystemLoopException)
+ {
+ if (!NOTIFIED_PATHS.contains(file))
+ {
+ StartLog.warn("skipping detected filesystem loop: " + file);
+ NOTIFIED_PATHS.add(file);
+ }
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ else
+ {
+ StartLog.warn(exc);
+ return super.visitFileFailed(file,exc);
+ }
+ }
+}
\ No newline at end of file
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/PathMatchers.java b/jetty-start/src/main/java/org/eclipse/jetty/start/PathMatchers.java
new file mode 100644
index 0000000..609c8b2
--- /dev/null
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/PathMatchers.java
@@ -0,0 +1,208 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+
+/**
+ * Common PathMatcher implementations.
+ */
+public class PathMatchers
+{
+ private static class NonHiddenMatcher implements PathMatcher
+ {
+ @Override
+ public boolean matches(Path path)
+ {
+ try
+ {
+ return !Files.isHidden(path);
+ }
+ catch (IOException e)
+ {
+ StartLog.debug(e);
+ return false;
+ }
+ }
+ }
+
+ private static final char GLOB_CHARS[] = "*?".toCharArray();
+ private static final char SYNTAXED_GLOB_CHARS[] = "{}[]|:".toCharArray();
+ private static final Path EMPTY_PATH = new File(".").toPath();
+
+ /**
+ * Convert a pattern to a Path object.
+ *
+ * @param pattern
+ * the raw pattern (can contain "glob:" or "regex:" syntax indicator)
+ * @return the Path version of the pattern provided.
+ */
+ private static Path asPath(String pattern)
+ {
+ String test = pattern;
+ if (test.startsWith("glob:"))
+ {
+ test = test.substring("glob:".length());
+ }
+ else if (test.startsWith("regex:"))
+ {
+ test = test.substring("regex:".length());
+ }
+ return new File(test).toPath();
+ }
+
+ public static PathMatcher getMatcher(String pattern)
+ {
+ FileSystem fs = FileSystems.getDefault();
+
+ // If using FileSystem.getPathMatcher() with "glob:" or "regex:"
+ // use FileSystem default pattern behavior
+ if (pattern.startsWith("glob:") || pattern.startsWith("regex:"))
+ {
+ StartLog.debug("Using Standard " + fs.getClass().getName() + " pattern: " + pattern);
+ return fs.getPathMatcher(pattern);
+ }
+
+ // If the pattern starts with a root path then its assumed to
+ // be a full system path
+ for (Path root : fs.getRootDirectories())
+ {
+ StartLog.debug("root: " + root);
+ if (pattern.startsWith(root.toString()))
+ {
+ String pat = "glob:" + pattern;
+ StartLog.debug("Using absolute path pattern: " + pat);
+ return fs.getPathMatcher(pat);
+ }
+ }
+
+ // Doesn't start with filesystem root, then assume the pattern
+ // is a relative file path pattern.
+ String pat = "glob:**/" + pattern;
+ StartLog.debug("Using relative path pattern: " + pat);
+ return fs.getPathMatcher(pat);
+ }
+
+ public static PathMatcher getNonHidden()
+ {
+ return new NonHiddenMatcher();
+ }
+
+ /**
+ * Provide the non-glob / non-regex prefix on the pattern as a Path reference.
+ *
+ * @param pattern
+ * the pattern to test
+ * @return the Path representing the search root for the pattern provided.
+ */
+ public static Path getSearchRoot(final String pattern)
+ {
+ Path path = asPath(pattern);
+ Path test = path.getRoot();
+
+ boolean isSyntaxed = pattern.startsWith("glob:") || pattern.startsWith("regex:");
+
+ int len = path.getNameCount();
+ for (int i = 0; i < len; i++)
+ {
+ Path part = path.getName(i);
+ if (isGlob(part.toString(),isSyntaxed))
+ {
+ // found a glob part, return prior parts now
+ break;
+ }
+
+ // is this the last entry?
+ if (i == (len - 1))
+ {
+ // always return prior entries
+ break;
+ }
+
+ if (test == null)
+ {
+ test = part;
+ }
+ else
+ {
+ test = test.resolve(part);
+ }
+ }
+
+ if (test == null)
+ {
+ return EMPTY_PATH;
+ }
+ return test;
+ }
+
+ /**
+ * Tests if provided pattern is an absolute reference (or not)
+ *
+ * @param pattern
+ * the pattern to test
+ * @return true if pattern is an absolute reference.
+ */
+ public static boolean isAbsolute(final String pattern)
+ {
+ return asPath(pattern).isAbsolute();
+ }
+
+ /**
+ * Determine if part is a glob pattern.
+ *
+ * @param part
+ * the string to check
+ * @param syntaxed
+ * true if overall pattern is syntaxed with <code>"glob:"</code> or <code>"regex:"</code>
+ * @return true if part has glob characters
+ */
+ private static boolean isGlob(String part, boolean syntaxed)
+ {
+ int len = part.length();
+ for (int i = 0; i < len; i++)
+ {
+ char c = part.charAt(i);
+ for (char g : GLOB_CHARS)
+ {
+ if (c == g)
+ {
+ return true;
+ }
+ }
+ if (syntaxed)
+ {
+ for (char g : SYNTAXED_GLOB_CHARS)
+ {
+ if (c == g)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Props.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Props.java
index 838cf46..f760f6e 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Props.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Props.java
@@ -18,10 +18,14 @@
package org.eclipse.jetty.start;
+import static org.eclipse.jetty.start.UsageException.*;
+
import java.io.IOException;
import java.io.OutputStream;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Stack;
@@ -60,8 +64,91 @@
}
public static final String ORIGIN_SYSPROP = "<system-property>";
+
+ public static String getValue(String arg)
+ {
+ int idx = arg.indexOf('=');
+ if (idx == (-1))
+ {
+ throw new UsageException(ERR_BAD_ARG,"Argument is missing a required value: %s",arg);
+ }
+ String value = arg.substring(idx + 1).trim();
+ if (value.length() <= 0)
+ {
+ throw new UsageException(ERR_BAD_ARG,"Argument is missing a required value: %s",arg);
+ }
+ return value;
+ }
+
+ public static List<String> getValues(String arg)
+ {
+ String v = getValue(arg);
+ ArrayList<String> l = new ArrayList<>();
+ for (String s : v.split(","))
+ {
+ if (s != null)
+ {
+ s = s.trim();
+ if (s.length() > 0)
+ {
+ l.add(s);
+ }
+ }
+ }
+ return l;
+ }
private Map<String, Prop> props = new HashMap<>();
+ private List<String> sysPropTracking = new ArrayList<>();
+
+ public void addAll(Props other)
+ {
+ this.props.putAll(other.props);
+ this.sysPropTracking.addAll(other.sysPropTracking);
+ }
+
+ /**
+ * Add a potential argument as a property.
+ * <p>
+ * If arg is not a property, ignore it.
+ * @param arg the argument to parse for a potential property
+ * @param source the source for this argument (to track origin of property from)
+ */
+ public void addPossibleProperty(String arg, String source)
+ {
+ // Start property (syntax similar to System property)
+ if (arg.startsWith("-D"))
+ {
+ String[] assign = arg.substring(2).split("=",2);
+ switch (assign.length)
+ {
+ case 2:
+ setSystemProperty(assign[0],assign[1]);
+ setProperty(assign[0],assign[1],source);
+ break;
+ case 1:
+ setSystemProperty(assign[0],"");
+ setProperty(assign[0],"",source);
+ break;
+ default:
+ break;
+ }
+ return;
+ }
+
+ // Is this a raw property declaration?
+ int idx = arg.indexOf('=');
+ if (idx >= 0)
+ {
+ String key = arg.substring(0,idx);
+ String value = arg.substring(idx + 1);
+
+ setProperty(key,value,source);
+ return;
+ }
+
+ // All other strings are ignored
+ }
public String cleanReference(String property)
{
@@ -96,13 +183,6 @@
return str;
}
- if (props.isEmpty())
- {
- // nothing to expand
- // this situation can occur from --add-to-startd on a new blank base directory
- return str;
- }
-
Pattern pat = Pattern.compile("(?<=[^$]|^)(\\$\\{[^}]*\\})");
Matcher mat = pat.matcher(str);
StringBuilder expanded = new StringBuilder();
@@ -138,7 +218,7 @@
if (value == null)
{
StartLog.debug("Unable to expand: %s",property);
- expanded.append(property);
+ expanded.append(mat.group(1));
}
else
{
@@ -164,8 +244,13 @@
public Prop getProp(String key)
{
+ return getProp(key,true);
+ }
+
+ public Prop getProp(String key, boolean searchSystemProps)
+ {
Prop prop = props.get(key);
- if (prop == null)
+ if ((prop == null) && searchSystemProps)
{
// try system property
prop = getSystemProperty(key);
@@ -221,6 +306,11 @@
return props.values().iterator();
}
+ public void reset()
+ {
+ props.clear();
+ }
+
public void setProperty(Prop prop)
{
props.put(prop.key,prop);
@@ -256,4 +346,10 @@
// write normal properties file
props.store(stream,comments);
}
+
+ public void setSystemProperty(String key, String value)
+ {
+ System.setProperty(key,value);
+ sysPropTracking.add(key);
+ }
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java b/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
index 93ca76d..cde9f56 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
@@ -21,26 +21,29 @@
import static org.eclipse.jetty.start.UsageException.*;
import java.io.File;
-import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
+import java.util.StringTokenizer;
import org.eclipse.jetty.start.Props.Prop;
+import org.eclipse.jetty.start.config.ConfigSource;
+import org.eclipse.jetty.start.config.ConfigSources;
+import org.eclipse.jetty.start.config.DirConfigSource;
/**
* The Arguments required to start Jetty.
*/
public class StartArgs
{
- public static final String CMD_LINE_SOURCE = "<command-line>";
public static final String VERSION;
static
@@ -67,23 +70,41 @@
private static final String SERVER_MAIN = "org.eclipse.jetty.xml.XmlConfiguration";
- private List<String> commandLine = new ArrayList<>();
+ /** List of enabled modules */
private Set<String> modules = new HashSet<>();
+ /** Map of enabled modules to the source of where that activation occurred */
private Map<String, List<String>> sources = new HashMap<>();
+ /** Map of properties to where that property was declared */
+ private Map<String, String> propertySource = new HashMap<>();
+ /** List of all active [files] sections from enabled modules */
private List<FileArg> files = new ArrayList<>();
+ /** List of all active [lib] sectinos from enabled modules */
private Classpath classpath;
+ /** List of all active [xml] sections from enabled modules */
+ private List<Path> xmls = new ArrayList<>();
+ /** JVM arguments, found via commmand line and in all active [exec] sections from enabled modules */
+ private List<String> jvmArgs = new ArrayList<>();
+
+ /** List of all xml references found directly on command line or start.ini */
private List<String> xmlRefs = new ArrayList<>();
- private List<File> xmls = new ArrayList<>();
+
private Props properties = new Props();
private Set<String> systemPropertyKeys = new HashSet<>();
- private List<String> jvmArgs = new ArrayList<>();
- private List<String> moduleStartdIni = new ArrayList<>();
- private List<String> moduleStartIni = new ArrayList<>();
- private Map<String, String> propertySource = new HashMap<>();
+ private List<String> rawLibs = new ArrayList<>();
+
+ // jetty.base - build out commands
+ /** --add-to-startd=[module,[module]] */
+ private List<String> addToStartdIni = new ArrayList<>();
+ /** --add-to-start=[module,[module]] */
+ private List<String> addToStartIni = new ArrayList<>();
+
+ // module inspection commands
+ /** --write-module-graph=[filename] */
private String moduleGraphFilename;
+ /** Collection of all modules */
private Modules allModules;
- // Should the server be run?
+ /** Should the server be run? */
private boolean run = true;
private boolean download = false;
private boolean help = false;
@@ -96,9 +117,8 @@
private boolean exec = false;
- public StartArgs(String[] commandLineArgs)
+ public StartArgs()
{
- commandLine.addAll(Arrays.asList(commandLineArgs));
classpath = new Classpath();
}
@@ -117,13 +137,13 @@
System.setProperty(key,value);
}
- private void addUniqueXmlFile(String xmlRef, File xmlfile) throws IOException
+ private void addUniqueXmlFile(String xmlRef, Path xmlfile) throws IOException
{
if (!FS.canReadFile(xmlfile))
{
throw new IOException("Cannot read file: " + xmlRef);
}
- xmlfile = xmlfile.getCanonicalFile();
+ xmlfile = FS.toRealPath(xmlfile);
if (!xmls.contains(xmlfile))
{
xmls.add(xmlfile);
@@ -141,13 +161,13 @@
return;
}
- for (File xml : xmls)
+ for (Path xml : xmls)
{
- System.out.printf(" %s%n",baseHome.toShortForm(xml.getAbsolutePath()));
+ System.out.printf(" %s%n",baseHome.toShortForm(xml.toAbsolutePath()));
}
}
- public void dumpEnvironment()
+ public void dumpEnvironment(BaseHome baseHome)
{
// Java Details
System.out.println();
@@ -169,10 +189,30 @@
System.out.println();
System.out.println("Jetty Environment:");
System.out.println("-----------------");
-
+ dumpProperty("jetty.version");
dumpProperty("jetty.home");
dumpProperty("jetty.base");
- dumpProperty("jetty.version");
+
+ // Jetty Configuration Environment
+ System.out.println();
+ System.out.println("Config Search Order:");
+ System.out.println("--------------------");
+ for (ConfigSource config : baseHome.getConfigSources())
+ {
+ System.out.printf(" %s",config.getId());
+ if (config instanceof DirConfigSource)
+ {
+ DirConfigSource dirsource = (DirConfigSource)config;
+ if (dirsource.isPropertyBased())
+ {
+ System.out.printf(" -> %s",dirsource.getDir());
+ }
+ }
+ System.out.println();
+ }
+
+ // Jetty Se
+ System.out.println();
}
public void dumpJvmArgs()
@@ -230,6 +270,30 @@
}
}
+ private void dumpProperty(String key)
+ {
+ Prop prop = properties.getProp(key);
+ if (prop == null)
+ {
+ System.out.printf(" %s (not defined)%n",key);
+ }
+ else
+ {
+ System.out.printf(" %s = %s%n",key,properties.expand(prop.value));
+ if (StartLog.isDebugEnabled())
+ {
+ System.out.printf(" origin: %s%n",prop.origin);
+ while (prop.overrides != null)
+ {
+ prop = prop.overrides;
+ System.out.printf(" (overrides)%n");
+ System.out.printf(" %s = %s%n",key,properties.expand(prop.value));
+ System.out.printf(" origin: %s%n",prop.origin);
+ }
+ }
+ }
+ }
+
public void dumpSystemProperties()
{
System.out.println();
@@ -258,30 +322,6 @@
System.out.printf(" %s = %s%n",key,System.getProperty(key));
}
- private void dumpProperty(String key)
- {
- Prop prop = properties.getProp(key);
- if (prop == null)
- {
- System.out.printf(" %s (not defined)%n",key);
- }
- else
- {
- System.out.printf(" %s = %s%n",key,properties.expand(prop.value));
- if (StartLog.isDebugEnabled())
- {
- System.out.printf(" origin: %s%n",prop.origin);
- while (prop.overrides != null)
- {
- prop = prop.overrides;
- System.out.printf(" (overrides)%n");
- System.out.printf(" %s = %s%n",key,properties.expand(prop.value));
- System.out.printf(" origin: %s%n",prop.origin);
- }
- }
- }
- }
-
/**
* Ensure that the System Properties are set (if defined as a System property, or start.config property, or start.ini property)
*
@@ -309,6 +349,27 @@
}
/**
+ * Expand any command line added <code>--lib</code> lib references.
+ *
+ * @param baseHome
+ * @throws IOException
+ */
+ public void expandLibs(BaseHome baseHome) throws IOException
+ {
+ for (String rawlibref : rawLibs)
+ {
+ StartLog.debug("rawlibref = " + rawlibref);
+ String libref = properties.expand(rawlibref);
+ StartLog.debug("expanded = " + libref);
+
+ for (Path libpath : baseHome.getPaths(libref))
+ {
+ classpath.addComponent(libpath.toFile());
+ }
+ }
+ }
+
+ /**
* Build up the Classpath and XML file references based on enabled Module list.
*
* @param baseHome
@@ -322,72 +383,27 @@
// Find and Expand Libraries
for (String rawlibref : module.getLibs())
{
+ StartLog.debug("rawlibref = " + rawlibref);
String libref = properties.expand(rawlibref);
+ StartLog.debug("expanded = " + libref);
- if (libref.startsWith("regex:"))
+ for (Path libpath : baseHome.getPaths(libref))
{
- String regex = libref.substring("regex:".length());
- for (File libfile : baseHome.listFilesRegex(regex))
- {
- classpath.addComponent(libfile);
- }
- continue;
+ classpath.addComponent(libpath.toFile());
}
+ }
- libref = FS.separators(libref);
-
- // Any globs here?
- if (libref.contains("*"))
- {
- // Glob Reference
- int idx = libref.lastIndexOf(File.separatorChar);
-
- String relativePath = "/";
- String filenameRef = libref;
- if (idx >= 0)
- {
- relativePath = libref.substring(0,idx);
- filenameRef = libref.substring(idx + 1);
- }
-
- StringBuilder regex = new StringBuilder();
- regex.append('^');
- for (char c : filenameRef.toCharArray())
- {
- switch (c)
- {
- case '*':
- regex.append(".*");
- break;
- case '.':
- regex.append("\\.");
- break;
- default:
- regex.append(c);
- }
- }
- regex.append('$');
-
- FileFilter filter = new FS.FilenameRegexFilter(regex.toString());
-
- for (File libfile : baseHome.listFiles(relativePath,filter))
- {
- classpath.addComponent(libfile);
- }
- }
- else
- {
- // Straight Reference
- File libfile = baseHome.getFile(libref);
- classpath.addComponent(libfile);
- }
+ for (String jvmArg : module.getJvmArgs())
+ {
+ exec = true;
+ jvmArgs.add(jvmArg);
}
// Find and Expand XML files
for (String xmlRef : module.getXmls())
{
// Straight Reference
- File xmlfile = baseHome.getFile(xmlRef);
+ Path xmlfile = baseHome.getPath(xmlRef);
addUniqueXmlFile(xmlRef,xmlfile);
}
@@ -400,6 +416,16 @@
}
}
+ public List<String> getAddToStartdIni()
+ {
+ return addToStartdIni;
+ }
+
+ public List<String> getAddToStartIni()
+ {
+ return addToStartIni;
+ }
+
public Modules getAllModules()
{
return allModules;
@@ -410,9 +436,9 @@
return classpath;
}
- public List<String> getCommandLine()
+ public Set<String> getEnabledModules()
{
- return this.commandLine;
+ return this.modules;
}
public List<FileArg> getFiles()
@@ -420,11 +446,6 @@
return files;
}
- public Set<String> getEnabledModules()
- {
- return this.modules;
- }
-
public List<String> getJvmArgs()
{
return jvmArgs;
@@ -436,11 +457,11 @@
if (addJavaInit)
{
- cmd.addArg(CommandLineBuilder.findJavaBin());
+ cmd.addRawArg(CommandLineBuilder.findJavaBin());
for (String x : jvmArgs)
{
- cmd.addArg(x);
+ cmd.addRawArg(x);
}
cmd.addRawArg("-Djetty.home=" + baseHome.getHome());
@@ -453,7 +474,7 @@
cmd.addEqualsArg("-D" + propKey,value);
}
- cmd.addArg("-cp");
+ cmd.addRawArg("-cp");
cmd.addRawArg(classpath.toString());
cmd.addRawArg(getMainClassname());
}
@@ -475,12 +496,12 @@
{
properties.store(out,"start.jar properties");
}
- cmd.addArg(prop_file.getAbsolutePath());
+ cmd.addRawArg(prop_file.getAbsolutePath());
}
- for (File xml : xmls)
+ for (Path xml : xmls)
{
- cmd.addRawArg(xml.getAbsolutePath());
+ cmd.addRawArg(xml.toAbsolutePath().toString());
}
return cmd;
@@ -497,16 +518,6 @@
return moduleGraphFilename;
}
- public List<String> getModuleStartdIni()
- {
- return moduleStartdIni;
- }
-
- public List<String> getModuleStartIni()
- {
- return moduleStartIni;
- }
-
public Props getProperties()
{
return properties;
@@ -517,40 +528,7 @@
return sources.get(module);
}
- private String getValue(String arg)
- {
- int idx = arg.indexOf('=');
- if (idx == (-1))
- {
- throw new UsageException(ERR_BAD_ARG,"Argument is missing a required value: %s",arg);
- }
- String value = arg.substring(idx + 1).trim();
- if (value.length() <= 0)
- {
- throw new UsageException(ERR_BAD_ARG,"Argument is missing a required value: %s",arg);
- }
- return value;
- }
-
- private List<String> getValues(String arg)
- {
- String v = getValue(arg);
- ArrayList<String> l = new ArrayList<>();
- for (String s : v.split(","))
- {
- if (s != null)
- {
- s = s.trim();
- if (s.length() > 0)
- {
- l.add(s);
- }
- }
- }
- return l;
- }
-
- public List<File> getXmlFiles()
+ public List<Path> getXmlFiles()
{
return xmls;
}
@@ -610,31 +588,6 @@
return listModules;
}
- private void setProperty(String key, String value, String source)
- {
- // Special / Prevent override from start.ini's
- if (key.equals("jetty.home"))
- {
- properties.setProperty("jetty.home",System.getProperty("jetty.home"),source);
- return;
- }
-
- // Special / Prevent override from start.ini's
- if (key.equals("jetty.base"))
- {
- properties.setProperty("jetty.base",System.getProperty("jetty.base"),source);
- return;
- }
-
- // Normal
- properties.setProperty(key,value,source);
- }
-
- public void setRun(boolean run)
- {
- this.run = run;
- }
-
public boolean isRun()
{
return run;
@@ -650,20 +603,16 @@
return version;
}
- public void parse(BaseHome baseHome, TextFile file)
+ public void parse(ConfigSources sources)
{
- String source;
- try
+ ListIterator<ConfigSource> iter = sources.reverseListIterator();
+ while (iter.hasPrevious())
{
- source = baseHome.toShortForm(file.getFile());
- }
- catch (Exception e)
- {
- throw new UsageException(ERR_BAD_ARG,"Bad file: %s",file);
- }
- for (String line : file)
- {
- parse(line,source);
+ ConfigSource source = iter.previous();
+ for (String arg : source.getArgs())
+ {
+ parse(arg,source.getId());
+ }
}
}
@@ -688,28 +637,25 @@
if ("--help".equals(arg) || "-?".equals(arg))
{
- if (!CMD_LINE_SOURCE.equals(source))
- {
- throw new UsageException(ERR_BAD_ARG,"%s not allowed in %s",arg,source);
- }
-
help = true;
run = false;
return;
}
- if ("--debug".equals(arg))
+ if ("--debug".equals(arg) || arg.startsWith("--start-log-file"))
{
// valid, but handled in StartLog instead
return;
}
+ if (arg.startsWith("--extra-start-dir="))
+ {
+ // valid, but handled in ConfigSources instead
+ return;
+ }
+
if ("--stop".equals(arg))
{
- if (!CMD_LINE_SOURCE.equals(source))
- {
- throw new UsageException(ERR_BAD_ARG,"%s not allowed in %s",arg,source);
- }
stopCommand = true;
run = false;
return;
@@ -717,7 +663,7 @@
if (arg.startsWith("--download="))
{
- addFile(getValue(arg));
+ addFile(Props.getValue(arg));
run = false;
download = true;
return;
@@ -746,15 +692,12 @@
if ("--dry-run".equals(arg) || "--exec-print".equals(arg))
{
- if (!CMD_LINE_SOURCE.equals(source))
- {
- throw new UsageException(ERR_BAD_ARG,"%s not allowed in %s",arg,source);
- }
dryRun = true;
run = false;
return;
}
+ // Enable forked execution of Jetty server
if ("--exec".equals(arg))
{
exec = true;
@@ -762,11 +705,18 @@
}
// Arbitrary Libraries
-
if (arg.startsWith("--lib="))
{
- String cp = getValue(arg);
- classpath.addClasspath(cp);
+ String cp = Props.getValue(arg);
+
+ if (cp != null)
+ {
+ StringTokenizer t = new StringTokenizer(cp,File.pathSeparator);
+ while (t.hasMoreTokens())
+ {
+ rawLibs.add(t.nextToken());
+ }
+ }
return;
}
@@ -778,31 +728,28 @@
return;
}
- if (arg.startsWith("--add-to-startd"))
+ // jetty.base build-out : add to ${jetty.base}/start.d/
+ if (arg.startsWith("--add-to-startd="))
{
- if (!CMD_LINE_SOURCE.equals(source))
- {
- throw new UsageException(ERR_BAD_ARG,"%s not allowed in %s",arg,source);
- }
- moduleStartdIni.addAll(getValues(arg));
+ addToStartdIni.addAll(Props.getValues(arg));
run = false;
+ download = true;
return;
}
- if (arg.startsWith("--add-to-start"))
+ // jetty.base build-out : add to ${jetty.base}/start.ini
+ if (arg.startsWith("--add-to-start="))
{
- if (!CMD_LINE_SOURCE.equals(source))
- {
- throw new UsageException(ERR_BAD_ARG,"%s not allowed in %s",arg,source);
- }
- moduleStartIni.addAll(getValues(arg));
+ addToStartIni.addAll(Props.getValues(arg));
run = false;
+ download = true;
return;
}
+ // Enable a module
if (arg.startsWith("--module="))
{
- for (String moduleName : getValues(arg))
+ for (String moduleName : Props.getValues(arg))
{
modules.add(moduleName);
List<String> list = sources.get(moduleName);
@@ -816,9 +763,10 @@
return;
}
+ // Create graphviz output of module graph
if (arg.startsWith("--write-module-graph="))
{
- this.moduleGraphFilename = getValue(arg);
+ this.moduleGraphFilename = Props.getValue(arg);
run = false;
return;
}
@@ -862,14 +810,11 @@
String key = arg.substring(0,idx);
String value = arg.substring(idx + 1);
- if (source != CMD_LINE_SOURCE)
+ if (propertySource.containsKey(key))
{
- if (propertySource.containsKey(key))
- {
- throw new UsageException(ERR_BAD_ARG,"Property %s in %s already set in %s",key,source,propertySource.get(key));
- }
- propertySource.put(key,source);
+ StartLog.warn("Property %s in %s already set in %s",key,source,propertySource.get(key));
}
+ propertySource.put(key,source);
if ("OPTION".equals(key) || "OPTIONS".equals(key))
{
@@ -901,26 +846,16 @@
throw new UsageException(ERR_BAD_ARG,"Unrecognized argument: \"%s\" in %s",arg,source);
}
- public StartArgs parseCommandLine()
- {
- for (String line : commandLine)
- {
- parse(line,StartArgs.CMD_LINE_SOURCE);
- }
-
- return this;
- }
-
public void resolveExtraXmls(BaseHome baseHome) throws IOException
{
// Find and Expand XML files
for (String xmlRef : xmlRefs)
{
// Straight Reference
- File xmlfile = baseHome.getFile(xmlRef);
- if (!xmlfile.exists())
+ Path xmlfile = baseHome.getPath(xmlRef);
+ if (!FS.exists(xmlfile))
{
- xmlfile = baseHome.getFile("etc/" + xmlRef);
+ xmlfile = baseHome.getPath("etc/" + xmlRef);
}
addUniqueXmlFile(xmlRef,xmlfile);
}
@@ -931,13 +866,36 @@
this.allModules = allModules;
}
+ private void setProperty(String key, String value, String source)
+ {
+ // Special / Prevent override from start.ini's
+ if (key.equals("jetty.home"))
+ {
+ properties.setProperty("jetty.home",System.getProperty("jetty.home"),source);
+ return;
+ }
+
+ // Special / Prevent override from start.ini's
+ if (key.equals("jetty.base"))
+ {
+ properties.setProperty("jetty.base",System.getProperty("jetty.base"),source);
+ return;
+ }
+
+ // Normal
+ properties.setProperty(key,value,source);
+ }
+
+ public void setRun(boolean run)
+ {
+ this.run = run;
+ }
+
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
- builder.append("StartArgs [commandLine=");
- builder.append(commandLine);
- builder.append(", enabledModules=");
+ builder.append("StartArgs [enabledModules=");
builder.append(modules);
builder.append(", xmlRefs=");
builder.append(xmlRefs);
@@ -948,5 +906,4 @@
builder.append("]");
return builder.toString();
}
-
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java b/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java
index c2635ae..524f958 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/StartIni.java
@@ -18,16 +18,17 @@
package org.eclipse.jetty.start;
-import java.io.File;
-import java.io.FileNotFoundException;
import java.io.IOException;
+import java.nio.file.Path;
/**
* Simple Start .INI handler
*/
public class StartIni extends TextFile
{
- public StartIni(File file) throws FileNotFoundException, IOException
+ private Path basedir;
+
+ public StartIni(Path file) throws IOException
{
super(file);
}
@@ -41,12 +42,33 @@
String value = line.substring(idx + 1);
for (String part : value.split(","))
{
- super.addUniqueLine("--module=" + part);
+ super.addUniqueLine("--module=" + expandBaseDir(part));
}
}
else
{
- super.addUniqueLine(line);
+ super.addUniqueLine(expandBaseDir(line));
}
}
+
+ private String expandBaseDir(String line)
+ {
+ if (line == null)
+ {
+ return line;
+ }
+
+ return line.replace("${start.basedir}",basedir.toString());
+ }
+
+ @Override
+ public void init()
+ {
+ basedir = getFile().getParent().toAbsolutePath();
+ }
+
+ public Path getBaseDir()
+ {
+ return basedir;
+ }
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/StartLog.java b/jetty-start/src/main/java/org/eclipse/jetty/start/StartLog.java
index c411d0d..1f4105d 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/StartLog.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/StartLog.java
@@ -18,13 +18,15 @@
package org.eclipse.jetty.start;
-import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
import java.util.Date;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+
+import org.eclipse.jetty.start.config.CommandLineConfigSource;
/**
* Centralized Place for logging.
@@ -62,7 +64,7 @@
{
System.err.printf("INFO: " + format + "%n",args);
}
-
+
public static void warn(String format, Object... args)
{
System.err.printf("WARNING: " + format + "%n",args);
@@ -72,7 +74,7 @@
{
t.printStackTrace(System.err);
}
-
+
public static boolean isDebugEnabled()
{
return INSTANCE.debug;
@@ -80,17 +82,17 @@
private boolean debug = false;
- public void initialize(BaseHome baseHome, StartArgs args) throws IOException
+ public void initialize(BaseHome baseHome, CommandLineConfigSource cmdLineSource) throws IOException
{
- // Debug with boolean
- Pattern debugBoolPat = Pattern.compile("(-D)?debug=(.*)");
- // Log file name
- Pattern logFilePat = Pattern.compile("(-D)?start-log-file=(.*)");
+ String dbgProp = cmdLineSource.getProperty("debug");
+ if (dbgProp != null)
+ {
+ debug = Boolean.parseBoolean(dbgProp);
+ }
- // TODO: support backward compatible --daemon argument ??
+ String logFileName = cmdLineSource.getProperty("start-log-file");
- Matcher matcher;
- for (String arg : args.getCommandLine())
+ for (String arg : cmdLineSource.getArgs())
{
if ("--debug".equals(arg))
{
@@ -98,55 +100,55 @@
continue;
}
- matcher = debugBoolPat.matcher(arg);
- if (matcher.matches())
+ if (arg.startsWith("--start-log-file"))
{
- debug = Boolean.parseBoolean(matcher.group(2));
+ logFileName = Props.getValue(arg);
continue;
}
+ }
- matcher = logFilePat.matcher(arg);
- if (matcher.matches())
- {
- String filename = matcher.group(2);
- File logfile = baseHome.getBaseFile(filename);
- initLogFile(logfile);
- }
+ if (logFileName != null)
+ {
+ Path logfile = baseHome.getBasePath(logFileName);
+ initLogFile(logfile);
}
}
- public void initLogFile(File logfile) throws IOException
+ public void initLogFile(Path logfile) throws IOException
{
if (logfile != null)
{
- File logDir = logfile.getParentFile();
- if (!logDir.exists() || !logDir.canWrite())
+ try
{
- String err = String.format("Cannot write %s to directory %s [directory doesn't exist or is read-only]",logfile.getName(),
- logDir.getAbsolutePath());
- throw new UsageException(UsageException.ERR_LOGGING,new IOException(err));
+ Path logDir = logfile.getParent();
+ FS.ensureDirectoryWritable(logDir);
+
+ Path startLog = logfile;
+
+ if (!FS.exists(startLog) && !FS.createNewFile(startLog))
+ {
+ // Output about error is lost in majority of cases.
+ throw new UsageException(UsageException.ERR_LOGGING,new IOException("Unable to create: " + startLog.toAbsolutePath()));
+ }
+
+ if (!FS.canWrite(startLog))
+ {
+ // Output about error is lost in majority of cases.
+ throw new UsageException(UsageException.ERR_LOGGING,new IOException("Unable to write to: " + startLog.toAbsolutePath()));
+ }
+
+ System.out.println("Logging to " + logfile);
+
+ OutputStream out = Files.newOutputStream(startLog,StandardOpenOption.CREATE,StandardOpenOption.APPEND);
+ PrintStream logger = new PrintStream(out);
+ System.setOut(logger);
+ System.setErr(logger);
+ System.out.println("Establishing " + logfile + " on " + new Date());
}
-
- File startLog = logfile;
-
- if (!startLog.exists() && !startLog.createNewFile())
+ catch (IOException e)
{
- // Output about error is lost in majority of cases.
- throw new UsageException(UsageException.ERR_LOGGING,new IOException("Unable to create: " + startLog.getAbsolutePath()));
+ throw new UsageException(UsageException.ERR_LOGGING,e);
}
-
- if (!startLog.canWrite())
- {
- // Output about error is lost in majority of cases.
- throw new UsageException(UsageException.ERR_LOGGING,new IOException("Unable to write to: " + startLog.getAbsolutePath()));
- }
-
- System.out.println("Logging to " + logfile);
-
- PrintStream logger = new PrintStream(new FileOutputStream(startLog,false));
- System.setOut(logger);
- System.setErr(logger);
- System.out.println("Establishing " + logfile + " on " + new Date());
}
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/TextFile.java b/jetty-start/src/main/java/org/eclipse/jetty/start/TextFile.java
index fccc762..862422f 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/TextFile.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/TextFile.java
@@ -19,10 +19,11 @@
package org.eclipse.jetty.start;
import java.io.BufferedReader;
-import java.io.File;
import java.io.FileNotFoundException;
-import java.io.FileReader;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -36,40 +37,37 @@
*/
public class TextFile implements Iterable<String>
{
- private final File file;
+ private final Path file;
private final List<String> lines = new ArrayList<>();
- public TextFile(File file) throws FileNotFoundException, IOException
+ public TextFile(Path file) throws FileNotFoundException, IOException
{
this.file = file;
init();
if (!FS.canReadFile(file))
{
- StartLog.debug("Skipping read of missing file: %s",file.getAbsolutePath());
+ StartLog.debug("Skipping read of missing file: %s",file.toAbsolutePath());
return;
}
- try (FileReader reader = new FileReader(file))
+ try (BufferedReader buf = Files.newBufferedReader(file,StandardCharsets.UTF_8))
{
- try (BufferedReader buf = new BufferedReader(reader))
+ String line;
+ while ((line = buf.readLine()) != null)
{
- String line;
- while ((line = buf.readLine()) != null)
+ if (line.length() == 0)
{
- if (line.length() == 0)
- {
- continue;
- }
-
- if (line.charAt(0) == '#')
- {
- continue;
- }
-
- // TODO - bad form calling derived method from base class constructor
- process(line.trim());
+ continue;
}
+
+ if (line.charAt(0) == '#')
+ {
+ continue;
+ }
+
+ // TODO - bad form calling derived method from base class constructor
+ process(line.trim());
}
}
}
@@ -84,7 +82,7 @@
lines.add(line);
}
- public File getFile()
+ public Path getFile()
{
return file;
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/config/CommandLineConfigSource.java b/jetty-start/src/main/java/org/eclipse/jetty/start/config/CommandLineConfigSource.java
new file mode 100644
index 0000000..61f9f64
--- /dev/null
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/config/CommandLineConfigSource.java
@@ -0,0 +1,245 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.config;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jetty.start.BaseHome;
+import org.eclipse.jetty.start.FS;
+import org.eclipse.jetty.start.Props;
+import org.eclipse.jetty.start.Props.Prop;
+import org.eclipse.jetty.start.UsageException;
+
+/**
+ * Configuration Source representing the Command Line arguments.
+ */
+public class CommandLineConfigSource implements ConfigSource
+{
+ public static final String ORIGIN_INTERNAL_FALLBACK = "<internal-fallback>";
+ public static final String ORIGIN_CMD_LINE = "<command-line>";
+
+ private final List<String> args;
+ private final Props props;
+ private final Path homePath;
+ private final Path basePath;
+
+ public CommandLineConfigSource(String rawargs[])
+ {
+ this.args = Arrays.asList(rawargs);
+ this.props = new Props();
+ for (String arg : args)
+ {
+ this.props.addPossibleProperty(arg,ORIGIN_CMD_LINE);
+ }
+
+ // Setup ${jetty.base} and ${jetty.home}
+ this.homePath = findJettyHomePath().toAbsolutePath();
+ this.basePath = findJettyBasePath().toAbsolutePath();
+
+ // Update System Properties
+ setSystemProperty(BaseHome.JETTY_HOME,homePath.toAbsolutePath().toString());
+ setSystemProperty(BaseHome.JETTY_BASE,basePath.toAbsolutePath().toString());
+ }
+
+ private final Path findJettyBasePath()
+ {
+ // If a jetty property is defined, use it
+ Prop prop = this.props.getProp(BaseHome.JETTY_BASE,false);
+ if (prop != null && !isEmpty(prop.value))
+ {
+ return FS.toPath(prop.value);
+ }
+
+ // If a system property is defined, use it
+ String val = System.getProperty(BaseHome.JETTY_BASE);
+ if (!isEmpty(val))
+ {
+ return FS.toPath(val);
+ }
+
+ // Lastly, fall back to base == ${user.dir}
+ Path base = FS.toPath(this.props.getString("user.dir","."));
+ setProperty(BaseHome.JETTY_BASE,base.toString(),ORIGIN_INTERNAL_FALLBACK);
+ return base;
+ }
+
+ private final Path findJettyHomePath()
+ {
+ // If a jetty property is defined, use it
+ Prop prop = this.props.getProp(BaseHome.JETTY_HOME,false);
+ if (prop != null && !isEmpty(prop.value))
+ {
+ return FS.toPath(prop.value);
+ }
+
+ // If a system property is defined, use it
+ String val = System.getProperty(BaseHome.JETTY_HOME);
+ if (!isEmpty(val))
+ {
+ return FS.toPath(val);
+ }
+
+ // Attempt to find path relative to content in jetty's start.jar
+ // based on lookup for the Main class (from jetty's start.jar)
+ String classRef = "org/eclipse/jetty/start/Main.class";
+ URL jarfile = this.getClass().getClassLoader().getResource(classRef);
+ if (jarfile != null)
+ {
+ Matcher m = Pattern.compile("jar:(file:.*)!/" + classRef).matcher(jarfile.toString());
+ if (m.matches())
+ {
+ // ${jetty.home} is relative to found BaseHome class
+ try
+ {
+ return new File(new URI(m.group(1))).getParentFile().toPath();
+ }
+ catch (URISyntaxException e)
+ {
+ throw new UsageException(UsageException.ERR_UNKNOWN,e);
+ }
+ }
+ }
+
+ // Lastly, fall back to ${user.dir} default
+ Path home = FS.toPath(System.getProperty("user.dir","."));
+ setProperty(BaseHome.JETTY_HOME,home.toString(),ORIGIN_INTERNAL_FALLBACK);
+ return home;
+ }
+
+ private boolean isEmpty(String value)
+ {
+ if (value == null)
+ {
+ return true;
+ }
+ int len = value.length();
+ for (int i = 0; i < len; i++)
+ {
+ int c = value.codePointAt(i);
+ if (!Character.isWhitespace(c))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ CommandLineConfigSource other = (CommandLineConfigSource)obj;
+ if (args == null)
+ {
+ if (other.args != null)
+ {
+ return false;
+ }
+ }
+ else if (!args.equals(other.args))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public List<String> getArgs()
+ {
+ return args;
+ }
+
+ public Path getBasePath()
+ {
+ return basePath;
+ }
+
+ public Path getHomePath()
+ {
+ return homePath;
+ }
+
+ @Override
+ public String getId()
+ {
+ return ORIGIN_CMD_LINE;
+ }
+
+ @Override
+ public String getProperty(String key)
+ {
+ return props.getString(key);
+ }
+
+ @Override
+ public Props getProps()
+ {
+ return props;
+ }
+
+ @Override
+ public int getWeight()
+ {
+ return -1; // default value for command line
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = (prime * result) + ((args == null)?0:args.hashCode());
+ return result;
+ }
+
+ public void setProperty(String key, String value, String origin)
+ {
+ this.props.setProperty(key,value,origin);
+ }
+
+ public void setSystemProperty(String key, String value)
+ {
+ this.props.setSystemProperty(key,value);
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("%s[%s,args.length=%d]",this.getClass().getSimpleName(),getId(),getArgs().size());
+ }
+}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/config/ConfigSource.java b/jetty-start/src/main/java/org/eclipse/jetty/start/config/ConfigSource.java
new file mode 100644
index 0000000..499013f
--- /dev/null
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/config/ConfigSource.java
@@ -0,0 +1,76 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.config;
+
+import java.util.List;
+
+import org.eclipse.jetty.start.Props;
+
+/**
+ * A Configuration Source
+ */
+public interface ConfigSource
+{
+ /**
+ * The identifier for this source.
+ * <p>
+ * Used in end-user display of the source.
+ *
+ * @return the configuration source identifier.
+ */
+ public String getId();
+
+ /**
+ * The weight of this source, used for proper ordering of the config source search order.
+ * <p>
+ * Recommended Weights:
+ * <pre>
+ * -1 = the command line
+ * 0 = the ${jetty.base} source
+ * [1..n] = extra-start-dir entries from command line
+ * [n+1..n] = extra-start-dir entries from start.ini (or start.d/*.ini)
+ * 9999999 = the ${jetty.home} source
+ * </pre>
+ *
+ * @return the weight of the config source. (lower value is more important)
+ */
+ public int getWeight();
+
+ /**
+ * The list of Arguments for this ConfigSource
+ *
+ * @return the list of Arguments for this ConfigSource
+ */
+ public List<String> getArgs();
+
+ /**
+ * The properties for this ConfigSource
+ *
+ * @return the properties for this ConfigSource
+ */
+ public Props getProps();
+
+ /**
+ * Return the value of the specified property.
+ *
+ * @param key the key to lookup
+ * @return the value of the property, or null if not found
+ */
+ public String getProperty(String key);
+}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/config/ConfigSources.java b/jetty-start/src/main/java/org/eclipse/jetty/start/config/ConfigSources.java
new file mode 100644
index 0000000..5f5843e
--- /dev/null
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/config/ConfigSources.java
@@ -0,0 +1,163 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.config;
+
+import static org.eclipse.jetty.start.UsageException.*;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.eclipse.jetty.start.FS;
+import org.eclipse.jetty.start.Props;
+import org.eclipse.jetty.start.Props.Prop;
+import org.eclipse.jetty.start.UsageException;
+
+/**
+ * Weighted List of ConfigSources.
+ * <p>
+ */
+public class ConfigSources implements Iterable<ConfigSource>
+{
+ private static class WeightedConfigSourceComparator implements Comparator<ConfigSource>
+ {
+ @Override
+ public int compare(ConfigSource o1, ConfigSource o2)
+ {
+ return o1.getWeight() - o2.getWeight();
+ }
+ }
+
+ private LinkedList<ConfigSource> sources = new LinkedList<>();
+ private Props props = new Props();
+ private AtomicInteger xtraSourceWeight = new AtomicInteger(1);
+
+ public void add(ConfigSource source) throws IOException
+ {
+ if (sources.contains(source))
+ {
+ // TODO: needs a better/more clear error message
+ throw new UsageException(ERR_BAD_ARG,"Duplicate Configuration Source Reference: " + source);
+ }
+ sources.add(source);
+
+ Collections.sort(sources,new WeightedConfigSourceComparator());
+
+ updateProps();
+
+ // look for --extra-start-dir entries
+ for (String arg : source.getArgs())
+ {
+ if (arg.startsWith("--extra-start-dir"))
+ {
+ String ref = getValue(arg);
+ String dirName = props.expand(ref);
+ Path dir = FS.toPath(dirName);
+ DirConfigSource dirsource = new DirConfigSource(ref,dir,xtraSourceWeight.incrementAndGet(),true);
+ add(dirsource);
+ }
+ }
+ }
+
+ public CommandLineConfigSource getCommandLineSource()
+ {
+ for (ConfigSource source : sources)
+ {
+ if (source instanceof CommandLineConfigSource)
+ {
+ return (CommandLineConfigSource)source;
+ }
+ }
+ return null;
+ }
+
+ public Prop getProp(String key)
+ {
+ return props.getProp(key);
+ }
+
+ public Props getProps()
+ {
+ return props;
+ }
+
+ private String getValue(String arg)
+ {
+ int idx = arg.indexOf('=');
+ if (idx == (-1))
+ {
+ throw new UsageException(ERR_BAD_ARG,"Argument is missing a required value: %s",arg);
+ }
+ String value = arg.substring(idx + 1).trim();
+ if (value.length() <= 0)
+ {
+ throw new UsageException(ERR_BAD_ARG,"Argument is missing a required value: %s",arg);
+ }
+ return value;
+ }
+
+ @Override
+ public Iterator<ConfigSource> iterator()
+ {
+ return sources.iterator();
+ }
+
+ public ListIterator<ConfigSource> reverseListIterator()
+ {
+ return sources.listIterator(sources.size());
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder str = new StringBuilder();
+ str.append(this.getClass().getSimpleName());
+ str.append('[');
+ boolean delim = false;
+ for (ConfigSource source : sources)
+ {
+ if (delim)
+ {
+ str.append(',');
+ }
+ str.append(source.getId());
+ delim = true;
+ }
+ str.append(']');
+ return str.toString();
+ }
+
+ private void updateProps()
+ {
+ props.reset();
+
+ // add all properties from config sources (in reverse order)
+ ListIterator<ConfigSource> iter = sources.listIterator(sources.size());
+ while (iter.hasPrevious())
+ {
+ ConfigSource source = iter.previous();
+ props.addAll(source.getProps());
+ }
+ }
+}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/config/DirConfigSource.java b/jetty-start/src/main/java/org/eclipse/jetty/start/config/DirConfigSource.java
new file mode 100644
index 0000000..b3a818c
--- /dev/null
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/config/DirConfigSource.java
@@ -0,0 +1,255 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.config;
+
+import static org.eclipse.jetty.start.UsageException.*;
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jetty.start.FS;
+import org.eclipse.jetty.start.NaturalSort;
+import org.eclipse.jetty.start.PathMatchers;
+import org.eclipse.jetty.start.Props;
+import org.eclipse.jetty.start.UsageException;
+import org.eclipse.jetty.start.Props.Prop;
+import org.eclipse.jetty.start.StartIni;
+import org.eclipse.jetty.start.StartLog;
+
+/**
+ * A Directory based {@link ConfigSource}.
+ * <p>
+ * Such as <code>${jetty.base}</code> or and <code>--extra-start-dir=[path]</code> sources.
+ */
+public class DirConfigSource implements ConfigSource
+{
+ private static final List<String> BANNED_ARGS;
+
+ static
+ {
+ // Arguments that are not allowed to be in start.ini or start.d/{name}.ini files
+ BANNED_ARGS = new ArrayList<>();
+ BANNED_ARGS.add("--help");
+ BANNED_ARGS.add("-?");
+ BANNED_ARGS.add("--stop");
+ BANNED_ARGS.add("--dry-run");
+ BANNED_ARGS.add("--exec-print");
+ BANNED_ARGS.add("--list-config");
+ BANNED_ARGS.add("--list-classpath");
+ BANNED_ARGS.add("--list-modules");
+ BANNED_ARGS.add("--write-module-graph");
+ BANNED_ARGS.add("--version");
+ BANNED_ARGS.add("-v");
+ BANNED_ARGS.add("--download");
+ BANNED_ARGS.add("--create-files");
+ BANNED_ARGS.add("--add-to-startd");
+ BANNED_ARGS.add("--add-to-start");
+ }
+
+ private final String id;
+ private final Path dir;
+ private final int weight;
+ private final List<String> args;
+ private final Props props;
+
+ /**
+ * Create DirConfigSource with specified identifier and directory.
+ *
+ * @param id
+ * the identifier for this {@link ConfigSource}
+ * @param dir
+ * the directory for this {@link ConfigSource}
+ * @param weight
+ * the configuration weight (used for search order)
+ * @param canHaveArgs
+ * true if this directory can have start.ini or start.d entries. (false for directories like ${jetty.home}, for example)
+ * @throws IOException
+ * if unable to load the configuration args
+ */
+ public DirConfigSource(String id, Path dir, int weight, boolean canHaveArgs) throws IOException
+ {
+ this.id = id;
+ this.dir = dir.toAbsolutePath();
+ this.weight = weight;
+ this.props = new Props();
+
+ this.args = new ArrayList<>();
+
+ if (canHaveArgs)
+ {
+ Path iniFile = dir.resolve("start.ini");
+ if (FS.canReadFile(iniFile))
+ {
+ StartIni ini = new StartIni(iniFile);
+ args.addAll(ini.getLines());
+ parseAllArgs(ini.getLines(),iniFile.toString());
+ }
+
+ Path startDdir = dir.resolve("start.d");
+
+ if (FS.canReadDirectory(startDdir))
+ {
+ DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>()
+ {
+ PathMatcher iniMatcher = PathMatchers.getMatcher("glob:**/start.d/*.ini");
+
+ @Override
+ public boolean accept(Path entry) throws IOException
+ {
+ return iniMatcher.matches(entry);
+ }
+ };
+
+ List<Path> paths = new ArrayList<>();
+
+ for (Path diniFile : Files.newDirectoryStream(startDdir,filter))
+ {
+ if (FS.canReadFile(diniFile))
+ {
+ paths.add(diniFile);
+ }
+ }
+
+ Collections.sort(paths,new NaturalSort.Paths());
+
+ for (Path diniFile : paths)
+ {
+ StartLog.debug("Reading %s/start.d/%s - %s",id,diniFile.getFileName(),diniFile);
+ StartIni ini = new StartIni(diniFile);
+ args.addAll(ini.getLines());
+ parseAllArgs(ini.getLines(),diniFile.toString());
+ }
+ }
+ }
+ }
+
+ private void parseAllArgs(List<String> lines, String origin)
+ {
+ for (String line : lines)
+ {
+ String arg = line;
+ int idx = line.indexOf('=');
+ if (idx > 0)
+ {
+ arg = line.substring(0,idx);
+ }
+ if (BANNED_ARGS.contains(arg))
+ {
+ throw new UsageException(ERR_BAD_ARG,"%s not allowed in %s",arg,origin);
+ }
+ this.props.addPossibleProperty(line,origin);
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ DirConfigSource other = (DirConfigSource)obj;
+ if (dir == null)
+ {
+ if (other.dir != null)
+ {
+ return false;
+ }
+ }
+ else if (!dir.equals(other.dir))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public List<String> getArgs()
+ {
+ return args;
+ }
+
+ public Path getDir()
+ {
+ return dir;
+ }
+
+ @Override
+ public String getId()
+ {
+ return id;
+ }
+
+ @Override
+ public String getProperty(String key)
+ {
+ Prop prop = props.getProp(key,false);
+ if (prop == null)
+ {
+ return null;
+ }
+ return prop.value;
+ }
+
+ @Override
+ public Props getProps()
+ {
+ return props;
+ }
+
+ @Override
+ public int getWeight()
+ {
+ return weight;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = (prime * result) + ((dir == null)?0:dir.hashCode());
+ return result;
+ }
+
+ public boolean isPropertyBased()
+ {
+ return id.contains("${");
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("%s[%s,%s,args.length=%d]",this.getClass().getSimpleName(),id,dir,getArgs().size());
+ }
+}
diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java b/jetty-start/src/main/java/org/eclipse/jetty/start/config/JettyBaseConfigSource.java
similarity index 61%
copy from jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java
copy to jetty-start/src/main/java/org/eclipse/jetty/start/config/JettyBaseConfigSource.java
index 50a1e5b..ebac601 100644
--- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/config/JettyBaseConfigSource.java
@@ -16,21 +16,21 @@
// ========================================================================
//
-package org.eclipse.jetty.spdy.client;
+package org.eclipse.jetty.start.config;
-import org.eclipse.jetty.io.ClientConnectionFactory;
+import java.io.IOException;
+import java.nio.file.Path;
-public abstract class NegotiatingClientConnectionFactory implements ClientConnectionFactory
+/**
+ * ${jetty.base} specific ConfigSource
+ */
+public class JettyBaseConfigSource extends DirConfigSource
{
- private final ClientConnectionFactory connectionFactory;
-
- protected NegotiatingClientConnectionFactory(ClientConnectionFactory connectionFactory)
+ // Standard weight for ${jetty.base}, so that it comes after command line, and before everything else
+ private final static int WEIGHT = 0;
+
+ public JettyBaseConfigSource(Path dir) throws IOException
{
- this.connectionFactory = connectionFactory;
- }
-
- public ClientConnectionFactory getClientConnectionFactory()
- {
- return connectionFactory;
+ super("${jetty.base}",dir,WEIGHT,true);
}
}
diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java b/jetty-start/src/main/java/org/eclipse/jetty/start/config/JettyHomeConfigSource.java
similarity index 61%
copy from jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java
copy to jetty-start/src/main/java/org/eclipse/jetty/start/config/JettyHomeConfigSource.java
index 50a1e5b..8ebe0bb 100644
--- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/NegotiatingClientConnectionFactory.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/config/JettyHomeConfigSource.java
@@ -16,21 +16,21 @@
// ========================================================================
//
-package org.eclipse.jetty.spdy.client;
+package org.eclipse.jetty.start.config;
-import org.eclipse.jetty.io.ClientConnectionFactory;
+import java.io.IOException;
+import java.nio.file.Path;
-public abstract class NegotiatingClientConnectionFactory implements ClientConnectionFactory
+/**
+ * ${jetty.home} specific ConfigSource
+ */
+public class JettyHomeConfigSource extends DirConfigSource
{
- private final ClientConnectionFactory connectionFactory;
+ // Standard weight for ${jetty.home}, so that it comes after everything else
+ private final static int WEIGHT = 9999999;
- protected NegotiatingClientConnectionFactory(ClientConnectionFactory connectionFactory)
+ public JettyHomeConfigSource(Path dir) throws IOException
{
- this.connectionFactory = connectionFactory;
- }
-
- public ClientConnectionFactory getClientConnectionFactory()
- {
- return connectionFactory;
+ super("${jetty.home}",dir,WEIGHT,false);
}
}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/BaseHomeTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/BaseHomeTest.java
index ef3ac68..861972c 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/BaseHomeTest.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/BaseHomeTest.java
@@ -22,9 +22,13 @@
import java.io.File;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
+import org.eclipse.jetty.start.config.ConfigSources;
+import org.eclipse.jetty.start.config.JettyBaseConfigSource;
+import org.eclipse.jetty.start.config.JettyHomeConfigSource;
import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.junit.Assert;
@@ -32,7 +36,55 @@
public class BaseHomeTest
{
- private void assertFileList(BaseHome hb, String message, List<String> expected, List<File> files)
+ public static void assertPathList(BaseHome hb, String message, List<String> expected, PathFinder finder)
+ {
+ List<String> actual = new ArrayList<>();
+ for (Path path : finder.getHits())
+ {
+ actual.add(hb.toShortForm(path.toFile()));
+ }
+
+ if (actual.size() != expected.size())
+ {
+ System.out.printf("Actual Path(s): %,d hits%n",actual.size());
+ for (String path : actual)
+ {
+ System.out.printf(" %s%n",path);
+ }
+ System.out.printf("Expected Path(s): %,d entries%n",expected.size());
+ for (String path : expected)
+ {
+ System.out.printf(" %s%n",path);
+ }
+ }
+ Assert.assertThat(message + ": " + Main.join(actual,", "),actual,containsInAnyOrder(expected.toArray()));
+ }
+
+ public static void assertPathList(BaseHome hb, String message, List<String> expected, List<Path> paths)
+ {
+ List<String> actual = new ArrayList<>();
+ for (Path path : paths)
+ {
+ actual.add(hb.toShortForm(path.toFile()));
+ }
+
+ if (actual.size() != expected.size())
+ {
+ System.out.printf("Actual Path(s): %,d hits%n",actual.size());
+ for (String path : actual)
+ {
+ System.out.printf(" %s%n",path);
+ }
+ System.out.printf("Expected Path(s): %,d entries%n",expected.size());
+ for (String path : expected)
+ {
+ System.out.printf(" %s%n",path);
+ }
+ }
+ Assert.assertThat(message + ": " + Main.join(actual,", "),actual,containsInAnyOrder(expected.toArray()));
+ }
+
+ public static void assertFileList(BaseHome hb, String message, List<String> expected, List<File> files)
{
List<String> actual = new ArrayList<>();
for (File file : files)
@@ -42,39 +94,34 @@
Assert.assertThat(message + ": " + Main.join(actual,", "),actual,containsInAnyOrder(expected.toArray()));
}
- private void toOsSeparators(List<String> expected)
- {
- for (int i = 0; i < expected.size(); i++)
- {
- String fixed = FS.separators(expected.get(i));
- expected.set(i,fixed);
- }
- }
-
@Test
- public void testGetFile_OnlyHome() throws IOException
+ public void testGetPath_OnlyHome() throws IOException
{
File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home");
- File baseDir = null;
+
+ ConfigSources config = new ConfigSources();
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
- BaseHome hb = new BaseHome(homeDir,baseDir);
- File startIni = hb.getFile("/start.ini");
+ BaseHome hb = new BaseHome(config);
+ Path startIni = hb.getPath("start.ini");
String ref = hb.toShortForm(startIni);
Assert.assertThat("Reference",ref,startsWith("${jetty.home}"));
- String contents = IO.readToString(startIni);
+ String contents = IO.readToString(startIni.toFile());
Assert.assertThat("Contents",contents,containsString("Home Ini"));
}
@Test
- public void testListFiles_OnlyHome() throws IOException
+ public void testGetPaths_OnlyHome() throws IOException
{
File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home");
- File baseDir = null;
- BaseHome hb = new BaseHome(homeDir,baseDir);
- List<File> files = hb.listFiles("/start.d");
+ ConfigSources config = new ConfigSources();
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
+
+ BaseHome hb = new BaseHome(config);
+ List<Path> paths = hb.getPaths("start.d/*");
List<String> expected = new ArrayList<>();
expected.add("${jetty.home}/start.d/jmx.ini");
@@ -82,19 +129,21 @@
expected.add("${jetty.home}/start.d/jsp.ini");
expected.add("${jetty.home}/start.d/logging.ini");
expected.add("${jetty.home}/start.d/ssl.ini");
- toOsSeparators(expected);
+ FSTest.toOsSeparators(expected);
- assertFileList(hb,"Files found",expected,files);
+ assertPathList(hb,"Paths found",expected,paths);
}
@Test
- public void testListFiles_Filtered_OnlyHome() throws IOException
+ public void testGetPaths_OnlyHome_InisOnly() throws IOException
{
File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home");
- File baseDir = null;
- BaseHome hb = new BaseHome(homeDir,baseDir);
- List<File> files = hb.listFiles("/start.d",new FS.IniFilter());
+ ConfigSources config = new ConfigSources();
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
+
+ BaseHome hb = new BaseHome(config);
+ List<Path> paths = hb.getPaths("start.d/*.ini");
List<String> expected = new ArrayList<>();
expected.add("${jetty.home}/start.d/jmx.ini");
@@ -102,19 +151,23 @@
expected.add("${jetty.home}/start.d/jsp.ini");
expected.add("${jetty.home}/start.d/logging.ini");
expected.add("${jetty.home}/start.d/ssl.ini");
- toOsSeparators(expected);
+ FSTest.toOsSeparators(expected);
- assertFileList(hb,"Files found",expected,files);
+ assertPathList(hb,"Paths found",expected,paths);
}
@Test
- public void testListFiles_Both() throws IOException
+ public void testGetPaths_Both() throws IOException
{
File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home");
File baseDir = MavenTestingUtils.getTestResourceDir("hb.1/base");
- BaseHome hb = new BaseHome(homeDir,baseDir);
- List<File> files = hb.listFiles("/start.d");
+ ConfigSources config = new ConfigSources();
+ config.add(new JettyBaseConfigSource(baseDir.toPath()));
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
+
+ BaseHome hb = new BaseHome(config);
+ List<Path> paths = hb.getPaths("start.d/*.ini");
List<String> expected = new ArrayList<>();
expected.add("${jetty.base}/start.d/jmx.ini");
@@ -123,9 +176,9 @@
expected.add("${jetty.base}/start.d/logging.ini");
expected.add("${jetty.home}/start.d/ssl.ini");
expected.add("${jetty.base}/start.d/myapp.ini");
- toOsSeparators(expected);
+ FSTest.toOsSeparators(expected);
- assertFileList(hb,"Files found",expected,files);
+ assertPathList(hb,"Paths found",expected,paths);
}
@Test
@@ -137,18 +190,22 @@
}
@Test
- public void testGetFile_Both() throws IOException
+ public void testGetPath_Both() throws IOException
{
File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home");
File baseDir = MavenTestingUtils.getTestResourceDir("hb.1/base");
- BaseHome hb = new BaseHome(homeDir,baseDir);
- File startIni = hb.getFile("/start.ini");
+ ConfigSources config = new ConfigSources();
+ config.add(new JettyBaseConfigSource(baseDir.toPath()));
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
+
+ BaseHome hb = new BaseHome(config);
+ Path startIni = hb.getPath("start.ini");
String ref = hb.toShortForm(startIni);
Assert.assertThat("Reference",ref,startsWith("${jetty.base}"));
- String contents = IO.readToString(startIni);
+ String contents = IO.readToString(startIni.toFile());
Assert.assertThat("Contents",contents,containsString("Base Ini"));
}
}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/ConfigurationAssert.java b/jetty-start/src/test/java/org/eclipse/jetty/start/ConfigurationAssert.java
index f3ba3a8..ced1889 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/ConfigurationAssert.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/ConfigurationAssert.java
@@ -25,6 +25,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@@ -52,7 +53,7 @@
{
File testResourcesDir = MavenTestingUtils.getTestResourcesDir();
File file = MavenTestingUtils.getTestResourceFile(filename);
- TextFile textFile = new TextFile(file);
+ TextFile textFile = new TextFile(file.toPath());
// Validate XMLs (order is important)
List<String> expectedXmls = new ArrayList<>();
@@ -64,7 +65,7 @@
}
}
List<String> actualXmls = new ArrayList<>();
- for (File xml : args.getXmlFiles())
+ for (Path xml : args.getXmlFiles())
{
actualXmls.add(shorten(baseHome,xml,testResourcesDir));
}
@@ -82,7 +83,7 @@
List<String> actualLibs = new ArrayList<>();
for (File path : args.getClasspath())
{
- actualLibs.add(shorten(baseHome,path,testResourcesDir));
+ actualLibs.add(shorten(baseHome,path.toPath(),testResourcesDir));
}
assertContainsUnordered("Libs",expectedLibs,actualLibs);
@@ -99,7 +100,8 @@
for (Prop prop : args.getProperties())
{
String name = prop.key;
- if ("jetty.home".equals(name) || "jetty.base".equals(name) || prop.origin.equals(Props.ORIGIN_SYSPROP))
+ if ("jetty.home".equals(name) || "jetty.base".equals(name) ||
+ "user.dir".equals(name) || prop.origin.equals(Props.ORIGIN_SYSPROP))
{
// strip these out from assertion, to make assertions easier.
continue;
@@ -147,7 +149,7 @@
assertContainsUnordered("Files/Dirs",expectedFiles,actualFiles);
}
- private static String shorten(BaseHome baseHome, File path, File testResourcesDir)
+ private static String shorten(BaseHome baseHome, Path path, File testResourcesDir)
{
String value = baseHome.toShortForm(path);
if (value.startsWith(testResourcesDir.getAbsolutePath()))
@@ -206,7 +208,7 @@
}
}
- private static void assertOrdered(String msg, List<String> expectedList, List<String> actualList)
+ public static void assertOrdered(String msg, List<String> expectedList, List<String> actualList)
{
// same size?
boolean mismatch = expectedList.size() != actualList.size();
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/ExtraStartTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/ExtraStartTest.java
new file mode 100644
index 0000000..0b41045
--- /dev/null
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/ExtraStartTest.java
@@ -0,0 +1,559 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jetty.start.Props.Prop;
+import org.eclipse.jetty.start.config.ConfigSource;
+import org.eclipse.jetty.start.config.ConfigSources;
+import org.eclipse.jetty.start.config.DirConfigSource;
+import org.eclipse.jetty.toolchain.test.FS;
+import org.eclipse.jetty.toolchain.test.TestingDir;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class ExtraStartTest
+{
+ private static class MainResult
+ {
+ private Main main;
+ private StartArgs args;
+
+ public void assertSearchOrder(List<String> expectedSearchOrder)
+ {
+ ConfigSources sources = main.getBaseHome().getConfigSources();
+ List<String> actualOrder = new ArrayList<>();
+ for (ConfigSource source : sources)
+ {
+ if (source instanceof DirConfigSource)
+ {
+ actualOrder.add(source.getId());
+ }
+ }
+ ConfigurationAssert.assertOrdered("Search Order",expectedSearchOrder,actualOrder);
+ }
+
+ public void assertProperty(String key, String expectedValue)
+ {
+ Prop prop = args.getProperties().getProp(key);
+ String prefix = "Prop[" + key + "]";
+ Assert.assertThat(prefix + " should have a value",prop,notNullValue());
+ Assert.assertThat(prefix + " value",prop.value,is(expectedValue));
+ }
+ }
+
+ @Rule
+ public TestingDir testdir = new TestingDir();
+
+ private MainResult runMain(File baseDir, File homeDir, String... cmdLineArgs) throws Exception
+ {
+ MainResult ret = new MainResult();
+ ret.main = new Main();
+ List<String> cmdLine = new ArrayList<>();
+ cmdLine.add("jetty.home=" + homeDir.getAbsolutePath());
+ cmdLine.add("jetty.base=" + baseDir.getAbsolutePath());
+ // cmdLine.add("--debug");
+ for (String arg : cmdLineArgs)
+ {
+ cmdLine.add(arg);
+ }
+ ret.args = ret.main.processCommandLine(cmdLine);
+ return ret;
+ }
+
+ @Test
+ public void testNoExtras() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1");
+
+ // Simple command line - no reference to extra-start-dirs
+ MainResult result = runMain(base,home);
+
+ List<String> expectedSearchOrder = new ArrayList<>();
+ expectedSearchOrder.add("${jetty.base}");
+ expectedSearchOrder.add("${jetty.home}");
+ result.assertSearchOrder(expectedSearchOrder);
+
+ result.assertProperty("jetty.host","127.0.0.1");
+ }
+
+ @Test
+ public void testCommandLine_1Extra() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini","jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1");
+
+ // Simple command line reference to extra-start-dir
+ MainResult result = runMain(base,home,
+ // direct reference via path
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ List<String> expectedSearchOrder = new ArrayList<>();
+ expectedSearchOrder.add("${jetty.base}");
+ expectedSearchOrder.add(common.getAbsolutePath());
+ expectedSearchOrder.add("${jetty.home}");
+ result.assertSearchOrder(expectedSearchOrder);
+
+ result.assertProperty("jetty.host","127.0.0.1");
+ result.assertProperty("jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testCommandLine_1Extra_FromSimpleProp() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini","jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1");
+
+ // Simple command line reference to extra-start-dir via property (also on command line)
+ MainResult result = runMain(base,home,
+ // property
+ "my.common=" + common.getAbsolutePath(),
+ // reference via property
+ "--extra-start-dir=${my.common}");
+
+ List<String> expectedSearchOrder = new ArrayList<>();
+ expectedSearchOrder.add("${jetty.base}");
+ expectedSearchOrder.add("${my.common}"); // should see property use
+ expectedSearchOrder.add("${jetty.home}");
+ result.assertSearchOrder(expectedSearchOrder);
+
+ result.assertProperty("jetty.host","127.0.0.1");
+ result.assertProperty("jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testCommandLine_1Extra_FromPropPrefix() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create opt
+ File opt = testdir.getFile("opt");
+ FS.ensureEmpty(opt);
+
+ // Create common
+ File common = new File(opt,"common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini","jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1");
+
+ String dirRef = "${my.opt}" + File.separator + "common";
+
+ // Simple command line reference to extra-start-dir via property (also on command line)
+ MainResult result = runMain(base,home,
+ // property to 'opt' dir
+ "my.opt=" + opt.getAbsolutePath(),
+ // reference via property prefix
+ "--extra-start-dir=" + dirRef);
+
+ List<String> expectedSearchOrder = new ArrayList<>();
+ expectedSearchOrder.add("${jetty.base}");
+ expectedSearchOrder.add(dirRef); // should use property
+ expectedSearchOrder.add("${jetty.home}");
+ result.assertSearchOrder(expectedSearchOrder);
+
+ result.assertProperty("jetty.host","127.0.0.1");
+ result.assertProperty("jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testCommandLine_1Extra_FromCompoundProp() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create opt
+ File opt = testdir.getFile("opt");
+ FS.ensureEmpty(opt);
+
+ // Create common
+ File common = new File(opt,"common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini","jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1");
+
+ String dirRef = "${my.opt}" + File.separator + "${my.dir}";
+
+ // Simple command line reference to extra-start-dir via property (also on command line)
+ MainResult result = runMain(base,home,
+ // property to 'opt' dir
+ "my.opt=" + opt.getAbsolutePath(),
+ // property to commmon dir name
+ "my.dir=common",
+ // reference via property prefix
+ "--extra-start-dir=" + dirRef);
+
+ List<String> expectedSearchOrder = new ArrayList<>();
+ expectedSearchOrder.add("${jetty.base}");
+ expectedSearchOrder.add(dirRef); // should use property
+ expectedSearchOrder.add("${jetty.home}");
+ result.assertSearchOrder(expectedSearchOrder);
+
+ result.assertProperty("jetty.host","127.0.0.1");
+ result.assertProperty("jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testRefCommon() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini","jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ MainResult result = runMain(base,home);
+
+ List<String> expectedSearchOrder = new ArrayList<>();
+ expectedSearchOrder.add("${jetty.base}");
+ expectedSearchOrder.add(common.getAbsolutePath());
+ expectedSearchOrder.add("${jetty.home}");
+ result.assertSearchOrder(expectedSearchOrder);
+
+ result.assertProperty("jetty.host","127.0.0.1");
+ result.assertProperty("jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testRefCommonAndCorp() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini","jetty.port=8080");
+
+ // Create corp
+ File corp = testdir.getFile("corp");
+ FS.ensureEmpty(corp);
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath(), //
+ "--extra-start-dir=" + corp.getAbsolutePath());
+
+ MainResult result = runMain(base,home);
+
+ List<String> expectedSearchOrder = new ArrayList<>();
+ expectedSearchOrder.add("${jetty.base}");
+ expectedSearchOrder.add(common.getAbsolutePath());
+ expectedSearchOrder.add(corp.getAbsolutePath());
+ expectedSearchOrder.add("${jetty.home}");
+ result.assertSearchOrder(expectedSearchOrder);
+
+ result.assertProperty("jetty.host","127.0.0.1");
+ result.assertProperty("jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testRefCommonRefCorp() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create corp
+ File corp = testdir.getFile("corp");
+ FS.ensureEmpty(corp);
+ TestEnv.makeFile(corp,"start.ini","jetty.port=9090");
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini", //
+ "--extra-start-dir=" + corp.getAbsolutePath(), //
+ "jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ MainResult result = runMain(base,home);
+
+ List<String> expectedSearchOrder = new ArrayList<>();
+ expectedSearchOrder.add("${jetty.base}");
+ expectedSearchOrder.add(common.getAbsolutePath());
+ expectedSearchOrder.add(corp.getAbsolutePath());
+ expectedSearchOrder.add("${jetty.home}");
+ result.assertSearchOrder(expectedSearchOrder);
+
+ result.assertProperty("jetty.host","127.0.0.1");
+ result.assertProperty("jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testRefCommonRefCorp_FromSimpleProps() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create corp
+ File corp = testdir.getFile("corp");
+ FS.ensureEmpty(corp);
+ TestEnv.makeFile(corp,"start.ini", //
+ "jetty.port=9090");
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini", //
+ "my.corp=" + corp.getAbsolutePath(), //
+ "--extra-start-dir=${my.corp}", //
+ "jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "my.common=" + common.getAbsolutePath(), //
+ "--extra-start-dir=${my.common}");
+
+ MainResult result = runMain(base,home);
+
+ List<String> expectedSearchOrder = new ArrayList<>();
+ expectedSearchOrder.add("${jetty.base}");
+ expectedSearchOrder.add("${my.common}");
+ expectedSearchOrder.add("${my.corp}");
+ expectedSearchOrder.add("${jetty.home}");
+ result.assertSearchOrder(expectedSearchOrder);
+
+ result.assertProperty("jetty.host","127.0.0.1");
+ result.assertProperty("jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testRefCommonRefCorp_CmdLineRef() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create devops
+ File devops = testdir.getFile("devops");
+ FS.ensureEmpty(devops);
+ TestEnv.makeFile(devops,"start.ini", //
+ "--module=logging", //
+ "jetty.port=2222");
+
+ // Create corp
+ File corp = testdir.getFile("corp");
+ FS.ensureEmpty(corp);
+ TestEnv.makeFile(corp,"start.ini", //
+ "jetty.port=9090");
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini", //
+ "--extra-start-dir=" + corp.getAbsolutePath(), //
+ "jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ MainResult result = runMain(base,home,
+ // command line provided extra-start-dir ref
+ "--extra-start-dir=" + devops.getAbsolutePath());
+
+ List<String> expectedSearchOrder = new ArrayList<>();
+ expectedSearchOrder.add("${jetty.base}");
+ expectedSearchOrder.add(devops.getAbsolutePath());
+ expectedSearchOrder.add(common.getAbsolutePath());
+ expectedSearchOrder.add(corp.getAbsolutePath());
+ expectedSearchOrder.add("${jetty.home}");
+ result.assertSearchOrder(expectedSearchOrder);
+
+ result.assertProperty("jetty.host","127.0.0.1");
+ result.assertProperty("jetty.port","2222"); // from 'devops'
+ }
+
+ @Test
+ public void testRefCommonRefCorp_CmdLineProp() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create corp
+ File corp = testdir.getFile("corp");
+ FS.ensureEmpty(corp);
+ TestEnv.makeFile(corp,"start.ini", //
+ "jetty.port=9090");
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini", //
+ "--extra-start-dir=" + corp.getAbsolutePath(), //
+ "jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ MainResult result = runMain(base,home,
+ // command line property should override all others
+ "jetty.port=7070");
+
+ List<String> expectedSearchOrder = new ArrayList<>();
+ expectedSearchOrder.add("${jetty.base}");
+ expectedSearchOrder.add(common.getAbsolutePath());
+ expectedSearchOrder.add(corp.getAbsolutePath());
+ expectedSearchOrder.add("${jetty.home}");
+ result.assertSearchOrder(expectedSearchOrder);
+
+ result.assertProperty("jetty.host","127.0.0.1");
+ result.assertProperty("jetty.port","7070"); // from command line
+ }
+
+ @Test
+ public void testBadDoubleRef() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+
+ // Create corp
+ File corp = testdir.getFile("corp");
+ FS.ensureEmpty(corp);
+ TestEnv.makeFile(corp,"start.ini",
+ // standard property
+ "jetty.port=9090",
+ // INTENTIONAL BAD Reference (duplicate)
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ // Populate common
+ TestEnv.makeFile(common,"start.ini",
+ // standard property
+ "jetty.port=8080",
+ // reference to corp
+ "--extra-start-dir=" + corp.getAbsolutePath());
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ try
+ {
+ runMain(base,home);
+ Assert.fail("Should have thrown a UsageException");
+ }
+ catch (UsageException e)
+ {
+ Assert.assertThat("UsageException",e.getMessage(),containsString("Duplicate"));
+ }
+ }
+}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/FSTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/FSTest.java
new file mode 100644
index 0000000..4061851
--- /dev/null
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/FSTest.java
@@ -0,0 +1,62 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.io.File;
+import java.util.List;
+
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class FSTest
+{
+ @Test
+ public void testCanReadDirectory()
+ {
+ File targetDir = MavenTestingUtils.getTargetDir();
+ Assert.assertTrue("Can read dir: " + targetDir,FS.canReadDirectory(targetDir.toPath()));
+ }
+
+ @Test
+ public void testCanReadDirectory_NotDir()
+ {
+ File bogusFile = MavenTestingUtils.getTestResourceFile("bogus.xml");
+ Assert.assertFalse("Can read dir: " + bogusFile,FS.canReadDirectory(bogusFile.toPath()));
+ }
+
+ @Test
+ public void testCanReadFile()
+ {
+ File pom = MavenTestingUtils.getProjectFile("pom.xml");
+ Assert.assertTrue("Can read file: " + pom,FS.canReadFile(pom.toPath()));
+ }
+
+ /**
+ * Utility method used by other test cases
+ */
+ public static void toOsSeparators(List<String> expected)
+ {
+ for (int i = 0; i < expected.size(); i++)
+ {
+ String fixed = FS.separators(expected.get(i));
+ expected.set(i,fixed);
+ }
+ }
+}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java
index 222f760..a8003c3 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java
@@ -18,28 +18,34 @@
package org.eclipse.jetty.start;
+import static org.hamcrest.Matchers.*;
+
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class MainTest
{
- private void addUseCasesHome(List<String> cmdLineArgs)
+ @Before
+ public void clearSystemProperties()
{
- File testJettyHome = MavenTestingUtils.getTestResourceDir("usecases/home");
- cmdLineArgs.add("jetty.home=" + testJettyHome);
+ System.setProperty("jetty.home","");
+ System.setProperty("jetty.base","");
}
-
+
@Test
public void testBasicProcessing() throws Exception
{
List<String> cmdLineArgs = new ArrayList<>();
- addUseCasesHome(cmdLineArgs);
+ File testJettyHome = MavenTestingUtils.getTestResourceDir("usecases/home").getAbsoluteFile();
+ cmdLineArgs.add("user.dir=" + testJettyHome);
+ cmdLineArgs.add("jetty.home=" + testJettyHome);
cmdLineArgs.add("jetty.port=9090");
Main main = new Main();
@@ -74,7 +80,8 @@
public void testListConfig() throws Exception
{
List<String> cmdLineArgs = new ArrayList<>();
- addUseCasesHome(cmdLineArgs);
+ File testJettyHome = MavenTestingUtils.getTestResourceDir("usecases/home");
+ cmdLineArgs.add("jetty.home=" + testJettyHome);
cmdLineArgs.add("jetty.port=9090");
cmdLineArgs.add("--list-config");
// cmdLineArgs.add("--debug");
@@ -97,8 +104,10 @@
{
List<String> cmdLineArgs = new ArrayList<>();
- addUseCasesHome(cmdLineArgs);
-
+ File homePath = MavenTestingUtils.getTestResourceDir("usecases/home").getAbsoluteFile();
+ cmdLineArgs.add("jetty.home=" + homePath);
+ cmdLineArgs.add("user.dir=" + homePath);
+
// JVM args
cmdLineArgs.add("--exec");
cmdLineArgs.add("-Xms1024m");
@@ -118,7 +127,9 @@
StartArgs args = main.processCommandLine(cmdLineArgs.toArray(new String[cmdLineArgs.size()]));
BaseHome baseHome = main.getBaseHome();
- System.err.println(args);
+
+ Assert.assertThat("jetty.home", baseHome.getHome(), is(homePath.getAbsolutePath()));
+ Assert.assertThat("jetty.base", baseHome.getBase(), is(homePath.getAbsolutePath()));
ConfigurationAssert.assertConfiguration(baseHome,args,"assert-home-with-jvm.txt");
}
@@ -128,14 +139,17 @@
{
List<String> cmdLineArgs = new ArrayList<>();
- File homePath = MavenTestingUtils.getTestResourceDir("jetty home with spaces");
+ File homePath = MavenTestingUtils.getTestResourceDir("jetty home with spaces").getAbsoluteFile();
+ cmdLineArgs.add("user.dir=" + homePath);
cmdLineArgs.add("jetty.home=" + homePath);
Main main = new Main();
StartArgs args = main.processCommandLine(cmdLineArgs.toArray(new String[cmdLineArgs.size()]));
BaseHome baseHome = main.getBaseHome();
- System.err.println(args);
-
+
+ Assert.assertThat("jetty.home", baseHome.getHome(), is(homePath.getAbsolutePath()));
+ Assert.assertThat("jetty.base", baseHome.getBase(), is(homePath.getAbsolutePath()));
+
ConfigurationAssert.assertConfiguration(baseHome,args,"assert-home-with-spaces.txt");
}
}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/ModuleGraphWriterTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/ModuleGraphWriterTest.java
index 92ad503..82db04c 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/ModuleGraphWriterTest.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/ModuleGraphWriterTest.java
@@ -18,13 +18,16 @@
package org.eclipse.jetty.start;
-import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.*;
import java.io.File;
import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
+import java.nio.file.Path;
+import org.eclipse.jetty.start.config.CommandLineConfigSource;
+import org.eclipse.jetty.start.config.ConfigSources;
+import org.eclipse.jetty.start.config.JettyBaseConfigSource;
+import org.eclipse.jetty.start.config.JettyHomeConfigSource;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.Assert;
@@ -33,30 +36,39 @@
public class ModuleGraphWriterTest
{
- @SuppressWarnings("unused")
- private final static List<String> TEST_SOURCE = Collections.singletonList("<test>");
-
- private StartArgs DEFAULT_ARGS = new StartArgs(new String[]{"jetty.version=TEST"}).parseCommandLine();
-
@Rule
public TestingDir testdir = new TestingDir();
@Test
public void testGenerate_NothingEnabled() throws IOException
{
+ // Test Env
File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
File baseDir = testdir.getEmptyDir();
- BaseHome basehome = new BaseHome(homeDir,baseDir);
+ String cmdLine[] = new String[] {"jetty.version=TEST"};
+
+ // Configuration
+ CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
+ ConfigSources config = new ConfigSources();
+ config.add(cmdLineSource);
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
+ config.add(new JettyBaseConfigSource(baseDir.toPath()));
+
+ // Initialize
+ BaseHome basehome = new BaseHome(config);
+
+ StartArgs args = new StartArgs();
+ args.parse(config);
Modules modules = new Modules();
- modules.registerAll(basehome, DEFAULT_ARGS);
+ modules.registerAll(basehome, args);
modules.buildGraph();
- File outputFile = new File(baseDir,"graph.dot");
+ Path outputFile = basehome.getBasePath("graph.dot");
ModuleGraphWriter writer = new ModuleGraphWriter();
writer.write(modules,outputFile);
- Assert.assertThat("Output File Exists",outputFile.exists(),is(true));
+ Assert.assertThat("Output File Exists",FS.exists(outputFile),is(true));
}
}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/ModuleTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/ModuleTest.java
index 31b2e4d..ced2d38 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/ModuleTest.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/ModuleTest.java
@@ -18,36 +18,53 @@
package org.eclipse.jetty.start;
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.*;
import java.io.File;
import java.io.IOException;
+import org.eclipse.jetty.start.config.CommandLineConfigSource;
+import org.eclipse.jetty.start.config.ConfigSources;
+import org.eclipse.jetty.start.config.JettyBaseConfigSource;
+import org.eclipse.jetty.start.config.JettyHomeConfigSource;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.Assert;
+import org.junit.Rule;
import org.junit.Test;
public class ModuleTest
{
- private Module loadTestHomeModule(String moduleFileName) throws IOException
- {
- File file = MavenTestingUtils.getTestResourceFile("usecases/home/modules/" + moduleFileName);
- return new Module(new BaseHome(),file);
- }
-
+ @Rule
+ public TestingDir testdir = new TestingDir();
+
@Test
public void testLoadWebSocket() throws IOException
{
- Module Module = loadTestHomeModule("websocket.mod");
-
- Assert.assertThat("Module Name",Module.getName(),is("websocket"));
- Assert.assertThat("Module Parents Size",Module.getParentNames().size(),is(2));
- Assert.assertThat("Module Parents",Module.getParentNames(),containsInAnyOrder("annotations","server"));
- Assert.assertThat("Module Xmls Size",Module.getXmls().size(),is(1));
- Assert.assertThat("Module Xmls",Module.getXmls(),contains("etc/jetty-websockets.xml"));
- Assert.assertThat("Module Options Size",Module.getLibs().size(),is(1));
- Assert.assertThat("Module Options",Module.getLibs(),contains("lib/websocket/*.jar"));
+ // Test Env
+ File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
+ File baseDir = testdir.getEmptyDir();
+ String cmdLine[] = new String[] {"jetty.version=TEST"};
+
+ // Configuration
+ CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
+ ConfigSources config = new ConfigSources();
+ config.add(cmdLineSource);
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
+ config.add(new JettyBaseConfigSource(baseDir.toPath()));
+
+ // Initialize
+ BaseHome basehome = new BaseHome(config);
+
+ File file = MavenTestingUtils.getTestResourceFile("usecases/home/modules/websocket.mod");
+ Module module = new Module(basehome,file.toPath());
+
+ Assert.assertThat("Module Name",module.getName(),is("websocket"));
+ Assert.assertThat("Module Parents Size",module.getParentNames().size(),is(2));
+ Assert.assertThat("Module Parents",module.getParentNames(),containsInAnyOrder("annotations","server"));
+ Assert.assertThat("Module Xmls Size",module.getXmls().size(),is(1));
+ Assert.assertThat("Module Xmls",module.getXmls(),contains("etc/jetty-websockets.xml"));
+ Assert.assertThat("Module Options Size",module.getLibs().size(),is(1));
+ Assert.assertThat("Module Options",module.getLibs(),contains("lib/websocket/*.jar"));
}
}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java
index 27d5726..4b2fd23 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java
@@ -27,50 +27,121 @@
import java.util.Collections;
import java.util.List;
+import org.eclipse.jetty.start.config.CommandLineConfigSource;
+import org.eclipse.jetty.start.config.ConfigSources;
+import org.eclipse.jetty.start.config.JettyBaseConfigSource;
+import org.eclipse.jetty.start.config.JettyHomeConfigSource;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.Assert;
+import org.junit.Rule;
import org.junit.Test;
public class ModulesTest
{
private final static List<String> TEST_SOURCE = Collections.singletonList("<test>");
- private StartArgs DEFAULT_ARGS = new StartArgs(new String[] { "jetty.version=TEST" }).parseCommandLine();
-
+
+ @Rule
+ public TestingDir testdir = new TestingDir();
+
@Test
public void testLoadAllModules() throws IOException
{
+ // Test Env
File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
- BaseHome basehome = new BaseHome(homeDir,homeDir);
+ File baseDir = testdir.getEmptyDir();
+ String cmdLine[] = new String[] {"jetty.version=TEST"};
+
+ // Configuration
+ CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
+ ConfigSources config = new ConfigSources();
+ config.add(cmdLineSource);
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
+ config.add(new JettyBaseConfigSource(baseDir.toPath()));
+
+ // Initialize
+ BaseHome basehome = new BaseHome(config);
+
+ StartArgs args = new StartArgs();
+ args.parse(config);
+ // Test Modules
Modules modules = new Modules();
- modules.registerAll(basehome, DEFAULT_ARGS);
- Assert.assertThat("Module count",modules.count(),is(30));
+ modules.registerAll(basehome,args);
+
+ List<String> moduleNames = new ArrayList<>();
+ for (Module mod : modules)
+ {
+ // skip npn-boot in this test (as its behavior is jdk specific)
+ if (mod.getName().equals("npn-boot"))
+ {
+ continue;
+ }
+ moduleNames.add(mod.getName());
+ }
+
+ String expected[] = { "jmx", "client", "stats", "spdy", "deploy", "debug", "security", "npn", "ext", "websocket", "rewrite", "ipaccess", "xinetd",
+ "proxy", "webapp", "jndi", "lowresources", "https", "plus", "requestlog", "jsp", "monitor", "xml", "servlet", "jaas", "http", "base", "server",
+ "annotations" };
+
+ Assert.assertThat("Module count: " + moduleNames,moduleNames.size(),is(expected.length));
}
-
+
@Test
public void testEnableRegexSimple() throws IOException
{
+ // Test Env
File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
- BaseHome basehome = new BaseHome(homeDir,homeDir);
+ File baseDir = testdir.getEmptyDir();
+ String cmdLine[] = new String[] {"jetty.version=TEST"};
+
+ // Configuration
+ CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
+ ConfigSources config = new ConfigSources();
+ config.add(cmdLineSource);
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
+ config.add(new JettyBaseConfigSource(baseDir.toPath()));
+
+ // Initialize
+ BaseHome basehome = new BaseHome(config);
+
+ StartArgs args = new StartArgs();
+ args.parse(config);
+ // Test Modules
Modules modules = new Modules();
- modules.registerAll(basehome, DEFAULT_ARGS);
+ modules.registerAll(basehome,args);
modules.enable("[sj]{1}.*",TEST_SOURCE);
-
+
String expected[] = { "jmx", "stats", "spdy", "security", "jndi", "jsp", "servlet", "jaas", "server" };
-
+
Assert.assertThat("Enabled Module count",modules.resolveEnabled().size(),is(expected.length));
}
@Test
public void testResolve_ServerHttp() throws IOException
{
+ // Test Env
File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
- BaseHome basehome = new BaseHome(homeDir,homeDir);
+ File baseDir = testdir.getEmptyDir();
+ String cmdLine[] = new String[] {"jetty.version=TEST"};
+
+ // Configuration
+ CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
+ ConfigSources config = new ConfigSources();
+ config.add(cmdLineSource);
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
+ config.add(new JettyBaseConfigSource(baseDir.toPath()));
+
+ // Initialize
+ BaseHome basehome = new BaseHome(config);
+
+ StartArgs args = new StartArgs();
+ args.parse(config);
- // Register modules
+ // Test Modules
Modules modules = new Modules();
- modules.registerAll(basehome, DEFAULT_ARGS);
+ modules.registerAll(basehome,args);
modules.buildGraph();
// Enable 2 modules
@@ -108,12 +179,12 @@
List<String> actualLibs = modules.normalizeLibs(active);
Assert.assertThat("Resolved Libs: " + actualLibs,actualLibs,contains(expectedLibs.toArray()));
-
+
// Assert XML List
List<String> expectedXmls = new ArrayList<>();
expectedXmls.add("etc/jetty.xml");
expectedXmls.add("etc/jetty-http.xml");
-
+
List<String> actualXmls = modules.normalizeXmls(active);
Assert.assertThat("Resolved XMLs: " + actualXmls,actualXmls,contains(expectedXmls.toArray()));
}
@@ -121,12 +192,27 @@
@Test
public void testResolve_WebSocket() throws IOException
{
+ // Test Env
File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
- BaseHome basehome = new BaseHome(homeDir,homeDir);
+ File baseDir = testdir.getEmptyDir();
+ String cmdLine[] = new String[] {"jetty.version=TEST"};
+
+ // Configuration
+ CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
+ ConfigSources config = new ConfigSources();
+ config.add(cmdLineSource);
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
+ config.add(new JettyBaseConfigSource(baseDir.toPath()));
+
+ // Initialize
+ BaseHome basehome = new BaseHome(config);
+
+ StartArgs args = new StartArgs();
+ args.parse(config);
- // Register modules
+ // Test Modules
Modules modules = new Modules();
- modules.registerAll(basehome, DEFAULT_ARGS);
+ modules.registerAll(basehome,args);
modules.buildGraph();
// modules.dump();
@@ -136,7 +222,7 @@
// Collect active module list
List<Module> active = modules.resolveEnabled();
-
+
// Assert names are correct, and in the right order
List<String> expectedNames = new ArrayList<>();
expectedNames.add("base");
@@ -174,10 +260,10 @@
expectedLibs.add("lib/jetty-annotations-${jetty.version}.jar");
expectedLibs.add("lib/annotations/*.jar");
expectedLibs.add("lib/websocket/*.jar");
-
+
List<String> actualLibs = modules.normalizeLibs(active);
Assert.assertThat("Resolved Libs: " + actualLibs,actualLibs,contains(expectedLibs.toArray()));
-
+
// Assert XML List
List<String> expectedXmls = new ArrayList<>();
expectedXmls.add("etc/jetty.xml");
@@ -185,7 +271,7 @@
expectedXmls.add("etc/jetty-plus.xml");
expectedXmls.add("etc/jetty-annotations.xml");
expectedXmls.add("etc/jetty-websockets.xml");
-
+
List<String> actualXmls = modules.normalizeXmls(active);
Assert.assertThat("Resolved XMLs: " + actualXmls,actualXmls,contains(expectedXmls.toArray()));
}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/PathFinderTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/PathFinderTest.java
new file mode 100644
index 0000000..18b05cd
--- /dev/null
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/PathFinderTest.java
@@ -0,0 +1,88 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitOption;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.junit.Test;
+
+public class PathFinderTest
+{
+ @Test
+ public void testFindInis() throws IOException
+ {
+ File homeDir = MavenTestingUtils.getTestResourceDir("hb.1/home");
+ Path homePath = homeDir.toPath().toAbsolutePath();
+
+ PathFinder finder = new PathFinder();
+ finder.setFileMatcher("glob:**/*.ini");
+ finder.setBase(homePath);
+
+ Files.walkFileTree(homePath,EnumSet.of(FileVisitOption.FOLLOW_LINKS),30,finder);
+
+ List<String> expected = new ArrayList<>();
+ expected.add("${jetty.home}/start.d/jmx.ini");
+ expected.add("${jetty.home}/start.d/jndi.ini");
+ expected.add("${jetty.home}/start.d/jsp.ini");
+ expected.add("${jetty.home}/start.d/logging.ini");
+ expected.add("${jetty.home}/start.d/ssl.ini");
+ expected.add("${jetty.home}/start.ini");
+ FSTest.toOsSeparators(expected);
+
+ BaseHome hb = new BaseHome(new String[] { "jetty.home=" + homePath.toString() });
+ BaseHomeTest.assertPathList(hb,"Files found",expected,finder);
+ }
+
+ @Test
+ public void testFindMods() throws IOException
+ {
+ File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
+ Path homePath = homeDir.toPath().toAbsolutePath();
+
+ List<String> expected = new ArrayList<>();
+ File modulesDir = new File(homeDir,"modules");
+ for (File file : modulesDir.listFiles())
+ {
+ if (file.getName().endsWith(".mod"))
+ {
+ expected.add("${jetty.home}/modules/" + file.getName());
+ }
+ }
+ FSTest.toOsSeparators(expected);
+
+ Path modulesPath = modulesDir.toPath();
+
+ PathFinder finder = new PathFinder();
+ finder.setFileMatcher(PathMatchers.getMatcher("modules/*.mod"));
+ finder.setBase(modulesPath);
+
+ Files.walkFileTree(modulesPath,EnumSet.of(FileVisitOption.FOLLOW_LINKS),1,finder);
+
+ BaseHome hb = new BaseHome(new String[] { "jetty.home=" + homePath.toString() });
+ BaseHomeTest.assertPathList(hb,"Files found",expected,finder);
+ }
+}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/PathMatchersTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/PathMatchersTest.java
new file mode 100644
index 0000000..460f88d
--- /dev/null
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/PathMatchersTest.java
@@ -0,0 +1,105 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.nio.file.Path;
+
+import org.eclipse.jetty.toolchain.test.OS;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PathMatchersTest
+{
+ private void assertIsAbsolute(String pattern, boolean expected)
+ {
+ Assert.assertThat("isAbsolute(\"" + pattern + "\")",PathMatchers.isAbsolute(pattern),is(expected));
+ }
+
+ @Test
+ public void testIsAbsolute()
+ {
+ if (OS.IS_UNIX)
+ {
+ assertIsAbsolute("/opt/app",true);
+ assertIsAbsolute("/opt/florb",true);
+ assertIsAbsolute("/home/user/benfranklin",true);
+ assertIsAbsolute("glob:/home/user/benfranklin/*.jar",true);
+ assertIsAbsolute("glob:/**/*.jar",true);
+ assertIsAbsolute("regex:/*-[^dev].ini",true);
+ }
+
+ if (OS.IS_WINDOWS)
+ {
+ assertIsAbsolute("C:\\\\System32",true);
+ assertIsAbsolute("C:\\\\Program Files",true);
+ }
+ }
+
+ @Test
+ public void testIsNotAbsolute()
+ {
+ assertIsAbsolute("etc",false);
+ assertIsAbsolute("lib",false);
+ assertIsAbsolute("${user.dir}",false);
+ assertIsAbsolute("**/*.jar",false);
+ assertIsAbsolute("glob:*.ini",false);
+ assertIsAbsolute("regex:*-[^dev].ini",false);
+ }
+
+ private void assertSearchRoot(String pattern, String expectedSearchRoot)
+ {
+ Path actual = PathMatchers.getSearchRoot(pattern);
+ String expectedNormal = FS.separators(expectedSearchRoot);
+ Assert.assertThat(".getSearchRoot(\"" + pattern + "\")",actual.toString(),is(expectedNormal));
+ }
+
+ @Test
+ public void testGetSearchRoot()
+ {
+ if (OS.IS_UNIX)
+ {
+ // absolute first
+ assertSearchRoot("/opt/app/*.jar","/opt/app");
+ assertSearchRoot("/lib/jvm/**/jre/lib/*.jar","/lib/jvm");
+ assertSearchRoot("glob:/var/lib/*.xml","/var/lib");
+ assertSearchRoot("glob:/var/lib/*.{xml,java}","/var/lib");
+ assertSearchRoot("glob:/opt/corporate/lib-{dev,prod}/*.ini","/opt/corporate");
+ assertSearchRoot("regex:/opt/jetty/.*/lib-(dev|prod)/*.ini","/opt/jetty");
+
+ assertSearchRoot("/*.ini","/");
+ assertSearchRoot("/etc/jetty.conf","/etc");
+ assertSearchRoot("/common.conf","/");
+ }
+
+ if (OS.IS_WINDOWS)
+ {
+ // absolute patterns (complete with required windows slash escaping)
+ assertSearchRoot("C:\\\\corp\\\\lib\\\\*.jar","C:\\corp\\lib");
+ assertSearchRoot("D:\\\\lib\\\\**\\\\jre\\\\lib\\\\*.jar","C:\\lib");
+ }
+
+ // some relative paths
+ assertSearchRoot("lib/*.jar","lib");
+ assertSearchRoot("etc/jetty.xml","etc");
+ assertSearchRoot("start.ini",".");
+ assertSearchRoot("start.d/",".");
+ }
+}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/PropsTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/PropsTest.java
index b9f471f..7837764 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/PropsTest.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/PropsTest.java
@@ -91,6 +91,7 @@
assertThat(props.expand("port=8080"),is("port=8080"));
assertThat(props.expand("jdk=${java.version}"),is("jdk=" + System.getProperty("java.version")));
assertThat(props.expand("id=${name}-${version}"),is("id=jetty-9.1"));
+ assertThat(props.expand("id=${unknown}-${wibble}"),is("id=${unknown}-${wibble}"));
}
@Test
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/TestEnv.java b/jetty-start/src/test/java/org/eclipse/jetty/start/TestEnv.java
new file mode 100644
index 0000000..84659c2
--- /dev/null
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/TestEnv.java
@@ -0,0 +1,52 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import org.eclipse.jetty.toolchain.test.FS;
+import org.eclipse.jetty.toolchain.test.IO;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.eclipse.jetty.toolchain.test.OS;
+
+public class TestEnv
+{
+ public static void copyTestDir(String testResourceDir, File destDir) throws IOException
+ {
+ FS.ensureDirExists(destDir);
+ File srcDir = MavenTestingUtils.getTestResourceDir(testResourceDir);
+ IO.copyDir(srcDir,destDir);
+ }
+
+ public static void makeFile(File dir, String relFilePath, String... contents) throws IOException
+ {
+ File outputFile = new File(dir,OS.separators(relFilePath));
+ FS.ensureDirExists(outputFile.getParentFile());
+ try (FileWriter writer = new FileWriter(outputFile); PrintWriter out = new PrintWriter(writer))
+ {
+ for (String content : contents)
+ {
+ out.println(content);
+ }
+ }
+ }
+}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/TestUseCases.java b/jetty-start/src/test/java/org/eclipse/jetty/start/TestUseCases.java
index ec419cf..5e0e3c8 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/TestUseCases.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/TestUseCases.java
@@ -60,6 +60,12 @@
{
assertUseCase("home","base.jmx","assert-jmx.txt");
}
+
+ @Test
+ public void testWithExtraStartDir_Logging() throws Exception
+ {
+ assertUseCase("home","base.with.extra.start.dirs","assert-extra-start-dir-logging.txt");
+ }
@Test
public void testWithMissingNpnVersion() throws Exception
@@ -76,7 +82,6 @@
@Test
public void testWithSpdyBadNpnVersion() throws Exception
{
- //StartLog.enableDebug();
assertUseCase("home","base.enable.spdy.bad.npn.version","assert-enable-spdy-bad-npn-version.txt","java.version=1.7.0_01");
}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/config/ConfigSourcesTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/config/ConfigSourcesTest.java
new file mode 100644
index 0000000..bc55cb7
--- /dev/null
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/config/ConfigSourcesTest.java
@@ -0,0 +1,599 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.config;
+
+import static org.hamcrest.Matchers.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jetty.start.ConfigurationAssert;
+import org.eclipse.jetty.start.Props.Prop;
+import org.eclipse.jetty.start.TestEnv;
+import org.eclipse.jetty.start.UsageException;
+import org.eclipse.jetty.toolchain.test.FS;
+import org.eclipse.jetty.toolchain.test.TestingDir;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class ConfigSourcesTest
+{
+ @Rule
+ public TestingDir testdir = new TestingDir();
+
+ private void assertIdOrder(ConfigSources sources, String... expectedOrder)
+ {
+ List<String> actualList = new ArrayList<>();
+ for (ConfigSource source : sources)
+ {
+ actualList.add(source.getId());
+ }
+ List<String> expectedList = Arrays.asList(expectedOrder);
+ ConfigurationAssert.assertOrdered("ConfigSources.id order",expectedList,actualList);
+ }
+
+ private void assertDirOrder(ConfigSources sources, File... expectedDirOrder)
+ {
+ List<String> actualList = new ArrayList<>();
+ for (ConfigSource source : sources)
+ {
+ if (source instanceof DirConfigSource)
+ {
+ actualList.add(((DirConfigSource)source).getDir().toString());
+ }
+ }
+ List<String> expectedList = new ArrayList<>();
+ for (File path : expectedDirOrder)
+ {
+ expectedList.add(path.getAbsolutePath());
+ }
+ ConfigurationAssert.assertOrdered("ConfigSources.dir order",expectedList,actualList);
+ }
+
+ private void assertProperty(ConfigSources sources, String key, String expectedValue)
+ {
+ Prop prop = sources.getProp(key);
+ Assert.assertThat("getProp('" + key + "') should not be null",prop,notNullValue());
+ Assert.assertThat("getProp('" + key + "')",prop.value,is(expectedValue));
+ }
+
+ @Test
+ public void testOrder_BasicConfig() throws IOException
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1");
+
+ ConfigSources sources = new ConfigSources();
+
+ String[] cmdLine = new String[0];
+ sources.add(new CommandLineConfigSource(cmdLine));
+ sources.add(new JettyBaseConfigSource(base.toPath()));
+ sources.add(new JettyHomeConfigSource(home.toPath()));
+
+ assertIdOrder(sources,"<command-line>","${jetty.base}","${jetty.home}");
+ }
+
+ @Test
+ public void testOrder_With1ExtraConfig() throws IOException
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ ConfigSources sources = new ConfigSources();
+
+ String[] cmdLine = new String[0];
+ sources.add(new CommandLineConfigSource(cmdLine));
+ sources.add(new JettyHomeConfigSource(home.toPath()));
+ sources.add(new JettyBaseConfigSource(base.toPath()));
+
+ assertIdOrder(sources,"<command-line>","${jetty.base}",common.getAbsolutePath(),"${jetty.home}");
+ }
+
+ @Test
+ public void testCommandLine_1Extra_FromSimpleProp() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini","jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1");
+
+ ConfigSources sources = new ConfigSources();
+
+ // Simple command line reference to extra-start-dir via property (also on command line)
+
+ String[] cmdLine = new String[] {
+ // property
+ "my.common=" + common.getAbsolutePath(),
+ // reference via property
+ "--extra-start-dir=${my.common}" };
+
+ sources.add(new CommandLineConfigSource(cmdLine));
+ sources.add(new JettyHomeConfigSource(home.toPath()));
+ sources.add(new JettyBaseConfigSource(base.toPath()));
+
+ assertIdOrder(sources,"<command-line>","${jetty.base}","${my.common}","${jetty.home}");
+
+ assertDirOrder(sources,base,common,home);
+
+ assertProperty(sources,"jetty.host","127.0.0.1");
+ assertProperty(sources,"jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testCommandLine_1Extra_FromPropPrefix() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create opt
+ File opt = testdir.getFile("opt");
+ FS.ensureEmpty(opt);
+
+ // Create common
+ File common = new File(opt,"common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini","jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1");
+
+ String dirRef = "${my.opt}" + File.separator + "common";
+
+ ConfigSources sources = new ConfigSources();
+
+ // Simple command line reference to extra-start-dir via property (also on command line)
+ String[] cmdLine = new String[] {
+ // property to 'opt' dir
+ "my.opt=" + opt.getAbsolutePath(),
+ // reference via property prefix
+ "--extra-start-dir=" + dirRef };
+
+ sources.add(new CommandLineConfigSource(cmdLine));
+ sources.add(new JettyHomeConfigSource(home.toPath()));
+ sources.add(new JettyBaseConfigSource(base.toPath()));
+
+ assertIdOrder(sources,"<command-line>","${jetty.base}",dirRef,"${jetty.home}");
+
+ assertDirOrder(sources,base,common,home);
+
+ assertProperty(sources,"jetty.host","127.0.0.1");
+ assertProperty(sources,"jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testCommandLine_1Extra_FromCompoundProp() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create opt
+ File opt = testdir.getFile("opt");
+ FS.ensureEmpty(opt);
+
+ // Create common
+ File common = new File(opt,"common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini","jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1");
+
+ String dirRef = "${my.opt}" + File.separator + "${my.dir}";
+
+ ConfigSources sources = new ConfigSources();
+
+ // Simple command line reference to extra-start-dir via property (also on command line)
+
+ String[] cmdLine = new String[] {
+ // property to 'opt' dir
+ "my.opt=" + opt.getAbsolutePath(),
+ // property to commmon dir name
+ "my.dir=common",
+ // reference via property prefix
+ "--extra-start-dir=" + dirRef };
+
+ sources.add(new CommandLineConfigSource(cmdLine));
+ sources.add(new JettyHomeConfigSource(home.toPath()));
+ sources.add(new JettyBaseConfigSource(base.toPath()));
+
+ assertIdOrder(sources,"<command-line>","${jetty.base}",dirRef,"${jetty.home}");
+
+ assertDirOrder(sources,base,common,home);
+
+ assertProperty(sources,"jetty.host","127.0.0.1");
+ assertProperty(sources,"jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testRefCommon() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini","jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ ConfigSources sources = new ConfigSources();
+
+ String cmdLine[] = new String[0];
+ sources.add(new CommandLineConfigSource(cmdLine));
+ sources.add(new JettyHomeConfigSource(home.toPath()));
+ sources.add(new JettyBaseConfigSource(base.toPath()));
+
+ assertIdOrder(sources,"<command-line>","${jetty.base}",common.getAbsolutePath(),"${jetty.home}");
+
+ assertDirOrder(sources,base,common,home);
+
+ assertProperty(sources,"jetty.host","127.0.0.1");
+ assertProperty(sources,"jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testRefCommonAndCorp() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini","jetty.port=8080");
+
+ // Create corp
+ File corp = testdir.getFile("corp");
+ FS.ensureEmpty(corp);
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath(), //
+ "--extra-start-dir=" + corp.getAbsolutePath());
+
+ ConfigSources sources = new ConfigSources();
+
+ String cmdLine[] = new String[0];
+ sources.add(new CommandLineConfigSource(cmdLine));
+ sources.add(new JettyHomeConfigSource(home.toPath()));
+ sources.add(new JettyBaseConfigSource(base.toPath()));
+
+ assertIdOrder(sources,"<command-line>","${jetty.base}",
+ common.getAbsolutePath(),
+ corp.getAbsolutePath(),
+ "${jetty.home}");
+
+ assertDirOrder(sources,base,common,corp,home);
+
+ assertProperty(sources,"jetty.host","127.0.0.1");
+ assertProperty(sources,"jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testRefCommonRefCorp() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create corp
+ File corp = testdir.getFile("corp");
+ FS.ensureEmpty(corp);
+ TestEnv.makeFile(corp,"start.ini", //
+ "jetty.port=9090");
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini", //
+ "--extra-start-dir=" + corp.getAbsolutePath(), //
+ "jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ ConfigSources sources = new ConfigSources();
+
+ String cmdLine[] = new String[0];
+ sources.add(new CommandLineConfigSource(cmdLine));
+ sources.add(new JettyHomeConfigSource(home.toPath()));
+ sources.add(new JettyBaseConfigSource(base.toPath()));
+
+ assertIdOrder(sources,"<command-line>","${jetty.base}",
+ common.getAbsolutePath(),
+ corp.getAbsolutePath(),
+ "${jetty.home}");
+
+ assertDirOrder(sources,base,common,corp,home);
+
+ assertProperty(sources,"jetty.host","127.0.0.1");
+ assertProperty(sources,"jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testRefCommonRefCorp_FromSimpleProps() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create corp
+ File corp = testdir.getFile("corp");
+ FS.ensureEmpty(corp);
+ TestEnv.makeFile(corp,"start.ini", //
+ "jetty.port=9090");
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini", //
+ "my.corp=" + corp.getAbsolutePath(), //
+ "--extra-start-dir=${my.corp}", //
+ "jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "my.common="+common.getAbsolutePath(), //
+ "--extra-start-dir=${my.common}");
+
+ ConfigSources sources = new ConfigSources();
+
+ String cmdLine[] = new String[0];
+ sources.add(new CommandLineConfigSource(cmdLine));
+ sources.add(new JettyHomeConfigSource(home.toPath()));
+ sources.add(new JettyBaseConfigSource(base.toPath()));
+
+ assertIdOrder(sources,"<command-line>",
+ "${jetty.base}",
+ "${my.common}",
+ "${my.corp}",
+ "${jetty.home}");
+
+ assertDirOrder(sources,base,common,corp,home);
+
+ assertProperty(sources,"jetty.host","127.0.0.1");
+ assertProperty(sources,"jetty.port","8080"); // from 'common'
+ }
+
+ @Test
+ public void testRefCommonRefCorp_CmdLineRef() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create devops
+ File devops = testdir.getFile("devops");
+ FS.ensureEmpty(devops);
+ TestEnv.makeFile(devops,"start.ini", //
+ "--module=logging", //
+ "jetty.port=2222");
+
+ // Create corp
+ File corp = testdir.getFile("corp");
+ FS.ensureEmpty(corp);
+ TestEnv.makeFile(corp,"start.ini", //
+ "jetty.port=9090");
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini", //
+ "--extra-start-dir=" + corp.getAbsolutePath(), //
+ "jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ ConfigSources sources = new ConfigSources();
+
+ String cmdLine[] = new String[]{
+ // command line provided extra-start-dir ref
+ "--extra-start-dir=" + devops.getAbsolutePath()};
+ sources.add(new CommandLineConfigSource(cmdLine));
+ sources.add(new JettyHomeConfigSource(home.toPath()));
+ sources.add(new JettyBaseConfigSource(base.toPath()));
+
+ assertIdOrder(sources,"<command-line>",
+ "${jetty.base}",
+ devops.getAbsolutePath(),
+ common.getAbsolutePath(),
+ corp.getAbsolutePath(),
+ "${jetty.home}");
+
+ assertDirOrder(sources,base,devops,common,corp,home);
+
+ assertProperty(sources,"jetty.host","127.0.0.1");
+ assertProperty(sources,"jetty.port","2222"); // from 'common'
+ }
+
+ @Test
+ public void testRefCommonRefCorp_CmdLineProp() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create corp
+ File corp = testdir.getFile("corp");
+ FS.ensureEmpty(corp);
+ TestEnv.makeFile(corp,"start.ini", //
+ "jetty.port=9090");
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+ TestEnv.makeFile(common,"start.ini", //
+ "--extra-start-dir=" + corp.getAbsolutePath(), //
+ "jetty.port=8080");
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ ConfigSources sources = new ConfigSources();
+
+ String cmdLine[] = new String[]{
+ // command line property should override all others
+ "jetty.port=7070"
+ };
+ sources.add(new CommandLineConfigSource(cmdLine));
+ sources.add(new JettyHomeConfigSource(home.toPath()));
+ sources.add(new JettyBaseConfigSource(base.toPath()));
+
+ assertIdOrder(sources,"<command-line>","${jetty.base}",
+ common.getAbsolutePath(),
+ corp.getAbsolutePath(),
+ "${jetty.home}");
+
+ assertDirOrder(sources,base,common,corp,home);
+
+ assertProperty(sources,"jetty.host","127.0.0.1");
+ assertProperty(sources,"jetty.port","7070"); // from <command-line>
+ }
+
+ @Test
+ public void testBadDoubleRef() throws Exception
+ {
+ // Create home
+ File home = testdir.getFile("home");
+ FS.ensureEmpty(home);
+ TestEnv.copyTestDir("usecases/home",home);
+
+ // Create common
+ File common = testdir.getFile("common");
+ FS.ensureEmpty(common);
+
+ // Create corp
+ File corp = testdir.getFile("corp");
+ FS.ensureEmpty(corp);
+ TestEnv.makeFile(corp,"start.ini",
+ // standard property
+ "jetty.port=9090",
+ // INTENTIONAL BAD Reference (duplicate)
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ // Populate common
+ TestEnv.makeFile(common,"start.ini",
+ // standard property
+ "jetty.port=8080",
+ // reference to corp
+ "--extra-start-dir=" + corp.getAbsolutePath());
+
+ // Create base
+ File base = testdir.getFile("base");
+ FS.ensureEmpty(base);
+ TestEnv.makeFile(base,"start.ini", //
+ "jetty.host=127.0.0.1",//
+ "--extra-start-dir=" + common.getAbsolutePath());
+
+ ConfigSources sources = new ConfigSources();
+
+ try
+ {
+ String cmdLine[] = new String[0];
+ sources.add(new CommandLineConfigSource(cmdLine));
+ sources.add(new JettyHomeConfigSource(home.toPath()));
+ sources.add(new JettyBaseConfigSource(base.toPath()));
+
+ Assert.fail("Should have thrown a UsageException");
+ }
+ catch (UsageException e)
+ {
+ Assert.assertThat("UsageException",e.getMessage(),containsString("Duplicate"));
+ }
+ }
+}
diff --git a/jetty-start/src/test/resources/assert-home-with-jvm.txt b/jetty-start/src/test/resources/assert-home-with-jvm.txt
index b73061b..9774d97 100644
--- a/jetty-start/src/test/resources/assert-home-with-jvm.txt
+++ b/jetty-start/src/test/resources/assert-home-with-jvm.txt
@@ -1,38 +1,38 @@
# The XMLs we expect (order is important)
-XML|${jetty.home}/etc/jetty-jmx.xml
-XML|${jetty.home}/etc/jetty.xml
-XML|${jetty.home}/etc/jetty-http.xml
-XML|${jetty.home}/etc/jetty-plus.xml
-XML|${jetty.home}/etc/jetty-annotations.xml
-XML|${jetty.home}/etc/jetty-websockets.xml
-XML|${jetty.home}/etc/jetty-logging.xml
+XML|${jetty.base}/etc/jetty-jmx.xml
+XML|${jetty.base}/etc/jetty.xml
+XML|${jetty.base}/etc/jetty-http.xml
+XML|${jetty.base}/etc/jetty-plus.xml
+XML|${jetty.base}/etc/jetty-annotations.xml
+XML|${jetty.base}/etc/jetty-websockets.xml
+XML|${jetty.base}/etc/jetty-logging.xml
# The LIBs we expect (order is irrelevant)
-LIB|${jetty.home}/lib/annotations/javax.annotation-api-1.2.jar
-LIB|${jetty.home}/lib/annotations/org.objectweb.asm-TEST.jar
-LIB|${jetty.home}/lib/jetty-annotations-TEST.jar
-LIB|${jetty.home}/lib/jetty-continuation-TEST.jar
-LIB|${jetty.home}/lib/jetty-http-TEST.jar
-LIB|${jetty.home}/lib/jetty-io-TEST.jar
-LIB|${jetty.home}/lib/jetty-jmx-TEST.jar
-LIB|${jetty.home}/lib/jetty-jndi-TEST.jar
-LIB|${jetty.home}/lib/jetty-plus-TEST.jar
-LIB|${jetty.home}/lib/jetty-schemas-3.1.jar
-LIB|${jetty.home}/lib/jetty-security-TEST.jar
-LIB|${jetty.home}/lib/jetty-server-TEST.jar
-LIB|${jetty.home}/lib/jetty-util-TEST.jar
-LIB|${jetty.home}/lib/jetty-xml-TEST.jar
-LIB|${jetty.home}/lib/jndi/javax.activation-1.1.jar
-LIB|${jetty.home}/lib/jndi/javax.transaction-api-1.2.jar
-LIB|${jetty.home}/lib/servlet-api-3.1.jar
-LIB|${jetty.home}/lib/websocket/javax.websocket-api-1.0.jar
-LIB|${jetty.home}/lib/websocket/javax-websocket-client-impl-TEST.jar
-LIB|${jetty.home}/lib/websocket/javax-websocket-server-impl-TEST.jar
-LIB|${jetty.home}/lib/websocket/websocket-api-TEST.jar
-LIB|${jetty.home}/lib/websocket/websocket-client-TEST.jar
-LIB|${jetty.home}/lib/websocket/websocket-common-TEST.jar
-LIB|${jetty.home}/lib/websocket/websocket-server-TEST.jar
-LIB|${jetty.home}/lib/websocket/websocket-servlet-TEST.jar
+LIB|${jetty.base}/lib/annotations/javax.annotation-api-1.2.jar
+LIB|${jetty.base}/lib/annotations/org.objectweb.asm-TEST.jar
+LIB|${jetty.base}/lib/jetty-annotations-TEST.jar
+LIB|${jetty.base}/lib/jetty-continuation-TEST.jar
+LIB|${jetty.base}/lib/jetty-http-TEST.jar
+LIB|${jetty.base}/lib/jetty-io-TEST.jar
+LIB|${jetty.base}/lib/jetty-jmx-TEST.jar
+LIB|${jetty.base}/lib/jetty-jndi-TEST.jar
+LIB|${jetty.base}/lib/jetty-plus-TEST.jar
+LIB|${jetty.base}/lib/jetty-schemas-3.1.jar
+LIB|${jetty.base}/lib/jetty-security-TEST.jar
+LIB|${jetty.base}/lib/jetty-server-TEST.jar
+LIB|${jetty.base}/lib/jetty-util-TEST.jar
+LIB|${jetty.base}/lib/jetty-xml-TEST.jar
+LIB|${jetty.base}/lib/jndi/javax.activation-1.1.jar
+LIB|${jetty.base}/lib/jndi/javax.transaction-api-1.2.jar
+LIB|${jetty.base}/lib/servlet-api-3.1.jar
+LIB|${jetty.base}/lib/websocket/javax.websocket-api-1.0.jar
+LIB|${jetty.base}/lib/websocket/javax-websocket-client-impl-TEST.jar
+LIB|${jetty.base}/lib/websocket/javax-websocket-server-impl-TEST.jar
+LIB|${jetty.base}/lib/websocket/websocket-api-TEST.jar
+LIB|${jetty.base}/lib/websocket/websocket-client-TEST.jar
+LIB|${jetty.base}/lib/websocket/websocket-common-TEST.jar
+LIB|${jetty.base}/lib/websocket/websocket-server-TEST.jar
+LIB|${jetty.base}/lib/websocket/websocket-servlet-TEST.jar
LIB|${maven-test-resources}/extra-resources
LIB|${maven-test-resources}/extra-libs/example.jar
diff --git a/jetty-start/src/test/resources/assert-home-with-spaces.txt b/jetty-start/src/test/resources/assert-home-with-spaces.txt
index 01d429a..d63fcce 100644
--- a/jetty-start/src/test/resources/assert-home-with-spaces.txt
+++ b/jetty-start/src/test/resources/assert-home-with-spaces.txt
@@ -2,7 +2,7 @@
# No XMLs in this home
# The LIBs we expect (order is irrelevant)
-LIB|${jetty.home}/lib/example of a library with spaces.jar
+LIB|${jetty.base}/lib/example of a library with spaces.jar
# The Properties we expect (order is irrelevant)
PROP|test.message=Hello
diff --git a/jetty-start/src/test/resources/assert-home.txt b/jetty-start/src/test/resources/assert-home.txt
index 327b770..5be8d46 100644
--- a/jetty-start/src/test/resources/assert-home.txt
+++ b/jetty-start/src/test/resources/assert-home.txt
@@ -1,37 +1,37 @@
# The XMLs we expect (order is important)
-XML|${jetty.home}/etc/jetty-jmx.xml
-XML|${jetty.home}/etc/jetty.xml
-XML|${jetty.home}/etc/jetty-http.xml
-XML|${jetty.home}/etc/jetty-plus.xml
-XML|${jetty.home}/etc/jetty-annotations.xml
-XML|${jetty.home}/etc/jetty-websockets.xml
+XML|${jetty.base}/etc/jetty-jmx.xml
+XML|${jetty.base}/etc/jetty.xml
+XML|${jetty.base}/etc/jetty-http.xml
+XML|${jetty.base}/etc/jetty-plus.xml
+XML|${jetty.base}/etc/jetty-annotations.xml
+XML|${jetty.base}/etc/jetty-websockets.xml
# The LIBs we expect (order is irrelevant)
-LIB|${jetty.home}/lib/annotations/javax.annotation-api-1.2.jar
-LIB|${jetty.home}/lib/annotations/org.objectweb.asm-TEST.jar
-LIB|${jetty.home}/lib/jetty-annotations-TEST.jar
-LIB|${jetty.home}/lib/jetty-continuation-TEST.jar
-LIB|${jetty.home}/lib/jetty-http-TEST.jar
-LIB|${jetty.home}/lib/jetty-io-TEST.jar
-LIB|${jetty.home}/lib/jetty-jmx-TEST.jar
-LIB|${jetty.home}/lib/jetty-jndi-TEST.jar
-LIB|${jetty.home}/lib/jetty-plus-TEST.jar
-LIB|${jetty.home}/lib/jetty-schemas-3.1.jar
-LIB|${jetty.home}/lib/jetty-security-TEST.jar
-LIB|${jetty.home}/lib/jetty-server-TEST.jar
-LIB|${jetty.home}/lib/jetty-util-TEST.jar
-LIB|${jetty.home}/lib/jetty-xml-TEST.jar
-LIB|${jetty.home}/lib/jndi/javax.activation-1.1.jar
-LIB|${jetty.home}/lib/jndi/javax.transaction-api-1.2.jar
-LIB|${jetty.home}/lib/servlet-api-3.1.jar
-LIB|${jetty.home}/lib/websocket/javax.websocket-api-1.0.jar
-LIB|${jetty.home}/lib/websocket/javax-websocket-client-impl-TEST.jar
-LIB|${jetty.home}/lib/websocket/javax-websocket-server-impl-TEST.jar
-LIB|${jetty.home}/lib/websocket/websocket-api-TEST.jar
-LIB|${jetty.home}/lib/websocket/websocket-client-TEST.jar
-LIB|${jetty.home}/lib/websocket/websocket-common-TEST.jar
-LIB|${jetty.home}/lib/websocket/websocket-server-TEST.jar
-LIB|${jetty.home}/lib/websocket/websocket-servlet-TEST.jar
+LIB|${jetty.base}/lib/annotations/javax.annotation-api-1.2.jar
+LIB|${jetty.base}/lib/annotations/org.objectweb.asm-TEST.jar
+LIB|${jetty.base}/lib/jetty-annotations-TEST.jar
+LIB|${jetty.base}/lib/jetty-continuation-TEST.jar
+LIB|${jetty.base}/lib/jetty-http-TEST.jar
+LIB|${jetty.base}/lib/jetty-io-TEST.jar
+LIB|${jetty.base}/lib/jetty-jmx-TEST.jar
+LIB|${jetty.base}/lib/jetty-jndi-TEST.jar
+LIB|${jetty.base}/lib/jetty-plus-TEST.jar
+LIB|${jetty.base}/lib/jetty-schemas-3.1.jar
+LIB|${jetty.base}/lib/jetty-security-TEST.jar
+LIB|${jetty.base}/lib/jetty-server-TEST.jar
+LIB|${jetty.base}/lib/jetty-util-TEST.jar
+LIB|${jetty.base}/lib/jetty-xml-TEST.jar
+LIB|${jetty.base}/lib/jndi/javax.activation-1.1.jar
+LIB|${jetty.base}/lib/jndi/javax.transaction-api-1.2.jar
+LIB|${jetty.base}/lib/servlet-api-3.1.jar
+LIB|${jetty.base}/lib/websocket/javax.websocket-api-1.0.jar
+LIB|${jetty.base}/lib/websocket/javax-websocket-client-impl-TEST.jar
+LIB|${jetty.base}/lib/websocket/javax-websocket-server-impl-TEST.jar
+LIB|${jetty.base}/lib/websocket/websocket-api-TEST.jar
+LIB|${jetty.base}/lib/websocket/websocket-client-TEST.jar
+LIB|${jetty.base}/lib/websocket/websocket-common-TEST.jar
+LIB|${jetty.base}/lib/websocket/websocket-server-TEST.jar
+LIB|${jetty.base}/lib/websocket/websocket-servlet-TEST.jar
# The Properties we expect (order is irrelevant)
PROP|jetty.port=9090
diff --git a/jetty-start/src/test/resources/extra-start-dirs/logging/etc/jetty-logging.xml b/jetty-start/src/test/resources/extra-start-dirs/logging/etc/jetty-logging.xml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/jetty-start/src/test/resources/extra-start-dirs/logging/etc/jetty-logging.xml
diff --git a/jetty-start/src/test/resources/extra-start-dirs/logging/lib/logging/logback.jar b/jetty-start/src/test/resources/extra-start-dirs/logging/lib/logging/logback.jar
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/jetty-start/src/test/resources/extra-start-dirs/logging/lib/logging/logback.jar
diff --git a/jetty-start/src/test/resources/extra-start-dirs/logging/start.ini b/jetty-start/src/test/resources/extra-start-dirs/logging/start.ini
new file mode 100644
index 0000000..905d6db
--- /dev/null
+++ b/jetty-start/src/test/resources/extra-start-dirs/logging/start.ini
@@ -0,0 +1 @@
+--module=logging
\ No newline at end of file
diff --git a/jetty-start/src/test/resources/extra-start-dirs/more-startd/start.d/more.ini b/jetty-start/src/test/resources/extra-start-dirs/more-startd/start.d/more.ini
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/jetty-start/src/test/resources/extra-start-dirs/more-startd/start.d/more.ini
diff --git a/jetty-start/src/test/resources/usecases/assert-extra-start-dir-logging.txt b/jetty-start/src/test/resources/usecases/assert-extra-start-dir-logging.txt
new file mode 100644
index 0000000..def27d7
--- /dev/null
+++ b/jetty-start/src/test/resources/usecases/assert-extra-start-dir-logging.txt
@@ -0,0 +1,18 @@
+# The XMLs we expect (order is important)
+XML|${jetty.home}/etc/jetty-jmx.xml
+XML|${jetty.home}/etc/jetty.xml
+XML|${jetty.home}/etc/jetty-http.xml
+
+# The LIBs we expect (order is irrelevant)
+LIB|${jetty.home}/lib/jetty-continuation-TEST.jar
+LIB|${jetty.home}/lib/jetty-http-TEST.jar
+LIB|${jetty.home}/lib/jetty-io-TEST.jar
+LIB|${jetty.home}/lib/jetty-jmx-TEST.jar
+LIB|${jetty.home}/lib/jetty-schemas-3.1.jar
+LIB|${jetty.home}/lib/jetty-server-TEST.jar
+LIB|${jetty.home}/lib/jetty-util-TEST.jar
+LIB|${jetty.home}/lib/jetty-xml-TEST.jar
+LIB|${jetty.home}/lib/servlet-api-3.1.jar
+
+# The Properties we expect (order is irrelevant)
+PROP|jetty.port=9090
diff --git a/jetty-start/src/test/resources/usecases/base.with.extra.start.dirs/start.ini b/jetty-start/src/test/resources/usecases/base.with.extra.start.dirs/start.ini
new file mode 100644
index 0000000..81e6d72
--- /dev/null
+++ b/jetty-start/src/test/resources/usecases/base.with.extra.start.dirs/start.ini
@@ -0,0 +1,5 @@
+
+--extra-start-dir=${start.basedir}/../../extra-start-dirs/logging
+--module=server,http,jmx
+
+jetty.port=9090
diff --git a/jetty-start/src/test/resources/usecases/home/modules/ext.mod b/jetty-start/src/test/resources/usecases/home/modules/ext.mod
index c84697a..66c0519 100644
--- a/jetty-start/src/test/resources/usecases/home/modules/ext.mod
+++ b/jetty-start/src/test/resources/usecases/home/modules/ext.mod
@@ -3,7 +3,7 @@
#
[lib]
-regex:lib/ext/.*\.jar$
+lib/ext/**.jar
[files]
lib/
diff --git a/jetty-util-ajax/pom.xml b/jetty-util-ajax/pom.xml
index 7fdea25..26c3422 100644
--- a/jetty-util-ajax/pom.xml
+++ b/jetty-util-ajax/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-util-ajax</artifactId>
diff --git a/jetty-util/pom.xml b/jetty-util/pom.xml
index 0b0f987..8850d89 100644
--- a/jetty-util/pom.xml
+++ b/jetty-util/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-util</artifactId>
diff --git a/jetty-util/src/main/config/modules/logging.mod b/jetty-util/src/main/config/modules/logging.mod
index 9d36e2e..a39bfe4 100644
--- a/jetty-util/src/main/config/modules/logging.mod
+++ b/jetty-util/src/main/config/modules/logging.mod
@@ -8,6 +8,10 @@
[files]
logs/
+[lib]
+lib/logging/**.jar
+resources/
+
[ini-template]
## Logging Configuration
# Configure jetty logging for default internal behavior STDERR output
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 b5e2dcc..16d3701 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
@@ -575,6 +575,49 @@
return minus ? (-val) : val;
throw new NumberFormatException(toString(buffer));
}
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Convert buffer to an integer. Parses up to the first non-numeric character. If no number is found an IllegalArgumentException is thrown
+ *
+ * @param buffer
+ * A buffer containing an integer in flush mode. The position is updated.
+ * @return an int
+ */
+ public static int takeInt(ByteBuffer buffer)
+ {
+ int val = 0;
+ boolean started = false;
+ boolean minus = false;
+ int i;
+ for (i = buffer.position(); i < buffer.limit(); i++)
+ {
+ byte b = buffer.get(i);
+ if (b <= SPACE)
+ {
+ if (started)
+ break;
+ }
+ else if (b >= '0' && b <= '9')
+ {
+ val = val * 10 + (b - '0');
+ started = true;
+ }
+ else if (b == MINUS && !started)
+ {
+ minus = true;
+ }
+ else
+ break;
+ }
+
+ if (started)
+ {
+ buffer.position(i);
+ return minus ? (-val) : val;
+ }
+ throw new NumberFormatException(toString(buffer));
+ }
/**
* Convert buffer to an long. Parses up to the first non-numeric character. If no number is found an IllegalArgumentException is thrown
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java
deleted file mode 100644
index 63f5cd7..0000000
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java
+++ /dev/null
@@ -1,196 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2014 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;
-
-import java.nio.ByteBuffer;
-import java.util.AbstractMap;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-/* ------------------------------------------------------------ */
-/** Map implementation Optimized for Strings keys..
- * This String Map has been optimized for mapping small sets of
- * Strings where the most frequently accessed Strings have been put to
- * the map first.
- *
- * It also has the benefit that it can look up entries by substring or
- * sections of char and byte arrays. This can prevent many String
- * objects from being created just to look up in the map.
- *
- * This map is NOT synchronized.
- * @deprecated Use {@link Trie}
- */
-public class StringMap<O> extends AbstractMap<String,O>
-{
- private final TreeMap<Object, O> _map;
-
-
- public static final boolean CASE_INSENSTIVE=true;
-
- /* ------------------------------------------------------------ */
-
- private final boolean _caseInsensitive;
-
-
- /* ------------------------------------------------------------ */
- /** Constructor.
- */
- public StringMap()
- {
- this(false);
- }
-
- /* ------------------------------------------------------------ */
- /** Constructor.
- * @param ignoreCase
- */
- public StringMap(final boolean ignoreCase)
- {
- _caseInsensitive=ignoreCase;
- _map = new TreeMap<Object,O>(new Comparator<Object>()
- {
- @Override
- public int compare(Object o1, Object o2)
- {
- String s1=(o1 instanceof String)?(String)o1:null;
- ByteBuffer b1=(o1 instanceof ByteBuffer)?(ByteBuffer)o1:null;
- if (s1==null && b1==null)
- s1=o1.toString();
- String s2=(String)o2;
-
- int n1 = s1==null?b1.remaining():s1.length();
- int n2 = s2.length();
- int min = Math.min(n1, n2);
- for (int i = 0; i < min; i++) {
- char c1 = s1==null?(char)b1.get(b1.position()+i):s1.charAt(i);
- char c2 = s2.charAt(i);
- if (c1 != c2) {
- if (ignoreCase)
- {
- c1 = Character.toUpperCase(c1);
- c2 = Character.toUpperCase(c2);
- if (c1 != c2) {
- c1 = Character.toLowerCase(c1);
- c2 = Character.toLowerCase(c2);
- if (c1 != c2) {
- // No overflow because of numeric promotion
- return c1 - c2;
- }
- }
- }
- else
- return c1 - c2;
- }
- }
- return n1 - n2;
- }
- });
- }
-
- /* ------------------------------------------------------------ */
- public boolean isIgnoreCase()
- {
- return _caseInsensitive;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public O put(String key, O value)
- {
- return _map.put(key,value);
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public O get(Object key)
- {
- return _map.get(key);
- }
-
- /* ------------------------------------------------------------ */
- public O get(String key)
- {
- return _map.get(key);
- }
-
- /* ------------------------------------------------------------ */
- public O get(String key,int offset,int length)
- {
- return _map.get(key.substring(offset,offset+length));
- }
-
- /* ------------------------------------------------------------ */
- public O get(ByteBuffer buffer)
- {
- return _map.get(buffer);
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public O remove(Object key)
- {
- return _map.remove(key);
- }
-
- /* ------------------------------------------------------------ */
- public O remove(String key)
- {
- return _map.remove(key);
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public Set<Map.Entry<String,O>> entrySet()
- {
- Object o=_map.entrySet();
- return Collections.unmodifiableSet((Set<Map.Entry<String,O>>)o);
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public int size()
- {
- return _map.size();
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public boolean isEmpty()
- {
- return _map.isEmpty();
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public boolean containsKey(Object key)
- {
- return _map.containsKey(key);
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public void clear()
- {
- _map.clear();
- }
-
-}
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/UrlEncoded.java b/jetty-util/src/main/java/org/eclipse/jetty/util/UrlEncoded.java
index a826508..ef7f2f5 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/UrlEncoded.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/UrlEncoded.java
@@ -294,7 +294,7 @@
switch ((char)(0xff&b))
{
case '&':
- value = buffer.length()==0?"":buffer.toString();
+ value = buffer.toReplacedString();
buffer.reset();
if (key != null)
{
@@ -314,7 +314,7 @@
buffer.append(b);
break;
}
- key = buffer.toString();
+ key = buffer.toReplacedString();
buffer.reset();
break;
@@ -376,7 +376,7 @@
if (key != null)
{
- value = buffer.length()==0?"":buffer.toReplacedString();
+ value = buffer.toReplacedString();
buffer.reset();
map.add(key,value);
}
@@ -510,7 +510,7 @@
switch ((char) b)
{
case '&':
- value = buffer.length()==0?"":buffer.toString();
+ value = buffer.toReplacedString();
buffer.reset();
if (key != null)
{
@@ -532,7 +532,7 @@
buffer.append((byte)b);
break;
}
- key = buffer.toString();
+ key = buffer.toReplacedString();
buffer.reset();
break;
@@ -542,17 +542,26 @@
case '%':
int code0=in.read();
+ boolean decoded=false;
if ('u'==code0)
{
- int code1=in.read();
- if (code1>=0)
+ code0=in.read(); // XXX: we have to read the next byte, otherwise code0 is always 'u'
+ if (code0>=0)
{
- int code2=in.read();
- if (code2>=0)
+ int code1=in.read();
+ if (code1>=0)
{
- int code3=in.read();
- if (code3>=0)
- buffer.getStringBuilder().append(Character.toChars((convertHexDigit(code0)<<12)+(convertHexDigit(code1)<<8)+(convertHexDigit(code2)<<4)+convertHexDigit(code3)));
+ int code2=in.read();
+ if (code2>=0)
+ {
+ int code3=in.read();
+ if (code3>=0)
+ {
+ buffer.getStringBuilder().append(Character.toChars
+ ((convertHexDigit(code0)<<12)+(convertHexDigit(code1)<<8)+(convertHexDigit(code2)<<4)+convertHexDigit(code3)));
+ decoded=true;
+ }
+ }
}
}
}
@@ -560,8 +569,15 @@
{
int code1=in.read();
if (code1>=0)
+ {
buffer.append((byte)((convertHexDigit(code0)<<4)+convertHexDigit(code1)));
+ decoded=true;
+ }
}
+
+ if (!decoded)
+ buffer.getStringBuilder().append(Utf8Appendable.REPLACEMENT);
+
break;
default:
@@ -586,13 +602,13 @@
if (key != null)
{
- value = buffer.length()==0?"":buffer.toString();
+ value = buffer.toReplacedString();
buffer.reset();
map.add(key,value);
}
else if (buffer.length()>0)
{
- map.add(buffer.toString(), "");
+ map.add(buffer.toReplacedString(), "");
}
}
}
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/StringMapTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/StringMapTest.java
deleted file mode 100644
index c20e9f1..0000000
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/StringMapTest.java
+++ /dev/null
@@ -1,209 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2014 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;
-
-import java.util.Set;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-public class StringMapTest
-{
- StringMap<String> m0;
- StringMap<String> m1;
- StringMap<String> m5;
- StringMap<String> m5i;
-
- /*
- * @see TestCase#setUp()
- */
-
- @Before
- public void setUp() throws Exception
- {
- m0=new StringMap<>();
- m1=new StringMap<>(false);
- m1.put("abc", "0");
-
- m5=new StringMap<>(false);
- m5.put("a", "0");
- m5.put("ab", "1");
- m5.put("abc", "2");
- m5.put("abb", "3");
- m5.put("bbb", "4");
-
- m5i=new StringMap<>(true);
- m5i.put("ab", "1");
- m5i.put("abc", "2");
- m5i.put("abb", "3");
- }
-
- @Test
- public void testSize()
- {
- Assert.assertEquals(0, m0.size());
- Assert.assertEquals(1, m1.size());
- Assert.assertEquals(5, m5.size());
- Assert.assertEquals(3, m5i.size());
-
- m1.remove("abc");
- m5.remove("abc");
- m5.put("bbb","x");
- m5i.put("ABC", "x");
- Assert.assertEquals(0, m0.size());
- Assert.assertEquals(0, m1.size());
- Assert.assertEquals(4, m5.size());
- Assert.assertEquals(3, m5i.size());
- }
-
- @Test
- public void testIsEmpty()
- {
- Assert.assertTrue(m0.isEmpty());
- Assert.assertFalse(m1.isEmpty());
- Assert.assertFalse(m5.isEmpty());
- Assert.assertFalse(m5i.isEmpty());
- }
-
- @Test
- public void testClear()
- {
- m0.clear();
- m1.clear();
- m5.clear();
- m5i.clear();
- Assert.assertTrue(m0.isEmpty());
- Assert.assertTrue(m1.isEmpty());
- Assert.assertTrue(m5.isEmpty());
- Assert.assertTrue(m5i.isEmpty());
- Assert.assertEquals(null, m1.get("abc"));
- Assert.assertEquals(null, m5.get("abc"));
- Assert.assertEquals(null, m5i.get("abc"));
- }
-
-
- /*
- * Test for Object put(Object, Object)
- */
- @Test
- public void testPutGet()
- {
- Assert.assertEquals("2", m5.get("abc"));
- Assert.assertEquals(null, m5.get("aBc"));
- Assert.assertEquals("2", m5i.get("abc"));
- Assert.assertEquals("2", m5i.get("aBc"));
-
- m5.put("aBc", "x");
- m5i.put("AbC", "x");
-
- StringBuilder buffer=new StringBuilder();
- buffer.append("aBc");
- Assert.assertEquals("2", m5.get("abc"));
- Assert.assertEquals("x", m5.get(buffer));
- Assert.assertEquals("x", m5i.get((Object)"abc"));
- Assert.assertEquals("x", m5i.get("aBc"));
-
-
- }
-
- /*
- * Test for Object remove(Object)
- */
- @Test
- public void testRemove()
- {
- m0.remove("abc");
- m1.remove("abc");
- m5.remove("aBc");
- m5.remove("bbb");
- m5i.remove("aBc");
-
- Assert.assertEquals(0, m0.size());
- Assert.assertEquals(0, m1.size());
- Assert.assertEquals(4, m5.size());
- Assert.assertEquals(2, m5i.size());
-
- Assert.assertEquals("2", m5.get("abc"));
- Assert.assertEquals(null, m5.get("bbb"));
- Assert.assertEquals(null, m5i.get("AbC"));
- }
-
- /*
- * Test for Set entrySet()
- */
- @Test
- public void testEntrySet()
- {
- Set es0=m0.entrySet();
- Set es1=m1.entrySet();
- Set es5=m5.entrySet();
- Assert.assertEquals(0, es0.size());
- Assert.assertEquals(1, es1.size());
- Assert.assertEquals(5, es5.size());
- }
-
- /*
- * Test for boolean containsKey(Object)
- */
- @Test
- public void testContainsKey()
- {
- Assert.assertTrue(m5.containsKey("abc"));
- Assert.assertTrue(!m5.containsKey("aBc"));
- Assert.assertTrue(m5.containsKey("bbb"));
- Assert.assertTrue(!m5.containsKey("xyz"));
-
- Assert.assertTrue(m5i.containsKey("abc"));
- Assert.assertTrue(m5i.containsKey("aBc"));
- Assert.assertTrue(m5i.containsKey("ABC"));
- }
-
- @Test
- public void testToString()
- {
- Assert.assertEquals("{}", m0.toString());
- Assert.assertEquals("{abc=0}", m1.toString());
- Assert.assertTrue(m5.toString().indexOf("abc=2") > 0);
- }
-
- @Test
- public void testIgnoreCase()
- {
- StringMap<String> map = new StringMap<>(true);
- map.put("POST","1");
- map.put("HEAD","2");
- map.put("PUT","3");
- map.put("OPTIONS","4");
- map.put("DELETE","5");
- map.put("TRACE","6");
- map.put("CONNECT","7");
- map.put("Upgrade","8");
-
- Assert.assertEquals("1", map.get("POST"));
- Assert.assertEquals("1", map.get("pOST"));
- Assert.assertEquals("1", map.get("Post"));
-
- Assert.assertEquals("8", map.get("UPGRADE"));
- Assert.assertEquals("8", map.get("Upgrade"));
- Assert.assertEquals("8", map.get("upgrade"));
-
- }
-
-}
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/UrlEncodedUtf8Test.java b/jetty-util/src/test/java/org/eclipse/jetty/util/UrlEncodedUtf8Test.java
new file mode 100644
index 0000000..a80c51c
--- /dev/null
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/UrlEncodedUtf8Test.java
@@ -0,0 +1,165 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class UrlEncodedUtf8Test
+{
+
+ static final Logger LOG=Log.getLogger(UrlEncodedUtf8Test.class);
+
+
+ @Test
+ public void testIncompleteSequestAtTheEnd() throws Exception
+ {
+ byte[] bytes= { 97, 98, 61, 99, -50 };
+ String test=new String(bytes,StandardCharsets.UTF_8);
+ String expected = "c"+Utf8Appendable.REPLACEMENT;
+
+ fromByteArray(test,bytes,"ab",expected,false);
+ fromInputStream(test,bytes,"ab",expected,false);
+ }
+
+ @Test
+ public void testIncompleteSequestAtTheEnd2() throws Exception
+ {
+ byte[] bytes={ 97, 98, 61, -50 };
+ String test=new String(bytes,StandardCharsets.UTF_8);
+ String expected = ""+Utf8Appendable.REPLACEMENT;
+
+ fromByteArray(test,bytes,"ab",expected,false);
+ fromInputStream(test,bytes,"ab",expected,false);
+
+ }
+
+ @Test
+ public void testIncompleteSequestInName() throws Exception
+ {
+ byte[] bytes= { 101, -50, 61, 102, 103, 38, 97, 98, 61, 99, 100 };
+ String test=new String(bytes,StandardCharsets.UTF_8);
+ String name = "e"+Utf8Appendable.REPLACEMENT;
+ String value = "fg";
+
+ fromByteArray(test,bytes,name,value,false);
+ fromInputStream(test,bytes,name,value,false);
+ }
+
+ @Test
+ public void testIncompleteSequestInValue() throws Exception
+ {
+ byte[] bytes= { 101, 102, 61, 103, -50, 38, 97, 98, 61, 99, 100 };
+ String test=new String(bytes,StandardCharsets.UTF_8);
+ String name = "ef";
+ String value = "g"+Utf8Appendable.REPLACEMENT;
+
+ fromByteArray(test,bytes,name,value,false);
+ fromInputStream(test,bytes,name,value,false);
+
+ }
+
+ @Test
+ public void testCorrectUnicode() throws Exception
+ {
+ String chars="a=%u0061";
+ byte[] bytes= chars.getBytes(StandardCharsets.UTF_8);
+ String test=new String(bytes,StandardCharsets.UTF_8);
+ String name = "a";
+ String value = "a";
+
+ fromByteArray(test,bytes,name,value,false);
+ fromInputStream(test,bytes,name,value,false);
+
+ }
+
+ @Test
+ public void testIncompleteUnicode() throws Exception
+ {
+ String chars="a=%u0";
+ byte[] bytes= chars.getBytes(StandardCharsets.UTF_8);
+ String test=new String(bytes,StandardCharsets.UTF_8);
+ String name = "a";
+ String value = ""+Utf8Appendable.REPLACEMENT;
+
+ fromByteArray(test,bytes,name,value,false);
+ fromInputStream(test,bytes,name,value,false);
+
+ }
+
+ @Test
+ public void testIncompletePercent() throws Exception
+ {
+ String chars="a=%A";
+ byte[] bytes= chars.getBytes(StandardCharsets.UTF_8);
+ String test=new String(bytes,StandardCharsets.UTF_8);
+ String name = "a";
+ String value = ""+Utf8Appendable.REPLACEMENT;
+
+ fromByteArray(test,bytes,name,value,false);
+ fromInputStream(test,bytes,name,value,false);
+
+ }
+
+ static void fromByteArray(String test,byte[] b,String field,String expected,boolean thrown) throws Exception
+ {
+ MultiMap<String> values=new MultiMap<>();
+ try
+ {
+ //safeDecodeUtf8To(b, 0, b.length, values);
+ UrlEncoded.decodeUtf8To(b, 0, b.length, values);
+ if (thrown)
+ Assert.fail();
+ Assert.assertEquals(test, expected, values.getString(field));
+ }
+ catch (Exception e)
+ {
+ if (!thrown)
+ throw e;
+ LOG.ignore(e);
+ }
+ }
+
+ static void fromInputStream(String test, byte[] b,String field, String expected,boolean thrown) throws Exception
+ {
+ InputStream is=new ByteArrayInputStream(b);
+ MultiMap<String> values=new MultiMap<>();
+ try
+ {
+ //safeDecodeUtf8To(is, values, 1000000, 10000000);
+ UrlEncoded.decodeUtf8To(is, values, 1000000, 10000000);
+ if (thrown)
+ Assert.fail();
+ Assert.assertEquals(test, expected, values.getString(field));
+ }
+ catch (Exception e)
+ {
+ if (!thrown)
+ throw e;
+ LOG.ignore(e);
+ }
+ }
+
+}
diff --git a/jetty-webapp/pom.xml b/jetty-webapp/pom.xml
index b6812cf..6a62b70 100644
--- a/jetty-webapp/pom.xml
+++ b/jetty-webapp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-webapp</artifactId>
diff --git a/jetty-websocket/javax-websocket-client-impl/pom.xml b/jetty-websocket/javax-websocket-client-impl/pom.xml
index 75986c2..847dc89 100644
--- a/jetty-websocket/javax-websocket-client-impl/pom.xml
+++ b/jetty-websocket/javax-websocket-client-impl/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/AbstractJsrEventDriver.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/AbstractJsrEventDriver.java
index 3b91b38..d7b9ced 100644
--- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/AbstractJsrEventDriver.java
+++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/AbstractJsrEventDriver.java
@@ -31,11 +31,10 @@
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.events.AbstractEventDriver;
-import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.jsr356.JsrSession;
import org.eclipse.jetty.websocket.jsr356.metadata.EndpointMetadata;
-public abstract class AbstractJsrEventDriver extends AbstractEventDriver implements EventDriver
+public abstract class AbstractJsrEventDriver extends AbstractEventDriver
{
protected final EndpointMetadata metadata;
protected final EndpointConfig config;
diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedEventDriver.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedEventDriver.java
index a550c20..0cf9df7 100644
--- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedEventDriver.java
+++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedEventDriver.java
@@ -23,6 +23,7 @@
import java.io.Reader;
import java.nio.ByteBuffer;
import java.util.Map;
+
import javax.websocket.CloseReason;
import javax.websocket.DecodeException;
@@ -31,7 +32,6 @@
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Frame;
-import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.message.MessageInputStream;
import org.eclipse.jetty.websocket.common.message.MessageReader;
import org.eclipse.jetty.websocket.common.message.SimpleBinaryMessage;
@@ -44,7 +44,7 @@
/**
* Base implementation for JSR-356 Annotated event drivers.
*/
-public class JsrAnnotatedEventDriver extends AbstractJsrEventDriver implements EventDriver
+public class JsrAnnotatedEventDriver extends AbstractJsrEventDriver
{
private static final Logger LOG = Log.getLogger(JsrAnnotatedEventDriver.class);
private final JsrEvents<?, ?> events;
diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrEndpointEventDriver.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrEndpointEventDriver.java
index b977147..9ac4906 100644
--- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrEndpointEventDriver.java
+++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrEndpointEventDriver.java
@@ -23,6 +23,7 @@
import java.io.Reader;
import java.nio.ByteBuffer;
import java.util.Map;
+
import javax.websocket.CloseReason;
import javax.websocket.Endpoint;
import javax.websocket.MessageHandler;
@@ -34,7 +35,6 @@
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Frame;
-import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.message.MessageInputStream;
import org.eclipse.jetty.websocket.common.message.MessageReader;
import org.eclipse.jetty.websocket.jsr356.JsrPongMessage;
@@ -49,7 +49,7 @@
/**
* EventDriver for websocket that extend from {@link javax.websocket.Endpoint}
*/
-public class JsrEndpointEventDriver extends AbstractJsrEventDriver implements EventDriver
+public class JsrEndpointEventDriver extends AbstractJsrEventDriver
{
private static final Logger LOG = Log.getLogger(JsrEndpointEventDriver.class);
diff --git a/jetty-websocket/javax-websocket-server-impl/pom.xml b/jetty-websocket/javax-websocket-server-impl/pom.xml
index 0b62c8f..d03b688 100644
--- a/jetty-websocket/javax-websocket-server-impl/pom.xml
+++ b/jetty-websocket/javax-websocket-server-impl/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-websocket/pom.xml b/jetty-websocket/pom.xml
index a955fe0..596020b 100644
--- a/jetty-websocket/pom.xml
+++ b/jetty-websocket/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-websocket/websocket-api/pom.xml b/jetty-websocket/websocket-api/pom.xml
index ba16ff0..716dddb 100644
--- a/jetty-websocket/websocket-api/pom.xml
+++ b/jetty-websocket/websocket-api/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-websocket/websocket-client/pom.xml b/jetty-websocket/websocket-client/pom.xml
index fce652e..5e516d6 100644
--- a/jetty-websocket/websocket-client/pom.xml
+++ b/jetty-websocket/websocket-client/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/ConnectionManager.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/ConnectionManager.java
index da112f9..ab20d77 100644
--- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/ConnectionManager.java
+++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/ConnectionManager.java
@@ -32,6 +32,7 @@
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@@ -158,7 +159,7 @@
sessions.add(session);
}
- private void closeAllConnections()
+ private void shutdownAllConnections()
{
for (WebSocketSession session : sessions)
{
@@ -166,11 +167,13 @@
{
try
{
- session.getConnection().close();
+ session.getConnection().close(
+ StatusCode.SHUTDOWN,
+ "Shutdown");
}
catch (Throwable t)
{
- LOG.debug("During Close All Connections",t);
+ LOG.debug("During Shutdown All Connections",t);
}
}
}
@@ -203,7 +206,7 @@
@Override
protected void doStop() throws Exception
{
- closeAllConnections();
+ shutdownAllConnections();
sessions.clear();
super.doStop();
removeBean(selector);
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 928e911..6616f54 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
@@ -98,7 +98,7 @@
else
{
// Standard "ws://"
- endPoint.setIdleTimeout(connectPromise.getClient().getMaxIdleTimeout());
+ endPoint.setIdleTimeout(connectPromise.getDriver().getPolicy().getIdleTimeout());
return newUpgradeConnection(channel,endPoint,connectPromise);
}
}
@@ -139,4 +139,9 @@
{
this.sslContextFactory = sslContextFactory;
}
+
+ public WebSocketPolicy getPolicy()
+ {
+ return policy;
+ }
}
diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientCloseTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientCloseTest.java
new file mode 100644
index 0000000..3a7f338
--- /dev/null
+++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientCloseTest.java
@@ -0,0 +1,626 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.client;
+
+import static org.hamcrest.Matchers.*;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.io.EofException;
+import org.eclipse.jetty.io.SelectChannelEndPoint;
+import org.eclipse.jetty.io.SelectorManager.ManagedSelector;
+import org.eclipse.jetty.toolchain.test.EventQueue;
+import org.eclipse.jetty.toolchain.test.TestTracker;
+import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.thread.Scheduler;
+import org.eclipse.jetty.websocket.api.ProtocolException;
+import org.eclipse.jetty.websocket.api.Session;
+import org.eclipse.jetty.websocket.api.StatusCode;
+import org.eclipse.jetty.websocket.api.WebSocketAdapter;
+import org.eclipse.jetty.websocket.client.io.ConnectionManager;
+import org.eclipse.jetty.websocket.client.io.WebSocketClientSelectorManager;
+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.WebSocketSession;
+import org.eclipse.jetty.websocket.common.frames.TextFrame;
+import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection;
+import org.eclipse.jetty.websocket.common.test.BlockheadServer;
+import org.eclipse.jetty.websocket.common.test.BlockheadServer.ServerConnection;
+import org.eclipse.jetty.websocket.common.test.IncomingFramesCapture;
+import org.eclipse.jetty.websocket.common.test.RawFrameBuilder;
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class ClientCloseTest
+{
+ private static final Logger LOG = Log.getLogger(ClientCloseTest.class);
+
+ private static class CloseTrackingSocket extends WebSocketAdapter
+ {
+ private static final Logger LOG = Log.getLogger(ClientCloseTest.CloseTrackingSocket.class);
+
+ public int closeCode = -1;
+ public String closeReason = null;
+ public CountDownLatch closeLatch = new CountDownLatch(1);
+ public CountDownLatch openLatch = new CountDownLatch(1);
+
+ public EventQueue<String> messageQueue = new EventQueue<>();
+ public EventQueue<Throwable> errorQueue = new EventQueue<>();
+
+ public void assertNoCloseEvent()
+ {
+ Assert.assertThat("Client Close Event",closeLatch.getCount(),is(1L));
+ Assert.assertThat("Client Close Event Status Code ",closeCode,is(-1));
+ }
+
+ public void assertReceivedCloseEvent(int clientTimeoutMs, Matcher<Integer> statusCodeMatcher, Matcher<String> reasonMatcher)
+ throws InterruptedException
+ {
+ long maxTimeout = clientTimeoutMs * 2;
+
+ Assert.assertThat("Client Close Event Occurred",closeLatch.await(maxTimeout,TimeUnit.MILLISECONDS),is(true));
+ Assert.assertThat("Client Close Event Status Code",closeCode,statusCodeMatcher);
+ if (reasonMatcher == null)
+ {
+ Assert.assertThat("Client Close Event Reason",closeReason,nullValue());
+ }
+ else
+ {
+ Assert.assertThat("Client Close Event Reason",closeReason,reasonMatcher);
+ }
+ }
+
+ public void assertReceivedError(Class<? extends Throwable> expectedThrownClass, Matcher<String> messageMatcher) throws TimeoutException,
+ InterruptedException
+ {
+ errorQueue.awaitEventCount(1,500,TimeUnit.MILLISECONDS);
+ Throwable actual = errorQueue.poll();
+ Assert.assertThat("Client Error Event",actual,instanceOf(expectedThrownClass));
+ if (messageMatcher == null)
+ {
+ Assert.assertThat("Client Error Event Message",actual.getMessage(),nullValue());
+ }
+ else
+ {
+ Assert.assertThat("Client Error Event Message",actual.getMessage(),messageMatcher);
+ }
+ }
+
+ public void clearQueues()
+ {
+ messageQueue.clear();
+ errorQueue.clear();
+ }
+
+ @Override
+ public void onWebSocketClose(int statusCode, String reason)
+ {
+ LOG.debug("onWebSocketClose({},{})",statusCode,reason);
+ super.onWebSocketClose(statusCode,reason);
+ closeCode = statusCode;
+ closeReason = reason;
+ closeLatch.countDown();
+ }
+
+ @Override
+ public void onWebSocketConnect(Session session)
+ {
+ super.onWebSocketConnect(session);
+ openLatch.countDown();
+ }
+
+ @Override
+ public void onWebSocketError(Throwable cause)
+ {
+ LOG.debug("onWebSocketError",cause);
+ Assert.assertThat("Error capture",errorQueue.offer(cause),is(true));
+ }
+
+ @Override
+ public void onWebSocketText(String message)
+ {
+ LOG.debug("onWebSocketText({})",message);
+ messageQueue.offer(message);
+ }
+
+ public EndPoint getEndPoint() throws Exception
+ {
+ Session session = getSession();
+ Assert.assertThat("Session type",session,instanceOf(WebSocketSession.class));
+
+ WebSocketSession wssession = (WebSocketSession)session;
+ Field fld = wssession.getClass().getDeclaredField("connection");
+ fld.setAccessible(true);
+ Assert.assertThat("Field: connection",fld,notNullValue());
+
+ Object val = fld.get(wssession);
+ Assert.assertThat("Connection type",val,instanceOf(AbstractWebSocketConnection.class));
+ @SuppressWarnings("resource")
+ AbstractWebSocketConnection wsconn = (AbstractWebSocketConnection)val;
+ return wsconn.getEndPoint();
+ }
+ }
+
+ @Rule
+ public TestTracker tt = new TestTracker();
+
+ private BlockheadServer server;
+ private WebSocketClient client;
+
+ private void confirmConnection(CloseTrackingSocket clientSocket, Future<Session> clientFuture, ServerConnection serverConn) throws Exception
+ {
+ // Wait for client connect on via future
+ clientFuture.get(500,TimeUnit.MILLISECONDS);
+
+ // Wait for client connect via client websocket
+ Assert.assertThat("Client WebSocket is Open",clientSocket.openLatch.await(500,TimeUnit.MILLISECONDS),is(true));
+
+ try
+ {
+ // Send message from client to server
+ final String echoMsg = "echo-test";
+ Future<Void> testFut = clientSocket.getRemote().sendStringByFuture(echoMsg);
+
+ // Wait for send future
+ testFut.get(500,TimeUnit.MILLISECONDS);
+
+ // Read Frame on server side
+ IncomingFramesCapture serverCapture = serverConn.readFrames(1,500,TimeUnit.MILLISECONDS);
+ serverCapture.assertNoErrors();
+ serverCapture.assertFrameCount(1);
+ WebSocketFrame frame = serverCapture.getFrames().poll();
+ Assert.assertThat("Server received frame",frame.getOpCode(),is(OpCode.TEXT));
+ Assert.assertThat("Server received frame payload",frame.getPayloadAsUTF8(),is(echoMsg));
+
+ // Server send echo reply
+ serverConn.write(new TextFrame().setPayload(echoMsg));
+
+ // Wait for received echo
+ clientSocket.messageQueue.awaitEventCount(1,1,TimeUnit.SECONDS);
+
+ // Verify received message
+ String recvMsg = clientSocket.messageQueue.poll();
+ Assert.assertThat("Received message",recvMsg,is(echoMsg));
+
+ // Verify that there are no errors
+ Assert.assertThat("Error events",clientSocket.errorQueue,empty());
+ }
+ finally
+ {
+ clientSocket.clearQueues();
+ }
+ }
+
+ private void confirmServerReceivedCloseFrame(ServerConnection serverConn, int expectedCloseCode, Matcher<String> closeReasonMatcher) throws IOException,
+ TimeoutException
+ {
+ IncomingFramesCapture serverCapture = serverConn.readFrames(1,500,TimeUnit.MILLISECONDS);
+ serverCapture.assertNoErrors();
+ serverCapture.assertFrameCount(1);
+ serverCapture.assertHasFrame(OpCode.CLOSE,1);
+ WebSocketFrame frame = serverCapture.getFrames().poll();
+ Assert.assertThat("Server received close frame",frame.getOpCode(),is(OpCode.CLOSE));
+ CloseInfo closeInfo = new CloseInfo(frame);
+ Assert.assertThat("Server received close code",closeInfo.getStatusCode(),is(expectedCloseCode));
+ if (closeReasonMatcher == null)
+ {
+ Assert.assertThat("Server received close reason",closeInfo.getReason(),nullValue());
+ }
+ else
+ {
+ Assert.assertThat("Server received close reason",closeInfo.getReason(),closeReasonMatcher);
+ }
+ }
+
+ public static class TestWebSocketClient extends WebSocketClient
+ {
+ @Override
+ protected ConnectionManager newConnectionManager()
+ {
+ return new TestConnectionManager(this);
+ }
+ }
+
+ public static class TestConnectionManager extends ConnectionManager
+ {
+ public TestConnectionManager(WebSocketClient client)
+ {
+ super(client);
+ }
+
+ @Override
+ protected WebSocketClientSelectorManager newWebSocketClientSelectorManager(WebSocketClient client)
+ {
+ return new TestSelectorManager(client);
+ }
+ }
+
+ public static class TestSelectorManager extends WebSocketClientSelectorManager
+ {
+ public TestSelectorManager(WebSocketClient client)
+ {
+ super(client);
+ }
+
+ @Override
+ protected EndPoint newEndPoint(SocketChannel channel, ManagedSelector selectSet, SelectionKey selectionKey) throws IOException
+ {
+ return new TestEndPoint(channel,selectSet,selectionKey,getScheduler(),getPolicy().getIdleTimeout());
+ }
+ }
+
+ public static class TestEndPoint extends SelectChannelEndPoint
+ {
+ public AtomicBoolean congestedFlush = new AtomicBoolean(false);
+
+ public TestEndPoint(SocketChannel channel, ManagedSelector selector, SelectionKey key, Scheduler scheduler, long idleTimeout)
+ {
+ super(channel,selector,key,scheduler,idleTimeout);
+ }
+
+ @Override
+ public boolean flush(ByteBuffer... buffers) throws IOException
+ {
+ boolean flushed = super.flush(buffers);
+ congestedFlush.set(!flushed);
+ return flushed;
+ }
+ }
+
+ @Before
+ public void startClient() throws Exception
+ {
+ client = new TestWebSocketClient();
+ client.start();
+ }
+
+ @Before
+ public void startServer() throws Exception
+ {
+ server = new BlockheadServer();
+ server.start();
+ }
+
+ @After
+ public void stopClient() throws Exception
+ {
+ if (client.isRunning())
+ {
+ client.stop();
+ }
+ }
+
+ @After
+ public void stopServer() throws Exception
+ {
+ server.stop();
+ }
+
+ @Test
+ public void testHalfClose() throws Exception
+ {
+ // Set client timeout
+ final int timeout = 1000;
+ client.setMaxIdleTimeout(timeout);
+
+ // Client connects
+ CloseTrackingSocket clientSocket = new CloseTrackingSocket();
+ Future<Session> clientConnectFuture = client.connect(clientSocket,server.getWsUri());
+
+ // Server accepts connect
+ ServerConnection serverConn = server.accept();
+ serverConn.upgrade();
+
+ // client confirms connection via echo
+ confirmConnection(clientSocket,clientConnectFuture,serverConn);
+
+ // client sends close frame (code 1000, normal)
+ final String origCloseReason = "Normal Close";
+ clientSocket.getSession().close(StatusCode.NORMAL,origCloseReason);
+
+ // server receives close frame
+ confirmServerReceivedCloseFrame(serverConn,StatusCode.NORMAL,is(origCloseReason));
+
+ // server sends 2 messages
+ serverConn.write(new TextFrame().setPayload("Hello"));
+ serverConn.write(new TextFrame().setPayload("World"));
+
+ // server sends close frame (code 1000, no reason)
+ CloseInfo sclose = new CloseInfo(StatusCode.NORMAL,"From Server");
+ serverConn.write(sclose.asFrame());
+
+ // client receives 2 messages
+ clientSocket.messageQueue.awaitEventCount(2,1,TimeUnit.SECONDS);
+
+ // Verify received messages
+ String recvMsg = clientSocket.messageQueue.poll();
+ Assert.assertThat("Received message 1",recvMsg,is("Hello"));
+ recvMsg = clientSocket.messageQueue.poll();
+ Assert.assertThat("Received message 2",recvMsg,is("World"));
+
+ // Verify that there are no errors
+ Assert.assertThat("Error events",clientSocket.errorQueue,empty());
+
+ // client close event on ws-endpoint
+ clientSocket.assertReceivedCloseEvent(timeout,is(StatusCode.NORMAL),containsString("From Server"));
+ }
+
+ @Test
+ public void testNetworkCongestion() throws Exception
+ {
+ // Set client timeout
+ final int timeout = 1000;
+ client.setMaxIdleTimeout(timeout);
+
+ // Client connects
+ CloseTrackingSocket clientSocket = new CloseTrackingSocket();
+ Future<Session> clientConnectFuture = client.connect(clientSocket,server.getWsUri());
+
+ // Server accepts connect
+ ServerConnection serverConn = server.accept();
+ serverConn.upgrade();
+
+ // client confirms connection via echo
+ confirmConnection(clientSocket,clientConnectFuture,serverConn);
+
+ // client sends BIG frames (until it cannot write anymore)
+ // server must not read (for test purpose, in order to congest connection)
+ // when write is congested, client enqueue close frame
+ // client initiate write, but write never completes
+ EndPoint endp = clientSocket.getEndPoint();
+ Assert.assertThat("EndPoint is testable",endp,instanceOf(TestEndPoint.class));
+ TestEndPoint testendp = (TestEndPoint)endp;
+
+ char msg[] = new char[10240];
+ int writeCount = 0;
+ long writeSize = 0;
+ int i = 0;
+ while (!testendp.congestedFlush.get())
+ {
+ int z = i - ((i / 26) * 26);
+ char c = (char)('a' + z);
+ Arrays.fill(msg,c);
+ clientSocket.getRemote().sendStringByFuture(String.valueOf(msg));
+ writeCount++;
+ writeSize += msg.length;
+ }
+ LOG.debug("Wrote {} frames totalling {} bytes of payload before congestion kicked in",writeCount,writeSize);
+
+ // Verify that there are no errors
+ Assert.assertThat("Error events",clientSocket.errorQueue,empty());
+
+ // client idle timeout triggers close event on client ws-endpoint
+ // client close event on ws-endpoint
+ clientSocket.assertReceivedCloseEvent(timeout,is(StatusCode.ABNORMAL),containsString("Timeout"));
+ }
+
+ @Test
+ public void testProtocolException() throws Exception
+ {
+ // Set client timeout
+ final int timeout = 1000;
+ client.setMaxIdleTimeout(timeout);
+
+ // Client connects
+ CloseTrackingSocket clientSocket = new CloseTrackingSocket();
+ Future<Session> clientConnectFuture = client.connect(clientSocket,server.getWsUri());
+
+ // Server accepts connect
+ ServerConnection serverConn = server.accept();
+ serverConn.upgrade();
+
+ // client confirms connection via echo
+ confirmConnection(clientSocket,clientConnectFuture,serverConn);
+
+ // client should not have received close message (yet)
+ clientSocket.assertNoCloseEvent();
+
+ // server sends bad close frame (too big of a reason message)
+ byte msg[] = new byte[400];
+ Arrays.fill(msg,(byte)'x');
+ ByteBuffer bad = ByteBuffer.allocate(500);
+ RawFrameBuilder.putOpFin(bad,OpCode.CLOSE,true);
+ RawFrameBuilder.putLength(bad,msg.length + 2,false);
+ bad.putShort((short)StatusCode.NORMAL);
+ bad.put(msg);
+ BufferUtil.flipToFlush(bad,0);
+ serverConn.write(bad);
+
+ // client should have noticed the error
+ clientSocket.assertReceivedError(ProtocolException.class,containsString("Invalid control frame"));
+
+ // client parse invalid frame, notifies server of close (protocol error)
+ confirmServerReceivedCloseFrame(serverConn,StatusCode.PROTOCOL,allOf(containsString("Invalid control frame"),containsString("length")));
+
+ // server disconnects
+ serverConn.disconnect();
+
+ // client triggers close event on client ws-endpoint
+ clientSocket.assertReceivedCloseEvent(timeout,is(StatusCode.PROTOCOL),allOf(containsString("Invalid control frame"),containsString("length")));
+ }
+
+ @Test
+ public void testReadEOF() throws Exception
+ {
+ // Set client timeout
+ final int timeout = 1000;
+ client.setMaxIdleTimeout(timeout);
+
+ // Client connects
+ CloseTrackingSocket clientSocket = new CloseTrackingSocket();
+ Future<Session> clientConnectFuture = client.connect(clientSocket,server.getWsUri());
+
+ // Server accepts connect
+ ServerConnection serverConn = server.accept();
+ serverConn.upgrade();
+
+ // client confirms connection via echo
+ confirmConnection(clientSocket,clientConnectFuture,serverConn);
+
+ // client sends close frame
+ final String origCloseReason = "Normal Close";
+ clientSocket.getSession().close(StatusCode.NORMAL,origCloseReason);
+
+ // server receives close frame
+ confirmServerReceivedCloseFrame(serverConn,StatusCode.NORMAL,is(origCloseReason));
+
+ // client should not have received close message (yet)
+ clientSocket.assertNoCloseEvent();
+
+ // server shuts down connection (no frame reply)
+ serverConn.disconnect();
+
+ // client reads -1 (EOF)
+ // client triggers close event on client ws-endpoint
+ clientSocket.assertReceivedCloseEvent(timeout,is(StatusCode.ABNORMAL),containsString("EOF"));
+ }
+
+ @Test
+ public void testServerNoCloseHandshake() throws Exception
+ {
+ // Set client timeout
+ final int timeout = 1000;
+ client.setMaxIdleTimeout(timeout);
+
+ // Client connects
+ CloseTrackingSocket clientSocket = new CloseTrackingSocket();
+ Future<Session> clientConnectFuture = client.connect(clientSocket,server.getWsUri());
+
+ // Server accepts connect
+ ServerConnection serverConn = server.accept();
+ serverConn.upgrade();
+
+ // client confirms connection via echo
+ confirmConnection(clientSocket,clientConnectFuture,serverConn);
+
+ // client sends close frame
+ final String origCloseReason = "Normal Close";
+ clientSocket.getSession().close(StatusCode.NORMAL,origCloseReason);
+
+ // server receives close frame
+ confirmServerReceivedCloseFrame(serverConn,StatusCode.NORMAL,is(origCloseReason));
+
+ // client should not have received close message (yet)
+ clientSocket.assertNoCloseEvent();
+
+ // server never sends close frame handshake
+ // server sits idle
+
+ // client idle timeout triggers close event on client ws-endpoint
+ // assert - close code==1006 (abnormal)
+ // assert - close reason message contains (timeout)
+ clientSocket.assertReceivedCloseEvent(timeout,is(StatusCode.ABNORMAL),containsString("Timeout"));
+ }
+
+ @Test
+ public void testStopLifecycle() throws Exception
+ {
+ // Set client timeout
+ final int timeout = 1000;
+ client.setMaxIdleTimeout(timeout);
+
+ int clientCount = 3;
+ CloseTrackingSocket clientSockets[] = new CloseTrackingSocket[clientCount];
+ ServerConnection serverConns[] = new ServerConnection[clientCount];
+
+ // Connect Multiple Clients
+ for (int i = 0; i < clientCount; i++)
+ {
+ // Client Request Upgrade
+ clientSockets[i] = new CloseTrackingSocket();
+ Future<Session> clientConnectFuture = client.connect(clientSockets[i],server.getWsUri());
+
+ // Server accepts connection
+ serverConns[i] = server.accept();
+ serverConns[i].upgrade();
+
+ // client confirms connection via echo
+ confirmConnection(clientSockets[i],clientConnectFuture,serverConns[i]);
+ }
+
+ // client lifecycle stop
+ client.stop();
+
+ // clients send close frames (code 1001, shutdown)
+ for (int i = 0; i < clientCount; i++)
+ {
+ // server receives close frame
+ confirmServerReceivedCloseFrame(serverConns[i],StatusCode.SHUTDOWN,containsString("Shutdown"));
+ }
+
+ // clients disconnect
+ for (int i = 0; i < clientCount; i++)
+ {
+ clientSockets[i].assertReceivedCloseEvent(timeout,is(StatusCode.SHUTDOWN),containsString("Shutdown"));
+ }
+ }
+
+ @Test
+ public void testWriteException() throws Exception
+ {
+ // Set client timeout
+ final int timeout = 1000;
+ client.setMaxIdleTimeout(timeout);
+
+ // Client connects
+ CloseTrackingSocket clientSocket = new CloseTrackingSocket();
+ Future<Session> clientConnectFuture = client.connect(clientSocket,server.getWsUri());
+
+ // Server accepts connect
+ ServerConnection serverConn = server.accept();
+ serverConn.upgrade();
+
+ // client confirms connection via echo
+ confirmConnection(clientSocket,clientConnectFuture,serverConn);
+
+ // setup client endpoint for write failure (test only)
+ EndPoint endp = clientSocket.getEndPoint();
+ endp.shutdownOutput();
+
+ // client enqueue close frame
+ // client write failure
+ final String origCloseReason = "Normal Close";
+ clientSocket.getSession().close(StatusCode.NORMAL,origCloseReason);
+
+ clientSocket.assertReceivedError(EofException.class,null);
+
+ // client triggers close event on client ws-endpoint
+ // assert - close code==1006 (abnormal)
+ // assert - close reason message contains (write failure)
+ clientSocket.assertReceivedCloseEvent(timeout,is(StatusCode.ABNORMAL),containsString("EOF"));
+ }
+}
diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerWriteThread.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerWriteThread.java
index e06e883..2cea2fd 100644
--- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerWriteThread.java
+++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerWriteThread.java
@@ -19,7 +19,6 @@
package org.eclipse.jetty.websocket.client;
import java.io.IOException;
-import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -32,7 +31,6 @@
{
private static final Logger LOG = Log.getLogger(ServerWriteThread.class);
private final ServerConnection conn;
- private Exchanger<String> exchanger;
private int slowness = -1;
private int messageCount = 100;
private String message = "Hello";
@@ -42,11 +40,6 @@
this.conn = conn;
}
- public Exchanger<String> getExchanger()
- {
- return exchanger;
- }
-
public String getMessage()
{
return message;
@@ -73,12 +66,6 @@
{
conn.write(new TextFrame().setPayload(message));
- if (exchanger != null)
- {
- // synchronized on exchange
- exchanger.exchange(message);
- }
-
m.incrementAndGet();
if (slowness > 0)
@@ -93,11 +80,6 @@
}
}
- public void setExchanger(Exchanger<String> exchanger)
- {
- this.exchanger = exchanger;
- }
-
public void setMessage(String message)
{
this.message = message;
diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SlowServerTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SlowServerTest.java
index 80720f3..4f56ec6 100644
--- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SlowServerTest.java
+++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SlowServerTest.java
@@ -49,7 +49,7 @@
public void startClient() throws Exception
{
client = new WebSocketClient();
- client.getPolicy().setIdleTimeout(60000);
+ client.setMaxIdleTimeout(60000);
client.start();
}
@@ -78,7 +78,7 @@
{
JettyTrackingSocket tsocket = new JettyTrackingSocket();
client.setMasker(new ZeroMasker());
- client.getPolicy().setIdleTimeout(60000);
+ client.setMaxIdleTimeout(60000);
URI wsUri = server.getWsUri();
Future<Session> future = client.connect(tsocket,wsUri);
@@ -123,41 +123,38 @@
@Slow
public void testServerSlowToSend() throws Exception
{
- // final Exchanger<String> exchanger = new Exchanger<String>();
- JettyTrackingSocket tsocket = new JettyTrackingSocket();
- // tsocket.messageExchanger = exchanger;
+ JettyTrackingSocket clientSocket = new JettyTrackingSocket();
client.setMasker(new ZeroMasker());
- client.getPolicy().setIdleTimeout(60000);
+ client.setMaxIdleTimeout(60000);
URI wsUri = server.getWsUri();
- Future<Session> future = client.connect(tsocket,wsUri);
+ Future<Session> clientConnectFuture = client.connect(clientSocket,wsUri);
- ServerConnection sconnection = server.accept();
- sconnection.setSoTimeout(60000);
- sconnection.upgrade();
+ ServerConnection serverConn = server.accept();
+ serverConn.setSoTimeout(60000);
+ serverConn.upgrade();
// Confirm connected
- future.get(500,TimeUnit.MILLISECONDS);
- tsocket.waitForConnected(500,TimeUnit.MILLISECONDS);
+ clientConnectFuture.get(500,TimeUnit.MILLISECONDS);
+ clientSocket.waitForConnected(500,TimeUnit.MILLISECONDS);
// Have server write slowly.
int messageCount = 1000;
- ServerWriteThread writer = new ServerWriteThread(sconnection);
+ ServerWriteThread writer = new ServerWriteThread(serverConn);
writer.setMessageCount(messageCount);
writer.setMessage("Hello");
- // writer.setExchanger(exchanger);
writer.setSlowness(10);
writer.start();
writer.join();
// Verify receive
- Assert.assertThat("Message Receive Count",tsocket.messageQueue.size(),is(messageCount));
+ Assert.assertThat("Message Receive Count",clientSocket.messageQueue.size(),is(messageCount));
// Close
- sconnection.close(StatusCode.NORMAL);
+ serverConn.close(StatusCode.NORMAL);
- Assert.assertTrue("Client Socket Closed",tsocket.closeLatch.await(10,TimeUnit.SECONDS));
- tsocket.assertCloseCode(StatusCode.NORMAL);
+ Assert.assertTrue("Client Socket Closed",clientSocket.closeLatch.await(10,TimeUnit.SECONDS));
+ clientSocket.assertCloseCode(StatusCode.NORMAL);
}
}
diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/TimeoutTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/TimeoutTest.java
deleted file mode 100644
index 72c1fc1..0000000
--- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/TimeoutTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2014 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.client;
-
-import static org.hamcrest.Matchers.lessThanOrEqualTo;
-
-import java.net.URI;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jetty.toolchain.test.TestTracker;
-import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.StatusCode;
-import org.eclipse.jetty.websocket.common.test.BlockheadServer;
-import org.eclipse.jetty.websocket.common.test.BlockheadServer.ServerConnection;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-/**
- * Various tests for Timeout handling
- */
-public class TimeoutTest
-{
- @Rule
- public TestTracker tt = new TestTracker();
-
- private BlockheadServer server;
- private WebSocketClient client;
-
- @Before
- public void startClient() throws Exception
- {
- client = new WebSocketClient();
- client.getPolicy().setIdleTimeout(250); // idle timeout (for all tests here)
- client.start();
- }
-
- @Before
- public void startServer() throws Exception
- {
- server = new BlockheadServer();
- server.start();
- }
-
- @After
- public void stopClient() throws Exception
- {
- client.stop();
- }
-
- @After
- public void stopServer() throws Exception
- {
- server.stop();
- }
-
- /**
- * In a situation where the upgrade/connection is successful, and there is no activity for a while, the idle timeout triggers on the client side and
- * automatically initiates a close handshake.
- */
- @Test
- public void testIdleDetectedByClient() throws Exception
- {
- JettyTrackingSocket wsocket = new JettyTrackingSocket();
-
- URI wsUri = server.getWsUri();
- client.setMaxIdleTimeout(1000);
- Future<Session> future = client.connect(wsocket,wsUri);
-
- ServerConnection ssocket = server.accept();
- ssocket.upgrade();
-
- try
- {
- ssocket.startEcho();
- // Validate that connect occurred
- future.get(500,TimeUnit.MILLISECONDS);
- wsocket.waitForConnected(500,TimeUnit.MILLISECONDS);
-
- // Wait for inactivity idle timeout.
- long start = System.currentTimeMillis();
- wsocket.waitForClose(2,TimeUnit.SECONDS);
- long end = System.currentTimeMillis();
- long dur = (end - start);
- // Make sure idle timeout takes less than 5 total seconds
- Assert.assertThat("Idle Timeout",dur,lessThanOrEqualTo(3000L));
-
- // Client should see a close event, with abnormal status NO_CLOSE
- wsocket.assertCloseCode(StatusCode.ABNORMAL);
- }
- finally
- {
- ssocket.stopEcho();
- }
- }
-}
diff --git a/jetty-websocket/websocket-client/src/test/resources/jetty-logging.properties b/jetty-websocket/websocket-client/src/test/resources/jetty-logging.properties
index 7c9bd36..9668b13 100644
--- a/jetty-websocket/websocket-client/src/test/resources/jetty-logging.properties
+++ b/jetty-websocket/websocket-client/src/test/resources/jetty-logging.properties
@@ -1,12 +1,17 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.LEVEL=WARN
# org.eclipse.jetty.LEVEL=DEBUG
-# org.eclipse.jetty.io.ChannelEndPoint.LEVEL=INFO
+# org.eclipse.jetty.io.ChannelEndPoint.LEVEL=DEBUG
+# org.eclipse.jetty.io.SelectChannelEndPoint.LEVEL=DEBUG
+# org.eclipse.jetty.io.IdleTimeout.LEVEL=DEBUG
+# org.eclipse.jetty.io.FillInterest.LEVEL=DEBUG
+# org.eclipse.jetty.io.AbstractConnection.LEVEL=DEBUG
# org.eclipse.jetty.websocket.LEVEL=WARN
# org.eclipse.jetty.websocket.LEVEL=DEBUG
# org.eclipse.jetty.websocket.client.LEVEL=DEBUG
# org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.LEVEL=DEBUG
-# org.eclipse.jetty.websocket.common.io.WriteBytesProvider.LEVEL=DEBUG
+# org.eclipse.jetty.websocket.common.io.IOState.LEVEL=DEBUG
+
# org.eclipse.jetty.websocket.common.Generator.LEVEL=DEBUG
# org.eclipse.jetty.websocket.common.Parser.LEVEL=DEBUG
# org.eclipse.jetty.websocket.client.TrackingSocket.LEVEL=DEBUG
diff --git a/jetty-websocket/websocket-common/pom.xml b/jetty-websocket/websocket-common/pom.xml
index ada7d5c..7a7fa30 100644
--- a/jetty-websocket/websocket-common/pom.xml
+++ b/jetty-websocket/websocket-common/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/CloseInfo.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/CloseInfo.java
index 03a737c..f14c252 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/CloseInfo.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/CloseInfo.java
@@ -20,6 +20,7 @@
import java.nio.ByteBuffer;
+import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception;
import org.eclipse.jetty.util.Utf8StringBuilder;
@@ -65,7 +66,8 @@
statusCode |= (data.get() & 0xFF) << 8;
statusCode |= (data.get() & 0xFF);
- if(validate) {
+ if (validate)
+ {
if ((statusCode < StatusCode.NORMAL) || (statusCode == StatusCode.UNDEFINED) || (statusCode == StatusCode.NO_CLOSE)
|| (statusCode == StatusCode.NO_CODE) || ((statusCode > 1011) && (statusCode <= 2999)) || (statusCode >= 5000))
{
@@ -120,7 +122,7 @@
public CloseInfo(int statusCode)
{
- this(statusCode, null);
+ this(statusCode,null);
}
public CloseInfo(int statusCode, String reason)
@@ -144,8 +146,9 @@
utf = StringUtil.getUtf8Bytes(reason);
len += utf.length;
}
-
- ByteBuffer buf = ByteBuffer.allocate(len);
+
+ ByteBuffer buf = BufferUtil.allocate(len);
+ BufferUtil.flipToFill(buf);
buf.put((byte)((statusCode >>> 8) & 0xFF));
buf.put((byte)((statusCode >>> 0) & 0xFF));
@@ -153,7 +156,7 @@
{
buf.put(utf,0,utf.length);
}
- buf.flip();
+ BufferUtil.flipToFlush(buf,0);
return buf;
}
@@ -162,7 +165,14 @@
{
CloseFrame frame = new CloseFrame();
frame.setFin(true);
- frame.setPayload(asByteBuffer());
+ if ((statusCode >= 1000) && (statusCode != StatusCode.NO_CLOSE) && (statusCode != StatusCode.NO_CODE))
+ {
+ if (statusCode == StatusCode.FAILED_TLS_HANDSHAKE)
+ {
+ throw new ProtocolException("Close Frame with status code " + statusCode + " not allowed (per RFC6455)");
+ }
+ frame.setPayload(asByteBuffer());
+ }
return frame;
}
@@ -180,10 +190,10 @@
{
return !((statusCode == StatusCode.NORMAL) || (statusCode == StatusCode.NO_CODE));
}
-
+
public boolean isAbnormal()
{
- return (statusCode == StatusCode.ABNORMAL);
+ return (statusCode != StatusCode.NORMAL);
}
@Override
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Parser.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Parser.java
index 0cf7e5f..86195a0 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Parser.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Parser.java
@@ -96,8 +96,9 @@
private void assertSanePayloadLength(long len)
{
- if (LOG.isDebugEnabled())
- LOG.debug("Payload Length: {} - {}",len,this);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("{} Payload Length: {} - {}",policy.getBehavior(),len,this);
+ }
// Since we use ByteBuffer so often, having lengths over Integer.MAX_VALUE is really impossible.
if (len > Integer.MAX_VALUE)
@@ -239,7 +240,7 @@
incomingFramesHandler.incomingError(e);
}
- public void parse(ByteBuffer buffer)
+ public void parse(ByteBuffer buffer) throws WebSocketException
{
if (buffer.remaining() <= 0)
{
@@ -266,13 +267,20 @@
{
buffer.position(buffer.limit()); // consume remaining
reset();
+ // let session know
notifyWebSocketException(e);
+ // need to throw for proper close behavior in connection
+ throw e;
}
catch (Throwable t)
{
buffer.position(buffer.limit()); // consume remaining
reset();
- notifyWebSocketException(new WebSocketException(t));
+ // let session know
+ WebSocketException e = new WebSocketException(t);
+ notifyWebSocketException(e);
+ // need to throw for proper close behavior in connection
+ throw e;
}
}
@@ -299,7 +307,9 @@
private boolean parseFrame(ByteBuffer buffer)
{
if (LOG.isDebugEnabled())
+ {
LOG.debug("{} Parsing {} bytes",policy.getBehavior(),buffer.remaining());
+ }
while (buffer.hasRemaining())
{
switch (state)
@@ -318,7 +328,8 @@
}
if (LOG.isDebugEnabled())
- LOG.debug("OpCode {}, fin={} rsv={}{}{}",
+ LOG.debug("{} OpCode {}, fin={} rsv={}{}{}",
+ policy.getBehavior(),
OpCode.name(opcode),
fin,
(isRsv1InUse()?'1':'.'),
@@ -412,11 +423,6 @@
throw new ProtocolException("RSV3 not allowed to be set");
}
}
- else
- {
- if (LOG.isDebugEnabled())
- LOG.debug("OpCode {}, fin={} rsv=000",OpCode.name(opcode),fin);
- }
state = State.PAYLOAD_LEN;
break;
@@ -591,8 +597,9 @@
buffer.limit(limit);
buffer.position(buffer.position() + window.remaining());
- if (LOG.isDebugEnabled())
- LOG.debug("Window: {}",BufferUtil.toDetailString(window));
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("{} Window: {}",policy.getBehavior(),BufferUtil.toDetailString(window));
+ }
maskProcessor.process(window);
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 e038e4d..04637e3 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
@@ -41,6 +41,7 @@
import org.eclipse.jetty.websocket.api.SuspendToken;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;
+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.ExtensionFactory;
@@ -90,20 +91,19 @@
@Override
public void close()
{
- this.close(StatusCode.NORMAL, null);
+ this.close(StatusCode.NORMAL,null);
}
@Override
public void close(CloseStatus closeStatus)
{
- this.close(closeStatus.getCode(), closeStatus.getPhrase());
+ this.close(closeStatus.getCode(),closeStatus.getPhrase());
}
@Override
public void close(int statusCode, String reason)
{
- connection.close(statusCode, reason);
- notifyClose(statusCode, reason);
+ connection.close(statusCode,reason);
}
/**
@@ -115,7 +115,7 @@
connection.disconnect();
// notify of harsh disconnect
- notifyClose(StatusCode.NO_CLOSE, "Harsh disconnect");
+ notifyClose(StatusCode.NO_CLOSE,"Harsh disconnect");
}
public void dispatch(Runnable runnable)
@@ -130,7 +130,7 @@
out.append(indent).append(" +- incomingHandler : ");
if (incomingHandler instanceof Dumpable)
{
- ((Dumpable)incomingHandler).dump(out, indent + " ");
+ ((Dumpable)incomingHandler).dump(out,indent + " ");
}
else
{
@@ -140,7 +140,7 @@
out.append(indent).append(" +- outgoingHandler : ");
if (outgoingHandler instanceof Dumpable)
{
- ((Dumpable)outgoingHandler).dump(out, indent + " ");
+ ((Dumpable)outgoingHandler).dump(out,indent + " ");
}
else
{
@@ -273,7 +273,7 @@
{
final int prime = 31;
int result = 1;
- result = (prime * result) + ((connection == null) ? 0 : connection.hashCode());
+ result = (prime * result) + ((connection == null)?0:connection.hashCode());
return result;
}
@@ -328,7 +328,11 @@
public void notifyClose(int statusCode, String reason)
{
- websocket.onClose(new CloseInfo(statusCode, reason));
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("notifyClose({},{})",statusCode,reason);
+ }
+ websocket.onClose(new CloseInfo(statusCode,reason));
}
public void notifyError(Throwable cause)
@@ -342,12 +346,13 @@
{
switch (state)
{
- case CLOSING:
+ case CLOSED:
// notify session listeners
for (SessionListener listener : sessionListeners)
{
try
{
+ LOG.debug("{}.onSessionClosed()",listener.getClass().getSimpleName());
listener.onSessionClosed(this);
}
catch (Throwable t)
@@ -355,18 +360,10 @@
LOG.ignore(t);
}
}
- break;
- case CLOSED:
IOState ioState = this.connection.getIOState();
- // The session only cares about abnormal close, as we need to notify
- // the endpoint of this close scenario.
- if (ioState.wasAbnormalClose())
- {
- CloseInfo close = ioState.getCloseInfo();
- LOG.debug("Detected abnormal close: {}", close);
- // notify local endpoint
- notifyClose(close.getStatusCode(), close.getReason());
- }
+ CloseInfo close = ioState.getCloseInfo();
+ // confirmed close of local endpoint
+ notifyClose(close.getStatusCode(),close.getReason());
break;
case OPEN:
// notify session listeners
@@ -400,17 +397,32 @@
connection.getIOState().onConnected();
// Connect remote
- remote = new WebSocketRemoteEndpoint(connection, outgoingHandler, getBatchMode());
+ remote = new WebSocketRemoteEndpoint(connection,outgoingHandler,getBatchMode());
- // Open WebSocket
- websocket.openSession(this);
-
- // Open connection
- connection.getIOState().onOpened();
-
- if (LOG.isDebugEnabled())
+ try
{
- LOG.debug("open -> {}", dump());
+ // Open WebSocket
+ websocket.openSession(this);
+
+ // Open connection
+ connection.getIOState().onOpened();
+
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("open -> {}",dump());
+ }
+ }
+ catch (Throwable t)
+ {
+ // Exception on end-user WS-Endpoint.
+ // Fast-fail & close connection with reason.
+ int statusCode = StatusCode.SERVER_ERROR;
+ if(policy.getBehavior() == WebSocketBehavior.CLIENT)
+ {
+ statusCode = StatusCode.POLICY_VIOLATION;
+ }
+
+ close(statusCode,t.getMessage());
}
}
@@ -450,11 +462,11 @@
List<String> values = entry.getValue();
if (values != null)
{
- this.parameterMap.put(entry.getKey(), values.toArray(new String[values.size()]));
+ this.parameterMap.put(entry.getKey(),values.toArray(new String[values.size()]));
}
else
{
- this.parameterMap.put(entry.getKey(), new String[0]);
+ this.parameterMap.put(entry.getKey(),new String[0]);
}
}
}
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/AbstractEventDriver.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/AbstractEventDriver.java
index 46a6612..7a55b2d 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/AbstractEventDriver.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/AbstractEventDriver.java
@@ -88,13 +88,7 @@
{
if (LOG.isDebugEnabled())
{
- LOG.debug("incoming(WebSocketException)",e);
- }
-
- if (e instanceof CloseException)
- {
- CloseException close = (CloseException)e;
- terminateConnection(close.getStatusCode(),close.getMessage());
+ LOG.debug("incomingError(" + e.getClass().getName() + ")",e);
}
onError(e);
@@ -105,7 +99,7 @@
{
if (LOG.isDebugEnabled())
{
- LOG.debug("{}.onFrame({})",websocket.getClass().getSimpleName(),frame);
+ LOG.debug("incomingFrame({})",frame);
}
try
@@ -121,9 +115,6 @@
CloseFrame closeframe = (CloseFrame)frame;
CloseInfo close = new CloseInfo(closeframe,validate);
- // notify user websocket pojo
- onClose(close);
-
// process handshake
session.getConnection().getIOState().onCloseRemote(close);
@@ -229,6 +220,7 @@
catch (Throwable t)
{
unhandled(t);
+ throw t;
}
}
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java
index 1576339..cea5909 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java
@@ -32,7 +32,6 @@
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.ByteBufferPool;
-import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
@@ -54,13 +53,13 @@
import org.eclipse.jetty.websocket.common.ConnectionState;
import org.eclipse.jetty.websocket.common.Generator;
import org.eclipse.jetty.websocket.common.LogicalConnection;
+import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.io.IOState.ConnectionStateListener;
/**
- * Provides the implementation of {@link LogicalConnection} within the
- * framework of the new {@link Connection} framework of {@code jetty-io}.
+ * Provides the implementation of {@link LogicalConnection} within the framework of the new {@link Connection} framework of {@code jetty-io}.
*/
public abstract class AbstractWebSocketConnection extends AbstractConnection implements LogicalConnection, ConnectionStateListener, Dumpable
{
@@ -68,7 +67,7 @@
{
private Flusher(ByteBufferPool bufferPool, Generator generator, EndPoint endpoint)
{
- super(bufferPool, generator, endpoint, getPolicy().getMaxBinaryMessageBufferSize(), 8);
+ super(bufferPool,generator,endpoint,getPolicy().getMaxBinaryMessageBufferSize(),8);
}
@Override
@@ -106,7 +105,7 @@
// Abnormal Close
reason = CloseStatus.trimMaxReasonLength(reason);
session.notifyError(x);
- session.notifyClose(StatusCode.NO_CLOSE,reason);
+ session.notifyClose(StatusCode.ABNORMAL,reason);
disconnect(); // disconnect endpoint & connection
}
@@ -114,16 +113,23 @@
public class OnDisconnectCallback implements WriteCallback
{
+ private final boolean outputOnly;
+
+ public OnDisconnectCallback(boolean outputOnly)
+ {
+ this.outputOnly = outputOnly;
+ }
+
@Override
public void writeFailed(Throwable x)
{
- disconnect();
+ disconnect(outputOnly);
}
@Override
public void writeSuccess()
{
- disconnect();
+ disconnect(outputOnly);
}
}
@@ -212,10 +218,10 @@
@Override
public void close(int statusCode, String reason)
{
+ LOG.debug("close({},{})",statusCode,reason);
CloseInfo close = new CloseInfo(statusCode,reason);
if (statusCode == StatusCode.ABNORMAL)
{
- flusher.close(); // TODO this makes the IdleTimeoutTest pass, but I'm dubious it is the correct way
ioState.onAbnormalClose(close);
}
else
@@ -224,7 +230,6 @@
}
}
-
@Override
public void disconnect()
{
@@ -360,7 +365,9 @@
@Override
public void onClose()
{
+ LOG.debug("{} onClose()",policy.getBehavior());
super.onClose();
+ // ioState.onDisconnected();
flusher.close();
}
@@ -379,18 +386,15 @@
{
// Fire out a close frame, indicating abnormal shutdown, then disconnect
CloseInfo abnormal = new CloseInfo(StatusCode.SHUTDOWN,"Abnormal Close - " + ioState.getCloseInfo().getReason());
- outgoingFrame(abnormal.asFrame(),new OnDisconnectCallback(), BatchMode.OFF);
+ outgoingFrame(abnormal.asFrame(),new OnDisconnectCallback(false),BatchMode.OFF);
}
- else
- {
- // Just disconnect
- this.disconnect();
- }
+ // Just disconnect
+ this.disconnect(false);
break;
case CLOSING:
CloseInfo close = ioState.getCloseInfo();
- // append close frame
- outgoingFrame(close.asFrame(),new OnDisconnectCallback(), BatchMode.OFF);
+ // reply to close handshake from remote
+ outgoingFrame(close.asFrame(),new OnDisconnectCallback(true),BatchMode.OFF);
default:
break;
}
@@ -441,20 +445,26 @@
@Override
protected boolean onReadTimeout()
{
- LOG.debug("{} Read Timeout",policy.getBehavior());
-
IOState state = getIOState();
- if ((state.getConnectionState() == ConnectionState.CLOSING) || (state.getConnectionState() == ConnectionState.CLOSED))
+ ConnectionState cstate = state.getConnectionState();
+ LOG.debug("{} Read Timeout - {}",policy.getBehavior(),cstate);
+
+ if (cstate == ConnectionState.CLOSED)
{
- // close already initiated, extra timeouts not relevant
+ // close already completed, extra timeouts not relevant
// allow underlying connection and endpoint to disconnect on its own
return true;
}
- // Initiate close - politely send close frame.
- session.notifyError(new SocketTimeoutException("Timeout on Read"));
- // This is an Abnormal Close condition
- close(StatusCode.ABNORMAL,"Idle Timeout");
+ try
+ {
+ session.notifyError(new SocketTimeoutException("Timeout on Read"));
+ }
+ finally
+ {
+ // This is an Abnormal Close condition
+ close(StatusCode.ABNORMAL,"Idle Timeout");
+ }
return false;
}
@@ -470,7 +480,21 @@
LOG.debug("outgoingFrame({}, {})",frame,callback);
}
- flusher.enqueue(frame,callback, batchMode);
+ CloseInfo close = null;
+ // grab a copy of the frame details before masking and whatnot
+ if (frame.getOpCode() == OpCode.CLOSE)
+ {
+ close = new CloseInfo(frame);
+ }
+
+ flusher.enqueue(frame,callback,batchMode);
+
+ // now trigger local close
+ if (close != null)
+ {
+ LOG.debug("outgoing CLOSE frame - {}: {}",frame,close);
+ ioState.onCloseLocal(close);
+ }
}
private int read(ByteBuffer buffer)
@@ -498,7 +522,6 @@
LOG.debug("Filled {} bytes - {}",filled,BufferUtil.toDetailString(buffer));
}
parser.parse(buffer);
- // TODO: has the end user application already consumed what it was given?
}
}
}
@@ -514,6 +537,12 @@
close(e.getStatusCode(),e.getMessage());
return -1;
}
+ catch (Throwable t)
+ {
+ LOG.warn(t);
+ close(StatusCode.ABNORMAL,t.getMessage());
+ return -1;
+ }
}
@Override
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java
index a7bb3cb..6e995e5 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java
@@ -29,7 +29,6 @@
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.ArrayQueue;
import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.IteratingCallback;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -45,246 +44,22 @@
*/
public class FrameFlusher
{
- public static final BinaryFrame FLUSH_FRAME = new BinaryFrame();
- private static final Logger LOG = Log.getLogger(FrameFlusher.class);
-
- private final ByteBufferPool bufferPool;
- private final EndPoint endpoint;
- private final int bufferSize;
- private final Generator generator;
- private final int maxGather;
- private final Object lock = new Object();
- private final ArrayQueue<FrameEntry> queue = new ArrayQueue<>(16, 16, lock);
- private final Flusher flusher = new Flusher();
- private final AtomicBoolean closed = new AtomicBoolean();
- private volatile Throwable failure;
-
- public FrameFlusher(ByteBufferPool bufferPool, Generator generator, EndPoint endpoint, int bufferSize, int maxGather)
- {
- this.bufferPool = bufferPool;
- this.endpoint = endpoint;
- this.bufferSize = bufferSize;
- this.generator = Objects.requireNonNull(generator);
- this.maxGather = maxGather;
- }
-
- public void enqueue(Frame frame, WriteCallback callback, BatchMode batchMode)
- {
- if (closed.get())
- {
- notifyCallbackFailure(callback, new EOFException("Connection has been closed locally"));
- return;
- }
- if (flusher.isFailed())
- {
- notifyCallbackFailure(callback, failure);
- return;
- }
-
- FrameEntry entry = new FrameEntry(frame, callback, batchMode);
-
- synchronized (lock)
- {
- switch (frame.getOpCode())
- {
- case OpCode.PING:
- {
- // Prepend PINGs so they are processed first.
- queue.add(0, entry);
- break;
- }
- case OpCode.CLOSE:
- {
- // There may be a chance that other frames are
- // added after this close frame, but we will
- // fail them later to keep it simple here.
- closed.set(true);
- queue.add(entry);
- break;
- }
- default:
- {
- queue.add(entry);
- break;
- }
- }
- }
-
- if (LOG.isDebugEnabled())
- LOG.debug("{} queued {}", this, entry);
-
- flusher.iterate();
- }
-
- public void close()
- {
- if (closed.compareAndSet(false, true))
- {
- LOG.debug("{} closing {}", this);
- EOFException eof = new EOFException("Connection has been closed locally");
- flusher.failed(eof);
-
- // Fail also queued entries.
- List<FrameEntry> entries = new ArrayList<>();
- synchronized (lock)
- {
- entries.addAll(queue);
- queue.clear();
- }
- // Notify outside sync block.
- for (FrameEntry entry : entries)
- notifyCallbackFailure(entry.callback, eof);
- }
- }
-
- protected void onFailure(Throwable x)
- {
- LOG.warn(x);
- }
-
- protected void notifyCallbackSuccess(WriteCallback callback)
- {
- try
- {
- if (callback != null)
- callback.writeSuccess();
- }
- catch (Throwable x)
- {
- LOG.debug("Exception while notifying success of callback " + callback, x);
- }
- }
-
- protected void notifyCallbackFailure(WriteCallback callback, Throwable failure)
- {
- try
- {
- if (callback != null)
- callback.writeFailed(failure);
- }
- catch (Throwable x)
- {
- LOG.debug("Exception while notifying failure of callback " + callback, x);
- }
- }
-
- @Override
- public String toString()
- {
- ByteBuffer aggregate = flusher.aggregate;
- return String.format("%s[queueSize=%d,aggregateSize=%d,failure=%s]",
- getClass().getSimpleName(),
- queue.size(),
- aggregate == null ? 0 : aggregate.position(),
- failure);
- }
-
private class Flusher extends IteratingCallback
{
private final List<FrameEntry> entries = new ArrayList<>(maxGather);
- private final List<ByteBuffer> buffers = new ArrayList<>(maxGather * 2 + 1);
+ private final List<ByteBuffer> buffers = new ArrayList<>((maxGather * 2) + 1);
private ByteBuffer aggregate;
private BatchMode batchMode;
- @Override
- protected Action process() throws Exception
- {
- int space = aggregate == null ? bufferSize : BufferUtil.space(aggregate);
- BatchMode currentBatchMode = BatchMode.AUTO;
- synchronized (lock)
- {
- while (entries.size() <= maxGather && !queue.isEmpty())
- {
- FrameEntry entry = queue.remove(0);
- currentBatchMode = BatchMode.max(currentBatchMode, entry.batchMode);
-
- // Force flush if we need to.
- if (entry.frame == FLUSH_FRAME)
- currentBatchMode = BatchMode.OFF;
-
- int payloadLength = BufferUtil.length(entry.frame.getPayload());
- int approxFrameLength = Generator.MAX_HEADER_LENGTH + payloadLength;
-
- // If it is a "big" frame, avoid copying into the aggregate buffer.
- if (approxFrameLength > (bufferSize >> 2))
- currentBatchMode = BatchMode.OFF;
-
- // If the aggregate buffer overflows, do not batch.
- space -= approxFrameLength;
- if (space <= 0)
- currentBatchMode = BatchMode.OFF;
-
- entries.add(entry);
- }
- }
-
- if (LOG.isDebugEnabled())
- LOG.debug("{} processing {} entries: {}", FrameFlusher.this, entries.size(), entries);
-
- if (entries.isEmpty())
- {
- if (batchMode != BatchMode.AUTO)
- {
- // Nothing more to do, release the aggregate buffer if we need to.
- // Releasing it here rather than in succeeded() allows for its reuse.
- releaseAggregate();
- return Action.IDLE;
- }
-
- LOG.debug("{} auto flushing", FrameFlusher.this);
- return flush();
- }
-
- batchMode = currentBatchMode;
-
- return currentBatchMode == BatchMode.OFF ? flush() : batch();
- }
-
- private Action flush()
- {
- if (!BufferUtil.isEmpty(aggregate))
- {
- buffers.add(aggregate);
- if (LOG.isDebugEnabled())
- LOG.debug("{} flushing aggregate {}", FrameFlusher.this, aggregate);
- }
-
- // Do not allocate the iterator here.
- for (int i = 0; i < entries.size(); ++i)
- {
- FrameEntry entry = entries.get(i);
- // Skip the "synthetic" frame used for flushing.
- if (entry.frame == FLUSH_FRAME)
- continue;
- buffers.add(entry.generateHeaderBytes());
- ByteBuffer payload = entry.frame.getPayload();
- if (BufferUtil.hasContent(payload))
- buffers.add(payload);
- }
-
- if (LOG.isDebugEnabled())
- LOG.debug("{} flushing {} frames: {}", FrameFlusher.this, entries.size(), entries);
-
- if (buffers.isEmpty())
- {
- releaseAggregate();
- // We may have the FLUSH_FRAME to notify.
- succeedEntries();
- return Action.IDLE;
- }
-
- endpoint.write(this, buffers.toArray(new ByteBuffer[buffers.size()]));
- buffers.clear();
- return Action.SCHEDULED;
- }
-
private Action batch()
{
if (aggregate == null)
{
- aggregate = bufferPool.acquire(bufferSize, true);
+ aggregate = bufferPool.acquire(bufferSize,true);
if (LOG.isDebugEnabled())
- LOG.debug("{} acquired aggregate buffer {}", FrameFlusher.this, aggregate);
+ {
+ LOG.debug("{} acquired aggregate buffer {}",FrameFlusher.this,aggregate);
+ }
}
// Do not allocate the iterator here.
@@ -296,17 +71,149 @@
ByteBuffer payload = entry.frame.getPayload();
if (BufferUtil.hasContent(payload))
- BufferUtil.append(aggregate, payload);
+ {
+ BufferUtil.append(aggregate,payload);
+ }
}
if (LOG.isDebugEnabled())
- LOG.debug("{} aggregated {} frames: {}", FrameFlusher.this, entries.size(), entries);
+ {
+ LOG.debug("{} aggregated {} frames: {}",FrameFlusher.this,entries.size(),entries);
+ }
succeeded();
return Action.SCHEDULED;
}
+ @Override
+ protected void completed()
+ {
+ // This IteratingCallback never completes.
+ }
+
+ @Override
+ public void failed(Throwable x)
+ {
+ for (FrameEntry entry : entries)
+ {
+ notifyCallbackFailure(entry.callback,x);
+ entry.release();
+ }
+ entries.clear();
+ super.failed(x);
+ failure = x;
+ onFailure(x);
+ }
+
+ private Action flush()
+ {
+ if (!BufferUtil.isEmpty(aggregate))
+ {
+ buffers.add(aggregate);
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("{} flushing aggregate {}",FrameFlusher.this,aggregate);
+ }
+ }
+
+ // Do not allocate the iterator here.
+ for (int i = 0; i < entries.size(); ++i)
+ {
+ FrameEntry entry = entries.get(i);
+ // Skip the "synthetic" frame used for flushing.
+ if (entry.frame == FLUSH_FRAME)
+ {
+ continue;
+ }
+ buffers.add(entry.generateHeaderBytes());
+ ByteBuffer payload = entry.frame.getPayload();
+ if (BufferUtil.hasContent(payload))
+ {
+ buffers.add(payload);
+ }
+ }
+
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("{} flushing {} frames: {}",FrameFlusher.this,entries.size(),entries);
+ }
+
+ if (buffers.isEmpty())
+ {
+ releaseAggregate();
+ // We may have the FLUSH_FRAME to notify.
+ succeedEntries();
+ return Action.IDLE;
+ }
+
+ endpoint.write(this,buffers.toArray(new ByteBuffer[buffers.size()]));
+ buffers.clear();
+ return Action.SCHEDULED;
+ }
+
+ @Override
+ protected Action process() throws Exception
+ {
+ int space = aggregate == null?bufferSize:BufferUtil.space(aggregate);
+ BatchMode currentBatchMode = BatchMode.AUTO;
+ synchronized (lock)
+ {
+ while ((entries.size() <= maxGather) && !queue.isEmpty())
+ {
+ FrameEntry entry = queue.remove(0);
+ currentBatchMode = BatchMode.max(currentBatchMode,entry.batchMode);
+
+ // Force flush if we need to.
+ if (entry.frame == FLUSH_FRAME)
+ {
+ currentBatchMode = BatchMode.OFF;
+ }
+
+ int payloadLength = BufferUtil.length(entry.frame.getPayload());
+ int approxFrameLength = Generator.MAX_HEADER_LENGTH + payloadLength;
+
+ // If it is a "big" frame, avoid copying into the aggregate buffer.
+ if (approxFrameLength > (bufferSize >> 2))
+ {
+ currentBatchMode = BatchMode.OFF;
+ }
+
+ // If the aggregate buffer overflows, do not batch.
+ space -= approxFrameLength;
+ if (space <= 0)
+ {
+ currentBatchMode = BatchMode.OFF;
+ }
+
+ entries.add(entry);
+ }
+ }
+
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("{} processing {} entries: {}",FrameFlusher.this,entries.size(),entries);
+ }
+
+ if (entries.isEmpty())
+ {
+ if (batchMode != BatchMode.AUTO)
+ {
+ // Nothing more to do, release the aggregate buffer if we need to.
+ // Releasing it here rather than in succeeded() allows for its reuse.
+ releaseAggregate();
+ return Action.IDLE;
+ }
+
+ LOG.debug("{} auto flushing",FrameFlusher.this);
+ return flush();
+ }
+
+ batchMode = currentBatchMode;
+
+ return currentBatchMode == BatchMode.OFF?flush():batch();
+ }
+
private void releaseAggregate()
{
- if (aggregate != null && BufferUtil.isEmpty(aggregate))
+ if ((aggregate != null) && BufferUtil.isEmpty(aggregate))
{
bufferPool.release(aggregate);
aggregate = null;
@@ -331,26 +238,6 @@
}
entries.clear();
}
-
- @Override
- protected void completed()
- {
- // This IteratingCallback never completes.
- }
-
- @Override
- public void failed(Throwable x)
- {
- for (FrameEntry entry : entries)
- {
- notifyCallbackFailure(entry.callback, x);
- entry.release();
- }
- entries.clear();
- super.failed(x);
- failure = x;
- onFailure(x);
- }
}
private class FrameEntry
@@ -374,7 +261,7 @@
private void generateHeaderBytes(ByteBuffer buffer)
{
- generator.generateHeaderBytes(frame, buffer);
+ generator.generateHeaderBytes(frame,buffer);
}
private void release()
@@ -389,7 +276,145 @@
@Override
public String toString()
{
- return String.format("%s[%s,%s,%s,%s]", getClass().getSimpleName(), frame, callback, batchMode, failure);
+ return String.format("%s[%s,%s,%s,%s]",getClass().getSimpleName(),frame,callback,batchMode,failure);
}
}
+
+ public static final BinaryFrame FLUSH_FRAME = new BinaryFrame();
+ private static final Logger LOG = Log.getLogger(FrameFlusher.class);
+ private final ByteBufferPool bufferPool;
+ private final EndPoint endpoint;
+ private final int bufferSize;
+ private final Generator generator;
+ private final int maxGather;
+ private final Object lock = new Object();
+ private final ArrayQueue<FrameEntry> queue = new ArrayQueue<>(16,16,lock);
+ private final Flusher flusher = new Flusher();
+ private final AtomicBoolean closed = new AtomicBoolean();
+ private volatile Throwable failure;
+
+ public FrameFlusher(ByteBufferPool bufferPool, Generator generator, EndPoint endpoint, int bufferSize, int maxGather)
+ {
+ this.bufferPool = bufferPool;
+ this.endpoint = endpoint;
+ this.bufferSize = bufferSize;
+ this.generator = Objects.requireNonNull(generator);
+ this.maxGather = maxGather;
+ }
+
+ public void close()
+ {
+ if (closed.compareAndSet(false,true))
+ {
+ LOG.debug("{} closing {}",this);
+ EOFException eof = new EOFException("Connection has been closed locally");
+ flusher.failed(eof);
+
+ // Fail also queued entries.
+ List<FrameEntry> entries = new ArrayList<>();
+ synchronized (lock)
+ {
+ entries.addAll(queue);
+ queue.clear();
+ }
+ // Notify outside sync block.
+ for (FrameEntry entry : entries)
+ {
+ notifyCallbackFailure(entry.callback,eof);
+ }
+ }
+ }
+
+ public void enqueue(Frame frame, WriteCallback callback, BatchMode batchMode)
+ {
+ if (closed.get())
+ {
+ notifyCallbackFailure(callback,new EOFException("Connection has been closed locally"));
+ return;
+ }
+ if (flusher.isFailed())
+ {
+ notifyCallbackFailure(callback,failure);
+ return;
+ }
+
+ FrameEntry entry = new FrameEntry(frame,callback,batchMode);
+
+ synchronized (lock)
+ {
+ switch (frame.getOpCode())
+ {
+ case OpCode.PING:
+ {
+ // Prepend PINGs so they are processed first.
+ queue.add(0,entry);
+ break;
+ }
+ case OpCode.CLOSE:
+ {
+ // There may be a chance that other frames are
+ // added after this close frame, but we will
+ // fail them later to keep it simple here.
+ closed.set(true);
+ queue.add(entry);
+ break;
+ }
+ default:
+ {
+ queue.add(entry);
+ break;
+ }
+ }
+ }
+
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("{} queued {}",this,entry);
+ }
+
+ flusher.iterate();
+ }
+
+ protected void notifyCallbackFailure(WriteCallback callback, Throwable failure)
+ {
+ try
+ {
+ if (callback != null)
+ {
+ callback.writeFailed(failure);
+ }
+ }
+ catch (Throwable x)
+ {
+ LOG.debug("Exception while notifying failure of callback " + callback,x);
+ }
+ }
+
+ protected void notifyCallbackSuccess(WriteCallback callback)
+ {
+ try
+ {
+ if (callback != null)
+ {
+ callback.writeSuccess();
+ }
+ }
+ catch (Throwable x)
+ {
+ LOG.debug("Exception while notifying success of callback " + callback,x);
+ }
+ }
+
+ protected void onFailure(Throwable x)
+ {
+ LOG.warn(x);
+ }
+
+ @Override
+ public String toString()
+ {
+ ByteBuffer aggregate = flusher.aggregate;
+ return String.format("%s[queueSize=%d,aggregateSize=%d,failure=%s]",getClass().getSimpleName(),queue.size(),aggregate == null?0:aggregate.position(),
+ failure);
+ }
}
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/IOState.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/IOState.java
index 6d4dbc4..815d2d3 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/IOState.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/IOState.java
@@ -139,6 +139,10 @@
{
for (ConnectionStateListener listener : listeners)
{
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("{}.onConnectionStateChange({})",listener.getClass().getSimpleName(),state.name());
+ }
listener.onConnectionStateChange(state);
}
}
@@ -166,8 +170,7 @@
}
this.state = ConnectionState.CLOSED;
- if (closeInfo == null)
- this.closeInfo = close;
+ this.closeInfo = close;
this.inputAvailable = false;
this.outputAvailable = false;
this.closeHandshakeSource = CloseHandshakeSource.ABNORMAL;
@@ -193,16 +196,16 @@
if (initialState == ConnectionState.CONNECTED)
{
- // fast close. a local close request from end-user onConnected() method
+ // fast close. a local close request from end-user onConnect/onOpen method
LOG.debug("FastClose in CONNECTED detected");
// Force the state open (to allow read/write to endpoint)
onOpened();
+ LOG.debug("FastClose continuing with Closure");
}
synchronized (this)
{
- if (closeInfo == null)
- closeInfo = close;
+ closeInfo = close;
boolean in = inputAvailable;
boolean out = outputAvailable;
@@ -236,7 +239,6 @@
LOG.debug("notifying state listeners: {}",event);
notifyStateListeners(event);
- /*
// if abnormal, we don't expect an answer.
if (close.isAbnormal())
{
@@ -253,7 +255,6 @@
notifyStateListeners(event);
return;
}
- */
}
}
@@ -272,8 +273,7 @@
return;
}
- if (closeInfo == null)
- closeInfo = close;
+ closeInfo = close;
boolean in = inputAvailable;
boolean out = outputAvailable;
@@ -360,7 +360,7 @@
// already opened
return;
}
-
+
if (this.state != ConnectionState.CONNECTED)
{
LOG.debug("Unable to open, not in CONNECTED state: {}",this.state);
@@ -394,12 +394,11 @@
return;
}
- CloseInfo close = new CloseInfo(StatusCode.NO_CLOSE,"Read EOF");
+ CloseInfo close = new CloseInfo(StatusCode.ABNORMAL,"Read EOF");
this.cleanClose = false;
this.state = ConnectionState.CLOSED;
- if (closeInfo == null)
- this.closeInfo = close;
+ this.closeInfo = close;
this.inputAvailable = false;
this.outputAvailable = false;
this.closeHandshakeSource = CloseHandshakeSource.ABNORMAL;
@@ -408,6 +407,58 @@
notifyStateListeners(event);
}
+ public void onDisconnected()
+ {
+ ConnectionState event = null;
+ synchronized (this)
+ {
+ if (this.state == ConnectionState.CLOSED)
+ {
+ // already closed
+ return;
+ }
+
+ CloseInfo close = new CloseInfo(StatusCode.ABNORMAL,"Disconnected");
+
+ this.cleanClose = false;
+ this.state = ConnectionState.CLOSED;
+ this.closeInfo = close;
+ this.inputAvailable = false;
+ this.outputAvailable = false;
+ this.closeHandshakeSource = CloseHandshakeSource.ABNORMAL;
+ event = this.state;
+ }
+ notifyStateListeners(event);
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder str = new StringBuilder();
+ str.append(this.getClass().getSimpleName());
+ str.append("@").append(Integer.toHexString(hashCode()));
+ str.append("[").append(state);
+ str.append(',');
+ if (!inputAvailable)
+ {
+ str.append('!');
+ }
+ str.append("in,");
+ if (!outputAvailable)
+ {
+ str.append('!');
+ }
+ str.append("out");
+ if ((state == ConnectionState.CLOSED) || (state == ConnectionState.CLOSING))
+ {
+ str.append(",close=").append(closeInfo);
+ str.append(",clean=").append(cleanClose);
+ str.append(",closeSource=").append(closeHandshakeSource);
+ }
+ str.append(']');
+ return str.toString();
+ }
+
public boolean wasAbnormalClose()
{
return closeHandshakeSource == CloseHandshakeSource.ABNORMAL;
@@ -427,4 +478,5 @@
{
return closeHandshakeSource == CloseHandshakeSource.REMOTE;
}
+
}
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/util/ReflectUtils.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/util/ReflectUtils.java
index 32b9c1b..2194ec5 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/util/ReflectUtils.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/util/ReflectUtils.java
@@ -392,4 +392,4 @@
}
return name;
}
-}
+}
\ No newline at end of file
diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/CloseInfoTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/CloseInfoTest.java
new file mode 100644
index 0000000..a40e306
--- /dev/null
+++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/CloseInfoTest.java
@@ -0,0 +1,166 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.websocket.common;
+
+import static org.eclipse.jetty.websocket.api.StatusCode.*;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.nio.ByteBuffer;
+
+import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.util.StringUtil;
+import org.eclipse.jetty.websocket.api.ProtocolException;
+import org.eclipse.jetty.websocket.common.frames.CloseFrame;
+import org.junit.Test;
+
+public class CloseInfoTest
+{
+ /**
+ * A test where no close is provided
+ */
+ @Test
+ public void testAnonymousClose()
+ {
+ CloseInfo close = new CloseInfo();
+ assertThat("close.code",close.getStatusCode(),is(NO_CODE));
+ assertThat("close.reason",close.getReason(),nullValue());
+
+ CloseFrame frame = close.asFrame();
+ assertThat("close frame op code",frame.getOpCode(),is(OpCode.CLOSE));
+ // should result in no payload
+ assertThat("close frame has payload",frame.hasPayload(),is(false));
+ assertThat("close frame payload length",frame.getPayloadLength(),is(0));
+ }
+
+ /**
+ * A test where NO_CODE (1005) is provided
+ */
+ @Test
+ public void testNoCode()
+ {
+ CloseInfo close = new CloseInfo(NO_CODE);
+ assertThat("close.code",close.getStatusCode(),is(NO_CODE));
+ assertThat("close.reason",close.getReason(),nullValue());
+
+ CloseFrame frame = close.asFrame();
+ assertThat("close frame op code",frame.getOpCode(),is(OpCode.CLOSE));
+ // should result in no payload
+ assertThat("close frame has payload",frame.hasPayload(),is(false));
+ assertThat("close frame payload length",frame.getPayloadLength(),is(0));
+ }
+
+ /**
+ * A test where NO_CLOSE (1006) is provided
+ */
+ @Test
+ public void testNoClose()
+ {
+ CloseInfo close = new CloseInfo(NO_CLOSE);
+ assertThat("close.code",close.getStatusCode(),is(NO_CLOSE));
+ assertThat("close.reason",close.getReason(),nullValue());
+
+ CloseFrame frame = close.asFrame();
+ assertThat("close frame op code",frame.getOpCode(),is(OpCode.CLOSE));
+ // should result in no payload
+ assertThat("close frame has payload",frame.hasPayload(),is(false));
+ assertThat("close frame payload length",frame.getPayloadLength(),is(0));
+ }
+
+ /**
+ * A test of FAILED_TLS_HANDSHAKE (1007)
+ */
+ @Test
+ public void testFailedTlsHandshake()
+ {
+ CloseInfo close = new CloseInfo(FAILED_TLS_HANDSHAKE);
+ assertThat("close.code",close.getStatusCode(),is(FAILED_TLS_HANDSHAKE));
+ assertThat("close.reason",close.getReason(),nullValue());
+
+ try
+ {
+ @SuppressWarnings("unused")
+ CloseFrame frame = close.asFrame();
+ fail("Expected " + ProtocolException.class.getName());
+ }
+ catch (ProtocolException e)
+ {
+ // expected path
+ assertThat("ProtocolException message",e.getMessage(),containsString("not allowed (per RFC6455)"));
+ }
+ }
+
+ /**
+ * A test of NORMAL (1000)
+ */
+ @Test
+ public void testNormal()
+ {
+ CloseInfo close = new CloseInfo(NORMAL);
+ assertThat("close.code",close.getStatusCode(),is(NORMAL));
+ assertThat("close.reason",close.getReason(),nullValue());
+
+ CloseFrame frame = close.asFrame();
+ assertThat("close frame op code",frame.getOpCode(),is(OpCode.CLOSE));
+ assertThat("close frame payload length",frame.getPayloadLength(),is(2));
+ }
+
+ private ByteBuffer asByteBuffer(int statusCode, String reason)
+ {
+ int len = 2; // status code length
+ byte utf[] = null;
+ if (StringUtil.isNotBlank(reason))
+ {
+ utf = StringUtil.getUtf8Bytes(reason);
+ len += utf.length;
+ }
+
+ ByteBuffer buf = BufferUtil.allocate(len);
+ BufferUtil.flipToFill(buf);
+ buf.put((byte)((statusCode >>> 8) & 0xFF));
+ buf.put((byte)((statusCode >>> 0) & 0xFF));
+
+ if (utf != null)
+ {
+ buf.put(utf,0,utf.length);
+ }
+ BufferUtil.flipToFlush(buf,0);
+
+ return buf;
+ }
+
+ @Test
+ public void testFromFrame()
+ {
+ ByteBuffer payload = asByteBuffer(NORMAL,null);
+ assertThat("payload length", payload.remaining(), is(2));
+ CloseFrame frame = new CloseFrame();
+ frame.setPayload(payload);
+
+ // create from frame
+ CloseInfo close = new CloseInfo(frame);
+ assertThat("close.code",close.getStatusCode(),is(NORMAL));
+ assertThat("close.reason",close.getReason(),nullValue());
+
+ // and back again
+ frame = close.asFrame();
+ assertThat("close frame op code",frame.getOpCode(),is(OpCode.CLOSE));
+ assertThat("close frame payload length",frame.getPayloadLength(),is(2));
+ }
+}
diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase4.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase4.java
index fe6011d..6b0f018 100644
--- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase4.java
+++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase4.java
@@ -21,6 +21,7 @@
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.log.StacklessLogging;
+import org.eclipse.jetty.websocket.api.ProtocolException;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
@@ -39,8 +40,7 @@
{
ByteBuffer expected = ByteBuffer.allocate(32);
- expected.put(new byte[]
- { (byte)0x8b, 0x00 });
+ expected.put(new byte[] { (byte)0x8b, 0x00 });
expected.flip();
@@ -50,10 +50,17 @@
{
Parser parser = new UnitParser(policy);
parser.setIncomingFramesHandler(capture);
- parser.parse(expected);
+ try
+ {
+ parser.parse(expected);
+ }
+ catch (ProtocolException ignore)
+ {
+ // ignore
+ }
}
- Assert.assertEquals( "error on undefined opcode", 1, capture.getErrorCount(WebSocketException.class)) ;
+ Assert.assertEquals("error on undefined opcode",1,capture.getErrorCount(WebSocketException.class));
Throwable known = capture.getErrors().poll();
@@ -65,8 +72,7 @@
{
ByteBuffer expected = ByteBuffer.allocate(32);
- expected.put(new byte[]
- { (byte)0x8c, 0x01, 0x00 });
+ expected.put(new byte[] { (byte)0x8c, 0x01, 0x00 });
expected.flip();
@@ -76,24 +82,29 @@
{
Parser parser = new UnitParser(policy);
parser.setIncomingFramesHandler(capture);
- parser.parse(expected);
+ try
+ {
+ parser.parse(expected);
+ }
+ catch (ProtocolException ignore)
+ {
+ // ignore
+ }
}
- Assert.assertEquals( "error on undefined opcode", 1, capture.getErrorCount(WebSocketException.class)) ;
+ Assert.assertEquals("error on undefined opcode",1,capture.getErrorCount(WebSocketException.class));
Throwable known = capture.getErrors().poll();
Assert.assertTrue("undefined option should be in message",known.getMessage().contains("Unknown opcode: 12"));
}
-
@Test
public void testParserNonControlOpCode3Case4_1_1() throws Exception
{
ByteBuffer expected = ByteBuffer.allocate(32);
- expected.put(new byte[]
- { (byte)0x83, 0x00 });
+ expected.put(new byte[] { (byte)0x83, 0x00 });
expected.flip();
@@ -103,10 +114,17 @@
{
Parser parser = new UnitParser(policy);
parser.setIncomingFramesHandler(capture);
- parser.parse(expected);
+ try
+ {
+ parser.parse(expected);
+ }
+ catch (ProtocolException ignore)
+ {
+ // ignore
+ }
}
- Assert.assertEquals( "error on undefined opcode", 1, capture.getErrorCount(WebSocketException.class)) ;
+ Assert.assertEquals("error on undefined opcode",1,capture.getErrorCount(WebSocketException.class));
Throwable known = capture.getErrors().poll();
@@ -118,8 +136,7 @@
{
ByteBuffer expected = ByteBuffer.allocate(32);
- expected.put(new byte[]
- { (byte)0x84, 0x01, 0x00 });
+ expected.put(new byte[] { (byte)0x84, 0x01, 0x00 });
expected.flip();
@@ -129,10 +146,17 @@
{
Parser parser = new UnitParser(policy);
parser.setIncomingFramesHandler(capture);
- parser.parse(expected);
+ try
+ {
+ parser.parse(expected);
+ }
+ catch (ProtocolException ignore)
+ {
+ // ignore
+ }
}
- Assert.assertEquals( "error on undefined opcode", 1, capture.getErrorCount(WebSocketException.class)) ;
+ Assert.assertEquals("error on undefined opcode",1,capture.getErrorCount(WebSocketException.class));
Throwable known = capture.getErrors().poll();
diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java
index bd02460..b4634c5 100644
--- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java
+++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java
@@ -18,7 +18,8 @@
package org.eclipse.jetty.websocket.common.test;
-import java.io.Closeable;
+import static org.hamcrest.Matchers.*;
+
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
@@ -68,10 +69,6 @@
import org.eclipse.jetty.websocket.common.io.http.HttpResponseHeaderParser;
import org.junit.Assert;
-import static org.hamcrest.Matchers.anyOf;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-
/**
* A simple websocket client for performing unit tests with.
* <p>
@@ -84,7 +81,7 @@
* with regards to basic IO behavior, a write should work as expected, a read should work as expected, but <u>what</u> byte it sends or reads is not within its
* scope.
*/
-public class BlockheadClient implements IncomingFrames, OutgoingFrames, ConnectionStateListener, Closeable
+public class BlockheadClient implements IncomingFrames, OutgoingFrames, ConnectionStateListener, AutoCloseable
{
private static final String REQUEST_HASH_KEY = "dGhlIHNhbXBsZSBub25jZQ==";
private static final int BUFFER_SIZE = 8192;
@@ -182,22 +179,14 @@
public void close(int statusCode, String message)
{
+ LOG.debug("close({},{})",statusCode,message);
CloseInfo close = new CloseInfo(statusCode,message);
- ioState.onCloseLocal(close);
-
if (!ioState.isClosed())
{
- WebSocketFrame frame = close.asFrame();
- LOG.debug("Issuing: {}",frame);
- try
- {
- write(frame);
- }
- catch (IOException e)
- {
- LOG.debug(e);
- }
+ ioState.onCloseLocal(close);
+ } else {
+ LOG.debug("Not issuing close. ioState = {}",ioState);
}
}
@@ -429,13 +418,8 @@
{
LOG.info("Client parsed {} frames",count);
}
-
- if (frame.getOpCode() == OpCode.CLOSE)
- {
- CloseInfo close = new CloseInfo(frame);
- ioState.onCloseRemote(close);
- }
-
+
+ // Capture Frame Copy
WebSocketFrame copy = WebSocketFrame.copy(frame);
incomingFrames.incomingFrame(copy);
}
@@ -448,6 +432,7 @@
@Override
public void onConnectionStateChange(ConnectionState state)
{
+ LOG.debug("CLIENT onConnectionStateChange() - {}", state);
switch (state)
{
case CLOSED:
@@ -455,10 +440,17 @@
// this.disconnect();
break;
case CLOSING:
- if (ioState.wasRemoteCloseInitiated())
+ CloseInfo close = ioState.getCloseInfo();
+
+ WebSocketFrame frame = close.asFrame();
+ LOG.debug("Issuing: {}",frame);
+ try
{
- CloseInfo close = ioState.getCloseInfo();
- close(close.getStatusCode(),close.getReason());
+ write(frame);
+ }
+ catch (IOException e)
+ {
+ LOG.debug(e);
}
break;
default:
@@ -532,8 +524,14 @@
return len;
}
+ @Deprecated
public IncomingFramesCapture readFrames(int expectedCount, TimeUnit timeoutUnit, int timeoutDuration) throws IOException, TimeoutException
{
+ return readFrames(expectedCount,timeoutDuration,timeoutUnit);
+ }
+
+ public IncomingFramesCapture readFrames(int expectedCount, int timeoutDuration, TimeUnit timeoutUnit) throws IOException, TimeoutException
+ {
LOG.debug("Read: waiting for {} frame(s) from server",expectedCount);
ByteBuffer buf = bufferPool.acquire(BUFFER_SIZE,false);
@@ -701,6 +699,7 @@
{
if (!ioState.isOpen())
{
+ LOG.debug("IO Not Open / Not Writing: {}",frame);
return;
}
LOG.debug("write(Frame->{}) to {}",frame,outgoing);
diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServer.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServer.java
index c3cd1ad..1b665bd 100644
--- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServer.java
+++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServer.java
@@ -54,6 +54,7 @@
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.extensions.Frame.Type;
import org.eclipse.jetty.websocket.common.AcceptHash;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.Generator;
@@ -124,7 +125,6 @@
{
write(new CloseFrame());
flush();
- disconnect();
}
public void close(int statusCode) throws IOException
@@ -132,7 +132,6 @@
CloseInfo close = new CloseInfo(statusCode);
write(close.asFrame());
flush();
- disconnect();
}
public void disconnect()
@@ -229,6 +228,19 @@
CloseInfo close = new CloseInfo(frame);
LOG.debug("Close frame: {}",close);
}
+
+ Type type = frame.getType();
+ if (echoing.get() && (type.isData() || type.isContinuation()))
+ {
+ try
+ {
+ write(WebSocketFrame.copy(frame));
+ }
+ catch (IOException e)
+ {
+ LOG.warn(e);
+ }
+ }
}
@Override
@@ -317,9 +329,18 @@
return len;
}
+ /**
+ * @deprecated use {@link #readFrames(int, int, TimeUnit)} for correct parameter order
+ */
+ @Deprecated
public IncomingFramesCapture readFrames(int expectedCount, TimeUnit timeoutUnit, int timeoutDuration) throws IOException, TimeoutException
{
- LOG.debug("Read: waiting for {} frame(s) from server",expectedCount);
+ return readFrames(expectedCount,timeoutDuration,timeoutUnit);
+ }
+
+ public IncomingFramesCapture readFrames(int expectedCount, int timeoutDuration, TimeUnit timeoutUnit) throws IOException, TimeoutException
+ {
+ LOG.debug("Read: waiting for {} frame(s) from client",expectedCount);
int startCount = incomingFrames.size();
ByteBuffer buf = bufferPool.acquire(BUFFER_SIZE,false);
@@ -562,13 +583,22 @@
public void write(Frame frame) throws IOException
{
LOG.debug("write(Frame->{}) to {}",frame,outgoing);
- outgoing.outgoingFrame(frame,null, BatchMode.OFF);
+ outgoing.outgoingFrame(frame,null,BatchMode.OFF);
}
public void write(int b) throws IOException
{
getOutputStream().write(b);
}
+
+ public void write(ByteBuffer buf) throws IOException
+ {
+ byte arr[] = BufferUtil.toArray(buf);
+ if ((arr != null) && (arr.length > 0))
+ {
+ getOutputStream().write(arr);
+ }
+ }
}
private static final Logger LOG = Log.getLogger(BlockheadServer.class);
diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java
index 3d6c641..8ebfc94 100644
--- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java
+++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java
@@ -45,7 +45,7 @@
/**
* Fuzzing utility for the AB tests.
*/
-public class Fuzzer
+public class Fuzzer implements AutoCloseable
{
public static enum CloseState
{
@@ -117,8 +117,14 @@
buf.flip();
return buf;
}
+
+ @Override
+ public void close() throws Exception
+ {
+ this.client.disconnect();
+ }
- public void close()
+ public void disconnect()
{
this.client.disconnect();
}
@@ -187,23 +193,6 @@
// TODO Should test for no more frames. success if connection closed.
}
- public void expectServerDisconnect(DisconnectMode mode)
- {
- client.expectServerDisconnect();
- IOState ios = client.getIOState();
-
- switch (mode)
- {
- case CLEAN:
- Assert.assertTrue(ios.wasRemoteCloseInitiated());
- Assert.assertTrue(ios.wasCleanClose());
- break;
- case UNCLEAN:
- Assert.assertTrue(ios.wasRemoteCloseInitiated());
- break;
- }
- }
-
public CloseState getCloseState()
{
IOState ios = client.getIOState();
diff --git a/jetty-websocket/websocket-server/pom.xml b/jetty-websocket/websocket-server/pom.xml
index 5288e54..19def58 100644
--- a/jetty-websocket/websocket-server/pom.xml
+++ b/jetty-websocket/websocket-server/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
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 bebe7c0..f6a2f2c 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
@@ -44,6 +44,7 @@
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
+import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
@@ -199,11 +200,23 @@
}
}
- protected void closeAllConnections()
+ protected void shutdownAllConnections()
{
for (WebSocketSession session : openSessions)
{
- session.close();
+ if (session.getConnection() != null)
+ {
+ try
+ {
+ session.getConnection().close(
+ StatusCode.SHUTDOWN,
+ "Shutdown");
+ }
+ catch (Throwable t)
+ {
+ LOG.debug("During Shutdown All Connections",t);
+ }
+ }
}
openSessions.clear();
}
@@ -269,7 +282,7 @@
@Override
protected void doStop() throws Exception
{
- closeAllConnections();
+ shutdownAllConnections();
super.doStop();
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java
index 7a6998b..7fdada4 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java
@@ -18,14 +18,22 @@
package org.eclipse.jetty.websocket.server;
+import static org.hamcrest.Matchers.*;
+
import java.util.concurrent.TimeUnit;
+import org.eclipse.jetty.websocket.api.StatusCode;
+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.frames.TextFrame;
import org.eclipse.jetty.websocket.common.test.BlockheadClient;
+import org.eclipse.jetty.websocket.common.test.IncomingFramesCapture;
import org.eclipse.jetty.websocket.server.helper.RFCSocket;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
import org.junit.AfterClass;
+import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -83,8 +91,13 @@
// The server could not read this frame, if it is in this half closed state
client.write(new TextFrame().setPayload("Hello"));
- // Expect server to be disconnected at this point
- client.expectServerDisconnect();
+ // Expect server to have closed due to its own timeout
+ IncomingFramesCapture capture = client.readFrames(1,500,TimeUnit.MILLISECONDS);
+ WebSocketFrame frame = capture.getFrames().poll();
+ Assert.assertThat("frame opcode",frame.getOpCode(),is(OpCode.CLOSE));
+ CloseInfo close = new CloseInfo(frame);
+ Assert.assertThat("close code",close.getStatusCode(),is(StatusCode.SHUTDOWN));
+ Assert.assertThat("close reason",close.getReason(),containsString("Timeout"));
}
finally
{
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 0c2ddb3..5a4707c 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
@@ -114,7 +114,7 @@
public void onWebSocketConnect(Session sess)
{
LOG.debug("onWebSocketConnect({})",sess);
- sess.close();
+ sess.close(StatusCode.NORMAL,"FastCloseServer");
}
}
@@ -129,14 +129,10 @@
public void onWebSocketConnect(Session sess)
{
LOG.debug("onWebSocketConnect({})",sess);
+ // Test failure due to unhandled exception
+ // this should trigger a fast-fail closure during open/connect
throw new RuntimeException("Intentional FastFail");
}
-
- @Override
- public void onWebSocketError(Throwable cause)
- {
- errors.add(cause);
- }
}
private static final Logger LOG = Log.getLogger(WebSocketCloseTest.class);
@@ -163,30 +159,28 @@
@Test
public void testFastClose() throws Exception
{
- BlockheadClient client = new BlockheadClient(server.getServerUri());
- client.setProtocols("fastclose");
- client.setTimeout(TimeUnit.SECONDS,1);
- try
+ try (BlockheadClient client = new BlockheadClient(server.getServerUri()))
{
+ client.setProtocols("fastclose");
+ client.setTimeout(TimeUnit.SECONDS,1);
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
+ // Verify that client got close frame
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.NORMAL));
-
+
+ // Notify server of close handshake
client.write(close.asFrame()); // respond with close
-
+
+ // ensure server socket got close event
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();
- }
}
/**
@@ -195,11 +189,10 @@
@Test
public void testFastFail() throws Exception
{
- BlockheadClient client = new BlockheadClient(server.getServerUri());
- client.setProtocols("fastfail");
- client.setTimeout(TimeUnit.SECONDS,1);
- try
+ try (BlockheadClient client = new BlockheadClient(server.getServerUri()))
{
+ client.setProtocols("fastfail");
+ client.setTimeout(TimeUnit.SECONDS,1);
try (StacklessLogging scope = new StacklessLogging(AbstractEventDriver.class))
{
client.connect();
@@ -214,14 +207,11 @@
client.write(close.asFrame()); // respond with close
+ // ensure server socket got close event
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
- {
- client.close();
- }
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase1.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase1.java
index 20ff642..502fb80 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase1.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase1.java
@@ -48,18 +48,12 @@
expect.add(new TextFrame());
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -81,18 +75,12 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -114,18 +102,12 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -147,18 +129,12 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -180,18 +156,12 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -213,18 +183,12 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -246,18 +210,12 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -284,19 +242,13 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.SLOW);
fuzzer.setSlowSendSegmentSize(segmentSize);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -314,18 +266,12 @@
expect.add(new BinaryFrame());
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -347,18 +293,12 @@
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -380,18 +320,12 @@
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -413,18 +347,12 @@
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -446,18 +374,12 @@
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -479,18 +401,12 @@
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -512,18 +428,12 @@
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
@@ -550,19 +460,13 @@
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(SendMode.SLOW);
fuzzer.setSlowSendSegmentSize(segmentSize);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase2.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase2.java
index 0e43806..4a1a1c1 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase2.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase2.java
@@ -50,18 +50,13 @@
WebSocketFrame expect = new PongFrame();
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -89,18 +84,13 @@
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -128,8 +118,7 @@
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.SLOW);
@@ -137,10 +126,6 @@
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -159,18 +144,13 @@
expect.add(new PongFrame().setPayload(copyOf(payload)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -179,8 +159,7 @@
@Test
public void testCase2_3() throws Exception
{
- byte payload[] = new byte[]
- { 0x00, (byte)0xFF, (byte)0xFE, (byte)0xFD, (byte)0xFC, (byte)0xFB, 0x00, (byte)0xFF };
+ byte payload[] = new byte[] { 0x00, (byte)0xFF, (byte)0xFE, (byte)0xFD, (byte)0xFC, (byte)0xFB, 0x00, (byte)0xFF };
List<WebSocketFrame> send = new ArrayList<>();
send.add(new PingFrame().setPayload(payload));
@@ -190,18 +169,13 @@
expect.add(new PongFrame().setPayload(copyOf(payload)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -221,18 +195,13 @@
expect.add(new PongFrame().setPayload(copyOf(payload)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -241,32 +210,26 @@
@Test
public void testCase2_5() throws Exception
{
- try(StacklessLogging scope = new StacklessLogging(Parser.class))
+ try (StacklessLogging scope = new StacklessLogging(Parser.class))
{
byte payload[] = new byte[126]; // intentionally too big
Arrays.fill(payload,(byte)'5');
ByteBuffer buf = ByteBuffer.wrap(payload);
-
+
List<WebSocketFrame> send = new ArrayList<>();
// trick websocket frame into making extra large payload for ping
send.add(new BadFrame(OpCode.PING).setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL,"Test 2.5").asFrame());
-
+
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
-
- Fuzzer fuzzer = new Fuzzer(this);
- try
+
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
}
@@ -288,8 +251,7 @@
expect.add(new PongFrame().setPayload(copyOf(payload)));
expect.add(new CloseInfo(StatusCode.NORMAL,"Test 2.6").asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.SLOW);
@@ -297,10 +259,6 @@
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -316,18 +274,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -343,18 +296,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -372,17 +320,12 @@
expect.add(new PongFrame().setPayload("our ping")); // our pong
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase3.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase3.java
index 4b5373b..de9ec69 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase3.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase3.java
@@ -51,18 +51,13 @@
WebSocketFrame expect = new CloseInfo(StatusCode.PROTOCOL).asFrame();
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -80,18 +75,13 @@
expect.add(new TextFrame().setPayload("small")); // echo on good frame
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -109,18 +99,13 @@
expect.add(new TextFrame().setPayload("small")); // echo on good frame
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.PER_FRAME);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -138,8 +123,7 @@
expect.add(new TextFrame().setPayload("small")); // echo on good frame
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.SLOW);
@@ -147,10 +131,6 @@
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -168,18 +148,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -197,18 +172,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -230,17 +200,12 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase4.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase4.java
index ffb6961..61f59ad 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase4.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase4.java
@@ -53,18 +53,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -82,18 +77,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -111,18 +101,13 @@
expect.add(new TextFrame().setPayload("hello")); // echo
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -132,7 +117,7 @@
public void testCase4_1_4() throws Exception
{
ByteBuffer buf = ByteBuffer.wrap(StringUtil.getUtf8Bytes("bad"));
-
+
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload("hello"));
send.add(new BadFrame((byte)6).setPayload(buf)); // intentionally bad
@@ -142,18 +127,13 @@
expect.add(new TextFrame().setPayload("hello")); // echo
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -163,7 +143,7 @@
public void testCase4_1_5() throws Exception
{
ByteBuffer buf = ByteBuffer.wrap(StringUtil.getUtf8Bytes("bad"));
-
+
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload("hello"));
send.add(new BadFrame((byte)7).setPayload(buf)); // intentionally bad
@@ -173,18 +153,13 @@
expect.add(new TextFrame().setPayload("hello")); // echo
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -199,18 +174,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -220,25 +190,20 @@
public void testCase4_2_2() throws Exception
{
ByteBuffer buf = ByteBuffer.wrap(StringUtil.getUtf8Bytes("bad"));
-
+
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BadFrame((byte)12).setPayload(buf)); // intentionally bad
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -256,18 +221,13 @@
expect.add(new TextFrame().setPayload("hello")); // echo
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -277,7 +237,7 @@
public void testCase4_2_4() throws Exception
{
ByteBuffer buf = ByteBuffer.wrap(StringUtil.getUtf8Bytes("bad"));
-
+
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload("hello"));
send.add(new BadFrame((byte)14).setPayload(buf)); // intentionally bad
@@ -287,18 +247,13 @@
expect.add(new TextFrame().setPayload("hello")); // echo
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -308,7 +263,7 @@
public void testCase4_2_5() throws Exception
{
ByteBuffer buf = ByteBuffer.wrap(StringUtil.getUtf8Bytes("bad"));
-
+
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload("hello"));
send.add(new BadFrame((byte)15).setPayload(buf)); // intentionally bad
@@ -318,17 +273,12 @@
expect.add(new TextFrame().setPayload("hello")); // echo
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase5.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase5.java
index c957fc9..c6349a3 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase5.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase5.java
@@ -57,19 +57,14 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
- }
+ }
/**
* Send continuation+fin, then text+fin (framewise)
@@ -85,18 +80,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.PER_FRAME);
fuzzer.sendAndIgnoreBrokenPipe(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -113,8 +103,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.SLOW);
@@ -122,10 +111,6 @@
fuzzer.sendAndIgnoreBrokenPipe(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -142,18 +127,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.sendAndIgnoreBrokenPipe(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -170,18 +150,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.PER_FRAME);
fuzzer.sendAndIgnoreBrokenPipe(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -198,8 +173,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.SLOW);
@@ -207,10 +181,6 @@
fuzzer.sendAndIgnoreBrokenPipe(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -230,18 +200,13 @@
expect.add(new TextFrame().setPayload("fragment1fragment2"));
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -262,18 +227,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.sendAndIgnoreBrokenPipe(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -294,18 +254,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -322,18 +277,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -365,8 +315,7 @@
expect2.add(new TextFrame().setPayload("f1,f2,f3,f4,f5"));
expect2.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -382,10 +331,6 @@
fuzzer.send(send2);
fuzzer.expect(expect2);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -402,18 +347,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -442,8 +382,7 @@
expect2.add(new TextFrame().setPayload("f1,f2,f3,f4,f5"));
expect2.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.PER_FRAME);
@@ -456,10 +395,6 @@
fuzzer.send(send2);
fuzzer.expect(expect2);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -488,8 +423,7 @@
expect2.add(new TextFrame().setPayload("f1,f2,f3,f4,f5"));
expect2.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.SLOW);
@@ -503,10 +437,6 @@
fuzzer.send(send2);
fuzzer.expect(expect2);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -524,18 +454,13 @@
expect.add(new TextFrame().setPayload("hello, world"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -553,18 +478,13 @@
expect.add(new TextFrame().setPayload("hello, world"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.PER_FRAME);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -582,8 +502,7 @@
expect.add(new TextFrame().setPayload("hello, world"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.SLOW);
@@ -591,10 +510,6 @@
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -614,18 +529,13 @@
expect.add(new TextFrame().setPayload("hello, world"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -645,18 +555,13 @@
expect.add(new TextFrame().setPayload("hello, world"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.PER_FRAME);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -676,8 +581,7 @@
expect.add(new TextFrame().setPayload("hello, world"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.SLOW);
@@ -685,10 +589,6 @@
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -706,17 +606,12 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try(Fuzzer fuzzer = new Fuzzer(this);StacklessLogging supress = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java
index 6ead418..c11aebf 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java
@@ -90,18 +90,13 @@
expect.add(new TextFrame());
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -120,18 +115,13 @@
expect.add(new TextFrame());
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -150,18 +140,13 @@
expect.add(new TextFrame().setPayload("middle"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -172,7 +157,7 @@
{
String utf1 = "Hello-\uC2B5@\uC39F\uC3A4";
String utf2 = "\uC3BC\uC3A0\uC3A1-UTF-8!!";
-
+
ByteBuffer b1 = ByteBuffer.wrap(StringUtil.getUtf8Bytes(utf1));
ByteBuffer b2 = ByteBuffer.wrap(StringUtil.getUtf8Bytes(utf2));
@@ -189,18 +174,13 @@
expect.add(new TextFrame().setPayload(e1));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -220,18 +200,13 @@
expect.add(new TextFrame().setPayload(ByteBuffer.wrap(msg)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -250,18 +225,13 @@
expect.add(new TextFrame().setPayload(ByteBuffer.wrap(msg)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -279,18 +249,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -311,8 +276,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -325,10 +289,6 @@
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -351,8 +311,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -363,10 +322,6 @@
fuzzer.send(new ContinuationFrame().setPayload(ByteBuffer.wrap(part3)).setFin(true));
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -393,15 +348,13 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
ByteBuffer net = fuzzer.asNetworkBuffer(send);
- int splits[] =
- { 17, 21, net.limit() };
+ int splits[] = { 17, 21, net.limit() };
ByteBuffer part1 = net.slice(); // Header + good UTF
part1.limit(splits[0]);
@@ -419,12 +372,6 @@
fuzzer.send(part3); // the rest (shouldn't work)
fuzzer.expect(expect);
-
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.UNCLEAN);
- }
- finally
- {
- fuzzer.close();
}
}
}
@@ -445,8 +392,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging scope = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging scope = new StacklessLogging(Parser.class))
{
fuzzer.connect();
@@ -460,9 +406,5 @@
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_BadUTF.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_BadUTF.java
index 7c61776..3ff1643 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_BadUTF.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_BadUTF.java
@@ -163,18 +163,15 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging supress = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this))
{
- fuzzer.connect();
- fuzzer.setSendMode(Fuzzer.SendMode.BULK);
- fuzzer.send(send);
- fuzzer.expect(expect);
- fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.UNCLEAN);
- }
- finally
- {
- fuzzer.close();
+ try (StacklessLogging supress = new StacklessLogging(Parser.class))
+ {
+ fuzzer.connect();
+ fuzzer.setSendMode(Fuzzer.SendMode.BULK);
+ fuzzer.send(send);
+ fuzzer.expect(expect);
+ }
}
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_GoodUTF.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_GoodUTF.java
index 8eebe6e..f5e9cbe 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_GoodUTF.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_GoodUTF.java
@@ -139,17 +139,12 @@
expect.add(new TextFrame().setPayload(clone(msg)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7.java
index 8c60551..b8ad71b 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7.java
@@ -64,18 +64,13 @@
expect.add(new TextFrame().setPayload("Hello World"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -91,8 +86,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -100,10 +94,6 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -119,8 +109,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -128,10 +117,6 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -147,8 +132,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -156,10 +140,6 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -176,8 +156,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -185,10 +164,6 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -210,8 +185,7 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -219,10 +193,6 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -237,8 +207,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -246,10 +215,6 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -258,8 +223,7 @@
@Test
public void testCase7_3_2() throws Exception
{
- byte payload[] = new byte[]
- { 0x00 };
+ byte payload[] = new byte[] { 0x00 };
ByteBuffer buf = ByteBuffer.wrap(payload);
List<WebSocketFrame> send = new ArrayList<>();
@@ -268,8 +232,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging scope = new StacklessLogging(Parser.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging scope = new StacklessLogging(Parser.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -277,10 +240,6 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -295,8 +254,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -304,10 +262,6 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -322,8 +276,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL,"Hic").asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -331,10 +284,6 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -353,8 +302,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL,reason).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging logging = new StacklessLogging(AbstractWebSocketConnection.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging logging = new StacklessLogging(AbstractWebSocketConnection.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -362,10 +310,6 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -390,8 +334,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try(StacklessLogging scope = new StacklessLogging(Parser.class,CloseInfo.class))
+ try (Fuzzer fuzzer = new Fuzzer(this); StacklessLogging scope = new StacklessLogging(Parser.class,CloseInfo.class))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -399,9 +342,5 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7_BadStatusCodes.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7_BadStatusCodes.java
index b3626f1..c76e174 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7_BadStatusCodes.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7_BadStatusCodes.java
@@ -98,8 +98,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -107,10 +106,6 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -131,8 +126,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -140,9 +134,5 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7_GoodStatusCodes.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7_GoodStatusCodes.java
index 425f657..5e8da15 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7_GoodStatusCodes.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7_GoodStatusCodes.java
@@ -93,8 +93,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseFrame().setPayload(clone(payload)));
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -102,10 +101,6 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -125,8 +120,7 @@
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseFrame().setPayload(clone(payload)));
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
@@ -134,9 +128,5 @@
fuzzer.expect(expect);
fuzzer.expectNoMoreFrames();
}
- finally
- {
- fuzzer.close();
- }
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java
index 3950394..1b117f4 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java
@@ -96,18 +96,13 @@
expect.add(toDataFrame(opcode).setPayload(copyOf(msg)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect,TimeUnit.SECONDS,8);
}
- finally
- {
- fuzzer.close();
- }
}
private void assertSlowFrameEcho(byte opcode, int overallMsgSize, int segmentSize) throws Exception
@@ -124,8 +119,7 @@
expect.add(toDataFrame(opcode).setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.SLOW);
@@ -133,10 +127,6 @@
fuzzer.send(send);
fuzzer.expect(expect,TimeUnit.SECONDS,8);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -157,18 +147,13 @@
expect.add(new TextFrame().setPayload(msg));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -189,18 +174,13 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -222,18 +202,13 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect,TimeUnit.SECONDS,4);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -255,18 +230,13 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect,TimeUnit.SECONDS,8);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -288,18 +258,13 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect,TimeUnit.SECONDS,16);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -321,18 +286,13 @@
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect,TimeUnit.SECONDS,32);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -352,18 +312,13 @@
expect.add(new BinaryFrame().setPayload(copyOf(data)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -384,18 +339,13 @@
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -417,18 +367,13 @@
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect,TimeUnit.SECONDS,4);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -450,18 +395,13 @@
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect,TimeUnit.SECONDS,8);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -483,18 +423,13 @@
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect,TimeUnit.SECONDS,16);
}
- finally
- {
- fuzzer.close();
- }
}
/**
@@ -516,18 +451,13 @@
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
- Fuzzer fuzzer = new Fuzzer(this);
- try
+ try(Fuzzer fuzzer = new Fuzzer(this))
{
fuzzer.connect();
fuzzer.setSendMode(Fuzzer.SendMode.BULK);
fuzzer.send(send);
fuzzer.expect(expect,TimeUnit.SECONDS,32);
}
- finally
- {
- fuzzer.close();
- }
}
/**
diff --git a/jetty-websocket/websocket-servlet/pom.xml b/jetty-websocket/websocket-servlet/pom.xml
index b90d2f6..0904097 100644
--- a/jetty-websocket/websocket-servlet/pom.xml
+++ b/jetty-websocket/websocket-servlet/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-xml/pom.xml b/jetty-xml/pom.xml
index 96e50cf..517cd7e 100644
--- a/jetty-xml/pom.xml
+++ b/jetty-xml/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-xml</artifactId>
diff --git a/pom.xml b/pom.xml
index e0b06dd..87c22e7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
<version>22</version>
</parent>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<name>Jetty :: Project</name>
<url>http://www.eclipse.org/jetty</url>
<packaging>pom</packaging>
@@ -17,6 +17,10 @@
<slf4j-version>1.6.1</slf4j-version>
<jetty-test-policy-version>1.2</jetty-test-policy-version>
<npn.api.version>1.1.0.v20120525</npn.api.version>
+ <alpn.api.version>1.0.0</alpn.api.version>
+ <!-- default values are unsupported, but required to be defined for reactor sanity reasons -->
+ <npn.version>undefined</npn.version>
+ <alpn.version>undefined</alpn.version>
</properties>
<scm>
<connection>scm:git:http://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git</connection>
@@ -126,10 +130,11 @@
<rules>
<requireMavenVersion>
<version>[3.0.0,)</version>
+ <message>[ERROR] OLD MAVEN [${maven.version}] in use, Jetty ${project.version} requires Maven 3.0.0 or newer</message>
</requireMavenVersion>
<requireJavaVersion>
- <version>[1.7,)</version>
- <message>[ERROR] OLD JDK [${java.version}] in use. Jetty ${project.version} requires JDK 1.7 or newer</message>
+ <version>[1.7.0-40,)</version>
+ <message>[ERROR] OLD JDK [${java.version}] in use. Jetty ${project.version} requires JDK 1.7.0_40 or newer</message>
</requireJavaVersion>
<versionTxtRule implementation="org.eclipse.jetty.toolchain.enforcer.rules.VersionTxtRule" />
<versionOsgiRule implementation="org.eclipse.jetty.toolchain.enforcer.rules.RequireOsgiCompatibleVersionRule" />
@@ -419,6 +424,8 @@
<module>jetty-servlets</module>
<module>jetty-util-ajax</module>
<module>jetty-jsp</module>
+ <module>apache-jsp</module>
+ <module>apache-jstl</module>
<module>jetty-maven-plugin</module>
<module>jetty-jspc-maven-plugin</module>
<module>jetty-deploy</module>
@@ -431,15 +438,17 @@
<module>jetty-client</module>
<module>jetty-proxy</module>
<module>jetty-jaspi</module>
- <module>jetty-osgi</module>
<module>jetty-rewrite</module>
<module>jetty-nosql</module>
<module>tests</module>
<module>examples</module>
+ <module>jetty-quickstart</module>
<module>jetty-distribution</module>
<module>jetty-runner</module>
<module>jetty-monitor</module>
<module>jetty-http-spi</module>
+ <module>jetty-osgi</module>
+ <module>jetty-alpn</module>
<!-- modules that need fixed and added back, or simply dropped and not maintained
<module>jetty-rhttp</module>
@@ -466,12 +475,12 @@
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
- <version>4.1</version>
+ <version>5.0.1</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
- <version>4.1</version>
+ <version>5.0.1</version>
</dependency>
<dependency>
@@ -519,6 +528,12 @@
</dependency>
<dependency>
+ <groupId>org.mortbay.jasper</groupId>
+ <artifactId>apache-jsp</artifactId>
+ <version>8.0.3.v20140313</version>
+ </dependency>
+
+ <dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
<version>3.8.2.v20130121</version>
@@ -805,102 +820,6 @@
</build>
</profile>
<profile>
- <id>7u9</id>
- <activation>
- <property>
- <name>java.version</name>
- <value>1.7.0_9</value>
- </property>
- </activation>
- <properties>
- <npn.version>1.1.3.v20130313</npn.version>
- </properties>
- </profile>
- <profile>
- <id>7u10</id>
- <activation>
- <property>
- <name>java.version</name>
- <value>1.7.0_10</value>
- </property>
- </activation>
- <properties>
- <npn.version>1.1.3.v20130313</npn.version>
- </properties>
- </profile>
- <profile>
- <id>7u11</id>
- <activation>
- <property>
- <name>java.version</name>
- <value>1.7.0_11</value>
- </property>
- </activation>
- <properties>
- <npn.version>1.1.3.v20130313</npn.version>
- </properties>
- </profile>
- <profile>
- <id>7u13</id>
- <activation>
- <property>
- <name>java.version</name>
- <value>1.7.0_13</value>
- </property>
- </activation>
- <properties>
- <npn.version>1.1.4.v20130313</npn.version>
- </properties>
- </profile>
- <profile>
- <id>7u15</id>
- <activation>
- <property>
- <name>java.version</name>
- <value>1.7.0_15</value>
- </property>
- </activation>
- <properties>
- <npn.version>1.1.5.v20130313</npn.version>
- </properties>
- </profile>
- <profile>
- <id>7u17</id>
- <activation>
- <property>
- <name>java.version</name>
- <value>1.7.0_17</value>
- </property>
- </activation>
- <properties>
- <npn.version>1.1.5.v20130313</npn.version>
- </properties>
- </profile>
- <profile>
- <id>7u21</id>
- <activation>
- <property>
- <name>java.version</name>
- <value>1.7.0_21</value>
- </property>
- </activation>
- <properties>
- <npn.version>1.1.5.v20130313</npn.version>
- </properties>
- </profile>
- <profile>
- <id>7u25</id>
- <activation>
- <property>
- <name>java.version</name>
- <value>1.7.0_25</value>
- </property>
- </activation>
- <properties>
- <npn.version>1.1.5.v20130313</npn.version>
- </properties>
- </profile>
- <profile>
<id>7u40</id>
<activation>
<property>
@@ -910,6 +829,7 @@
</activation>
<properties>
<npn.version>1.1.6.v20130911</npn.version>
+ <alpn.version>7.0.0.v20140317</alpn.version>
</properties>
</profile>
<profile>
@@ -922,6 +842,7 @@
</activation>
<properties>
<npn.version>1.1.6.v20130911</npn.version>
+ <alpn.version>7.0.0.v20140317</alpn.version>
</properties>
</profile>
<profile>
@@ -934,6 +855,7 @@
</activation>
<properties>
<npn.version>1.1.6.v20130911</npn.version>
+ <alpn.version>7.0.0.v20140317</alpn.version>
</properties>
</profile>
<profile>
@@ -946,6 +868,31 @@
</activation>
<properties>
<npn.version>1.1.7.v20140316</npn.version>
+ <alpn.version>7.0.0.v20140317</alpn.version>
+ </properties>
+ </profile>
+ <profile>
+ <id>8u00</id>
+ <activation>
+ <property>
+ <name>java.version</name>
+ <value>1.8.0</value>
+ </property>
+ </activation>
+ <properties>
+ <alpn.version>8.0.0.v20140317</alpn.version>
+ </properties>
+ </profile>
+ <profile>
+ <id>8u05</id>
+ <activation>
+ <property>
+ <name>java.version</name>
+ <value>1.8.0_05</value>
+ </property>
+ </activation>
+ <properties>
+ <alpn.version>8.0.0.v20140317</alpn.version>
</properties>
</profile>
</profiles>
diff --git a/tests/pom.xml b/tests/pom.xml
index ef36591..717de70 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.eclipse.jetty.tests</groupId>
diff --git a/tests/test-continuation/pom.xml b/tests/test-continuation/pom.xml
index ec02de3..fd6cc1e 100644
--- a/tests/test-continuation/pom.xml
+++ b/tests/test-continuation/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>tests-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/tests/test-integration/pom.xml b/tests/test-integration/pom.xml
index 3d0baac..928ec92 100644
--- a/tests/test-integration/pom.xml
+++ b/tests/test-integration/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>tests-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-integration</artifactId>
diff --git a/tests/test-loginservice/pom.xml b/tests/test-loginservice/pom.xml
index fd99f8c..263585a 100644
--- a/tests/test-loginservice/pom.xml
+++ b/tests/test-loginservice/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>tests-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<artifactId>test-loginservice</artifactId>
<name>Jetty Tests :: Login Service</name>
diff --git a/tests/test-sessions/pom.xml b/tests/test-sessions/pom.xml
index 7843d64..ec7205b 100644
--- a/tests/test-sessions/pom.xml
+++ b/tests/test-sessions/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>tests-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<artifactId>test-sessions-parent</artifactId>
<name>Jetty Tests :: Sessions :: Parent</name>
diff --git a/tests/test-sessions/test-hash-sessions/pom.xml b/tests/test-sessions/test-hash-sessions/pom.xml
index feae3f9..45b53ee 100644
--- a/tests/test-sessions/test-hash-sessions/pom.xml
+++ b/tests/test-sessions/test-hash-sessions/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-sessions-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<artifactId>test-hash-sessions</artifactId>
<name>Jetty Tests :: Sessions :: Hash</name>
diff --git a/tests/test-sessions/test-jdbc-sessions/pom.xml b/tests/test-sessions/test-jdbc-sessions/pom.xml
index 3b5e12e..8eebb4c 100644
--- a/tests/test-sessions/test-jdbc-sessions/pom.xml
+++ b/tests/test-sessions/test-jdbc-sessions/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-sessions-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<artifactId>test-jdbc-sessions</artifactId>
<name>Jetty Tests :: Sessions :: JDBC</name>
diff --git a/tests/test-sessions/test-sessions-common/pom.xml b/tests/test-sessions/test-sessions-common/pom.xml
index 369041a..c3830b8 100644
--- a/tests/test-sessions/test-sessions-common/pom.xml
+++ b/tests/test-sessions/test-sessions-common/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-sessions-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<artifactId>test-sessions-common</artifactId>
<name>Jetty Tests :: Sessions :: Common</name>
diff --git a/tests/test-webapps/pom.xml b/tests/test-webapps/pom.xml
index 5d872c3..702fb1b 100644
--- a/tests/test-webapps/pom.xml
+++ b/tests/test-webapps/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>tests-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>test-webapps-parent</artifactId>
diff --git a/tests/test-webapps/test-jaas-webapp/pom.xml b/tests/test-webapps/test-jaas-webapp/pom.xml
index f44221b..e86e72e 100644
--- a/tests/test-webapps/test-jaas-webapp/pom.xml
+++ b/tests/test-webapps/test-jaas-webapp/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-webapps-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<artifactId>test-jaas-webapp</artifactId>
<name>Jetty Tests :: WebApp :: JAAS</name>
diff --git a/tests/test-webapps/test-jetty-webapp/pom.xml b/tests/test-webapps/test-jetty-webapp/pom.xml
index 588f0c0..732c304 100644
--- a/tests/test-webapps/test-jetty-webapp/pom.xml
+++ b/tests/test-webapps/test-jetty-webapp/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-webapps-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -157,33 +157,6 @@
</loginServices>
</configuration>
</plugin>
- <!-- uncomment to precompile jsps -->
- <!--
- <plugin>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-jspc-maven-plugin</artifactId>
- <version>${project.version}</version>
- <executions>
- <execution>
- <id>jspc</id>
- <goals>
- <goal>jspc</goal>
- </goals>
- <configuration>
- <includes>**/*.foo</includes>
- <excludes>**/*.fff</excludes>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-war-plugin</artifactId>
- <configuration>
- <webXml>${basedir}/target/web.xml</webXml>
- </configuration>
- </plugin>
- -->
</plugins>
</build>
<dependencies>
@@ -261,4 +234,37 @@
<scope>provided</scope>
</dependency>
</dependencies>
+ <profiles>
+ <profile>
+ <id>precompile-jsp</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jspc-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <executions>
+ <execution>
+ <id>jspc</id>
+ <goals>
+ <goal>jspc</goal>
+ </goals>
+ <configuration>
+ <includes>**/*.foo</includes>
+ <excludes>**/*.fff</excludes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <webXml>${basedir}/target/web.xml</webXml>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
</project>
diff --git a/tests/test-webapps/test-jndi-webapp/pom.xml b/tests/test-webapps/test-jndi-webapp/pom.xml
index 31074cf..ddfe948 100644
--- a/tests/test-webapps/test-jndi-webapp/pom.xml
+++ b/tests/test-webapps/test-jndi-webapp/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-webapps-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<artifactId>test-jndi-webapp</artifactId>
<name>Jetty Tests :: WebApp :: JNDI</name>
diff --git a/tests/test-webapps/test-mock-resources/pom.xml b/tests/test-webapps/test-mock-resources/pom.xml
index 1b078df..c8e313d 100644
--- a/tests/test-webapps/test-mock-resources/pom.xml
+++ b/tests/test-webapps/test-mock-resources/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-webapps-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<name>Jetty Tests :: WebApp :: Mock Resources</name>
<artifactId>test-mock-resources</artifactId>
diff --git a/tests/test-webapps/test-proxy-webapp/pom.xml b/tests/test-webapps/test-proxy-webapp/pom.xml
index 4a3ccac..61c13f9 100644
--- a/tests/test-webapps/test-proxy-webapp/pom.xml
+++ b/tests/test-webapps/test-proxy-webapp/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-webapps-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/tests/test-webapps/test-servlet-spec/pom.xml b/tests/test-webapps/test-servlet-spec/pom.xml
index 9dccef1..07ec7ee 100644
--- a/tests/test-webapps/test-servlet-spec/pom.xml
+++ b/tests/test-webapps/test-servlet-spec/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-webapps-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<artifactId>test-servlet-spec-parent</artifactId>
<name>Jetty Tests :: Spec Test WebApp :: Parent</name>
diff --git a/tests/test-webapps/test-servlet-spec/test-container-initializer/pom.xml b/tests/test-webapps/test-servlet-spec/test-container-initializer/pom.xml
index 358b9e4..9210bab 100644
--- a/tests/test-webapps/test-servlet-spec/test-container-initializer/pom.xml
+++ b/tests/test-webapps/test-servlet-spec/test-container-initializer/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-servlet-spec-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<artifactId>test-container-initializer</artifactId>
<packaging>jar</packaging>
diff --git a/tests/test-webapps/test-servlet-spec/test-spec-webapp/pom.xml b/tests/test-webapps/test-servlet-spec/test-spec-webapp/pom.xml
index e21f34c..440a58c 100644
--- a/tests/test-webapps/test-servlet-spec/test-spec-webapp/pom.xml
+++ b/tests/test-webapps/test-servlet-spec/test-spec-webapp/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-servlet-spec-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<name>Jetty Tests :: Webapps :: Spec Webapp</name>
<artifactId>test-spec-webapp</artifactId>
diff --git a/tests/test-webapps/test-servlet-spec/test-web-fragment/pom.xml b/tests/test-webapps/test-servlet-spec/test-web-fragment/pom.xml
index eb874e8..da0f311 100644
--- a/tests/test-webapps/test-servlet-spec/test-web-fragment/pom.xml
+++ b/tests/test-webapps/test-servlet-spec/test-web-fragment/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-servlet-spec-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<name>Jetty Tests :: WebApp :: Servlet Spec :: Fragment Jar</name>
<groupId>org.eclipse.jetty.tests</groupId>
diff --git a/tests/test-webapps/test-webapp-rfc2616/pom.xml b/tests/test-webapps/test-webapp-rfc2616/pom.xml
index 8930d64..eeba737 100644
--- a/tests/test-webapps/test-webapp-rfc2616/pom.xml
+++ b/tests/test-webapps/test-webapp-rfc2616/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-webapps-parent</artifactId>
- <version>9.1.5-SNAPSHOT</version>
+ <version>9.2.0-SNAPSHOT</version>
</parent>
<artifactId>test-webapp-rfc2616</artifactId>
<name>Jetty Tests :: WebApp :: RFC2616</name>