A container for {@link ProtocolHandler}s accessible from {@link HttpClient#getProtocolHandlers()}.
*/
-public class ProtocolHandlers
+public class ProtocolHandlers implements Dumpable
{
private final Map handlers = new LinkedHashMap<>();
@@ -91,4 +93,16 @@ public class ProtocolHandlers
}
return null;
}
+
+ @Override
+ public String dump()
+ {
+ return Dumpable.dump(this);
+ }
+
+ @Override
+ public void dump(Appendable out, String indent) throws IOException
+ {
+ Dumpable.dumpObjects(out, indent, this, handlers);
+ }
}
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/ResponseNotifier.java b/jetty-client/src/main/java/org/eclipse/jetty/client/ResponseNotifier.java
index e879fd56d88..e4c2ffe3f69 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/ResponseNotifier.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/ResponseNotifier.java
@@ -30,7 +30,6 @@ import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.CountingCallback;
-import org.eclipse.jetty.util.Retainable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -122,13 +121,8 @@ public class ResponseNotifier
else
{
CountingCallback counter = new CountingCallback(callback, contentListeners.size());
- Retainable retainable = callback instanceof Retainable ? (Retainable)callback : null;
for (Response.AsyncContentListener listener : contentListeners)
- {
- if (retainable != null)
- retainable.retain();
notifyContent(listener, response, buffer.slice(), counter);
- }
}
}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java
index 16858c0c879..a8a263772bf 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java
@@ -19,6 +19,7 @@
package org.eclipse.jetty.client;
import java.nio.file.Path;
+import java.util.function.Consumer;
import java.util.stream.Stream;
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
@@ -30,6 +31,8 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.SocketAddressResolver;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
+import org.eclipse.jetty.util.thread.Scheduler;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
@@ -64,19 +67,32 @@ public abstract class AbstractHttpClientServerTest
protected void startClient(final Scenario scenario) throws Exception
{
- startClient(scenario, new HttpClientTransportOverHTTP(1));
+ startClient(scenario, null,null);
}
- protected void startClient(final Scenario scenario, HttpClientTransport transport) throws Exception
+ protected void startClient(final Scenario scenario, HttpClientTransport transport, Consumer config) throws Exception
{
- QueuedThreadPool clientThreads = new QueuedThreadPool();
- clientThreads.setName("client");
- client = new HttpClient(transport, scenario.newSslContextFactory());
- client.setExecutor(clientThreads);
+ if (transport==null)
+ transport = new HttpClientTransportOverHTTP(1);
+
+ QueuedThreadPool executor = new QueuedThreadPool();
+ executor.setName("client");
+ Scheduler scheduler = new ScheduledExecutorScheduler("client-scheduler", false);
+ client = newHttpClient(scenario, transport);
+ client.setExecutor(executor);
+ client.setScheduler(scheduler);
client.setSocketAddressResolver(new SocketAddressResolver.Sync());
+ if (config!=null)
+ config.accept(client);
+
client.start();
}
+ public HttpClient newHttpClient(Scenario scenario, HttpClientTransport transport)
+ {
+ return new HttpClient(transport, scenario.newSslContextFactory());
+ }
+
@AfterEach
public void disposeClient() throws Exception
{
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
index 9afbf8c32fa..d3470da5e33 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
@@ -111,6 +111,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
{
public WorkDir testdir;
+
@ParameterizedTest
@ArgumentsSource(ScenarioProvider.class)
public void testStoppingClosesConnections(Scenario scenario) throws Exception
@@ -880,31 +881,33 @@ public class HttpClientTest extends AbstractHttpClientServerTest
@ArgumentsSource(ScenarioProvider.class)
public void testConnectHostWithMultipleAddresses(Scenario scenario) throws Exception
{
- start(scenario, new EmptyServerHandler());
-
- client.setSocketAddressResolver(new SocketAddressResolver.Async(client.getExecutor(), client.getScheduler(), client.getConnectTimeout())
+ startServer(scenario, new EmptyServerHandler());
+ startClient(scenario, null, client ->
{
- @Override
- public void resolve(String host, int port, Promise> promise)
+ client.setSocketAddressResolver(new SocketAddressResolver.Async(client.getExecutor(), client.getScheduler(), 5000)
{
- super.resolve(host, port, new Promise>()
+ @Override
+ public void resolve(String host, int port, Promise> promise)
{
- @Override
- public void succeeded(List result)
+ super.resolve(host, port, new Promise>()
{
- // Add as first address an invalid address so that we test
- // that the connect operation iterates over the addresses.
- result.add(0, new InetSocketAddress("idontexist", port));
- promise.succeeded(result);
- }
+ @Override
+ public void succeeded(List result)
+ {
+ // Add as first address an invalid address so that we test
+ // that the connect operation iterates over the addresses.
+ result.add(0, new InetSocketAddress("idontexist", port));
+ promise.succeeded(result);
+ }
- @Override
- public void failed(Throwable x)
- {
- promise.failed(x);
- }
- });
- }
+ @Override
+ public void failed(Throwable x)
+ {
+ promise.failed(x);
+ }
+ });
+ }
+ });
});
// If no exceptions the test passes.
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpConnectionLifecycleTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpConnectionLifecycleTest.java
index 243303f5345..624092493a6 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpConnectionLifecycleTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpConnectionLifecycleTest.java
@@ -43,7 +43,6 @@ import org.eclipse.jetty.client.http.HttpDestinationOverHTTP;
import org.eclipse.jetty.client.util.ByteBufferContentProvider;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpVersion;
-import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.StacklessLogging;
@@ -55,10 +54,11 @@ import org.junit.jupiter.params.provider.ArgumentsSource;
public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
{
@Override
- public void start(Scenario scenario, Handler handler) throws Exception
+ public HttpClient newHttpClient(Scenario scenario, HttpClientTransport transport)
{
- super.start(scenario, handler);
+ HttpClient client = super.newHttpClient(scenario, transport);
client.setStrictEventOrdering(false);
+ return client;
}
@ParameterizedTest
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ValidatingConnectionPoolTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ValidatingConnectionPoolTest.java
index aa9a8381e1c..c3f1f8196ba 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/ValidatingConnectionPoolTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ValidatingConnectionPoolTest.java
@@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue;
@@ -43,13 +42,13 @@ import org.junit.jupiter.params.provider.ArgumentsSource;
public class ValidatingConnectionPoolTest extends AbstractHttpClientServerTest
{
@Override
- protected void startClient(final Scenario scenario) throws Exception
+ public HttpClient newHttpClient(Scenario scenario, HttpClientTransport transport)
{
long timeout = 1000;
- HttpClientTransportOverHTTP transport = new HttpClientTransportOverHTTP(1);
transport.setConnectionPoolFactory(destination ->
new ValidatingConnectionPool(destination, destination.getHttpClient().getMaxConnectionsPerDestination(), destination, destination.getHttpClient().getScheduler(), timeout));
- startClient(scenario, transport);
+
+ return super.newHttpClient(scenario, transport);
}
@ParameterizedTest
diff --git a/jetty-continuation/pom.xml b/jetty-continuation/pom.xml
index 05bb24b9448..c3b362e2e15 100644
--- a/jetty-continuation/pom.xml
+++ b/jetty-continuation/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-continuation
diff --git a/jetty-deploy/pom.xml b/jetty-deploy/pom.xml
index 494743c4d96..c2098f806b3 100644
--- a/jetty-deploy/pom.xml
+++ b/jetty-deploy/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-deploy
diff --git a/jetty-distribution/pom.xml b/jetty-distribution/pom.xml
index 40286e5ab3c..05976455701 100644
--- a/jetty-distribution/pom.xml
+++ b/jetty-distribution/pom.xml
@@ -4,7 +4,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-distribution
diff --git a/jetty-documentation/pom.xml b/jetty-documentation/pom.xml
index c0d5a837f41..1831363afcc 100644
--- a/jetty-documentation/pom.xml
+++ b/jetty-documentation/pom.xml
@@ -4,7 +4,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOTjetty-documentationJetty :: Documentation
diff --git a/jetty-documentation/src/main/asciidoc/administration/startup/startup-jpms.adoc b/jetty-documentation/src/main/asciidoc/administration/startup/startup-jpms.adoc
index 075b75d9c96..51f3b6b2984 100644
--- a/jetty-documentation/src/main/asciidoc/administration/startup/startup-jpms.adoc
+++ b/jetty-documentation/src/main/asciidoc/administration/startup/startup-jpms.adoc
@@ -19,16 +19,17 @@
[[startup-jpms]]
=== Startup using the Java Platform Module System (JPMS)
-Jetty modules also act ass automatic https://en.wikipedia.org/wiki/Java_Platform_Module_System[JPMS] modules via the `Automatic-Module-Name` attribute in the jar's `MANIFEST.MF` file.
+Jetty modules also act as automatic https://en.wikipedia.org/wiki/Java_Platform_Module_System[JPMS] modules via the `Automatic-Module-Name` attribute in the jar's `MANIFEST.MF` file.
This makes possible to run Jetty from the module-path, rather than the class-path.
-We recommend using JDK 11 or greater due to the fact that JDK 11 removed all the "enterprise" modules from the JDK.
+We recommend using JDK 11 or greater due to the fact that JDK 11 removed all the "enterprise" modules from the JDK,
+and therefore it guarantees a more stable platform to base your application's dependencies on.
The classes in these "enterprise" modules were bundled with JDK 8, and present in "enterprise" modules in JDK 9 and JDK 10.
With JDK 11, these "enterprise" classes are either not available in the JDK (because their corresponding module was removed), or they are present in a different module.
Because some of these "enterprise" classes are required by Jetty or by applications running in Jetty, it is better to use a stable source for those classes - in this case by using JDK 11
-or greater.
+or greater, and explicitly referencing the "enterprise" classes as dependencies, rather than assuming they are bundled with the JDK.
[[jpms-module-path]]
==== Starting Jetty on the module-path
@@ -53,7 +54,6 @@ The server then starts Jetty on the module-path using the `--jpms` option.
----
[NOTE]
When running on the module-path using the `--jpms` option, the Jetty start mechanism will fork a second JVM passing it the right JVM options to run on the module-path.
-
You will have two JVMs running: one that runs `start.jar` and one that runs Jetty on the module-path.
----
@@ -64,7 +64,7 @@ If you are interested in the details of how the command line to run Jetty on the
$ java -jar $JETTY_HOME/start.jar --jpms --dry-run
....
-This will give an out put looking something like this (broken in sections for clarity):
+This will give an output looking something like this (broken in sections for clarity):
[source, screen, subs="{sub-order}"]
....
@@ -156,3 +156,37 @@ add-opens: /=(,)*
add-exports: /=(,)*
add-reads: =(,)*
....
+
+[[jpms-module-path-alternative]]
+==== Alternative way to start Jetty on the module-path
+
+The section above uses the `--jpms` command line option to start Jetty on the module-path.
+An alternative way of achieving the same result is to use a Jetty module, `$JETTY_BASE/modules/jpms.mod`,
+that specifies that you want to run using JPMS (and possibly add some JPMS specific configuration).
+
+[source, screen, subs="{sub-order}"]
+.jpms.mod
+....
+[ini]
+--jpms
+
+[jpms]
+# Additional JPMS configuration.
+....
+
+The `[ini]` section is equivalent to passing the `--jpms` option to the command line.
+The `[jpms]` section (see also the link:#jpms-advanced-config[advanced JPMS configuration section])
+allows you specify additional JPMS configuration.
+
+[source, screen, subs="{sub-order}"]
+....
+$ mkdir jetty-base-jpms
+$ cd jetty-base-jpms
+$ mkdir modules
+# Copy the jpms.mod file above into the $JETTY_BASE/modules/ directory.
+$ cp /tmp/jpms.mod modules/
+# Add both the http and the jpms modules.
+$ java -jar $JETTY_HOME/start.jar --add-to-start=http,jpms
+# Jetty will start on the module-path.
+$ java -jar $JETTY_HOME/start.jar
+....
diff --git a/jetty-documentation/src/main/asciidoc/configuring/connectors/configuring-ssl.adoc b/jetty-documentation/src/main/asciidoc/configuring/connectors/configuring-ssl.adoc
index 8fd729a0d4e..c7c64a66e5a 100644
--- a/jetty-documentation/src/main/asciidoc/configuring/connectors/configuring-ssl.adoc
+++ b/jetty-documentation/src/main/asciidoc/configuring/connectors/configuring-ssl.adoc
@@ -754,11 +754,14 @@ New cipher suites are always being developed to stay ahead of attacks.
It's only a matter of time before the best of suites is exploited though, and making sure your server is up-to-date in this regard is paramount for any implementation.
As an example, to avoid the BEAST attack it is necessary to configure a specific set of cipher suites. This can either be done via link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html#setIncludeCipherSuites(java.lang.String...)[SslContext.setIncludeCipherSuites(java.lang.String...)] or vialink:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html#setExcludeCipherSuites(java.lang.String...)[SslContext.setExcludeCipherSuites(java.lang.String...)].
-____
-[NOTE]
It's crucial that you use the _exact_ names of the cipher suites as used/known by the JDK.
You can get them by obtaining an instance of SSLEngine and call `getSupportedCipherSuites()`.
Tools like https://www.ssllabs.com/[ssllabs.com] might report slightly different names which will be ignored.
+
+____
+[IMPORTANT]
+It is important to stay up-to-date with the latest supported cipher suites.
+Be sure to consult Oracle's link:https://java.com/en/jre-jdk-cryptoroadmap.html[JRE and JDK Cryptographic Roadmap] frequently for recent and upcoming changes to supported ciphers.
____
____
@@ -769,7 +772,6 @@ Just overwrite the two present JAR files in `/lib/security/`.
____
Both `setIncludeCipherSuites` and `setExcludeCipherSuites` can be fed by the exact cipher suite name used in the JDK or by using regular expressions.
-
If you have a need to adjust the Includes or Excludes, then this is best done with a custom XML that configures the `SslContextFactory` to suit your needs.
____
@@ -979,7 +981,7 @@ Specifically, you will want to look for the `SslConnectionFactory` portion of th
...
----
-In the example above you can see both the enabled/disabled protocols and included/excluded ciper suites.
+In the example above you can see both the enabled/disabled protocols and included/excluded cipher suites.
For disabled or excluded protocols and ciphers, the reason they are disabled is given - either due to JVM restrictions, configuration or both.
As a reminder, when configuring your includes/excludes, *excludes always win*.
diff --git a/jetty-documentation/src/main/asciidoc/development/frameworks/osgi.adoc b/jetty-documentation/src/main/asciidoc/development/frameworks/osgi.adoc
index da23e5dc9e2..2a890bef3e2 100644
--- a/jetty-documentation/src/main/asciidoc/development/frameworks/osgi.adoc
+++ b/jetty-documentation/src/main/asciidoc/development/frameworks/osgi.adoc
@@ -55,11 +55,8 @@ You *must also install the Apache Aries SPI Fly bundles* as many parts of Jetty
[cols=",,",options="header",]
|=======================================================================
|Jar |Bundle Symbolic Name |Location
-|org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle-1.0.1.jar |org.apache.aries.spifly.dynamic.bundle
+|org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle-1.1.jar |org.apache.aries.spifly.dynamic.bundle
|https://repo1.maven.org/maven2/org/apache/aries/spifly/org.apache.aries.spifly.dynamic.bundle/[Maven central]
-|org.apache.aries:org.apache.aries.util-1.0.1.jar |org.apache.aries.util
-|https://repo1.maven.org/maven2/org/apache/aries/org.apache.aries.util/[Maven
-central]
|=======================================================================
____
@@ -835,13 +832,13 @@ In order to use them with Jetty in OSGi, you will need to deploy some extra jars
|=======================================================================
|Jar |Bundle Symbolic Name |Location
|The link:#spifly[spifly jars] | |
-|org.ow2.asm:asm-5.0.1.jar |org.objectweb.asm
+|org.ow2.asm:asm-7.0.jar |org.objectweb.asm
|https://repo1.maven.org/maven2/org/ow2/asm/asm[Maven central]
-|org.ow2.asm:asm-commons-5.0.1.jar |org.objectweb.asm.commons
+|org.ow2.asm:asm-commons-7.0.jar |org.objectweb.asm.commons
|https://repo1.maven.org/maven2/org/ow2/asm/asm-commons[Maven central]
-|org.ow2.asm:asm-tree-5.0.1.jar |org.objectweb.asm.tree
+|org.ow2.asm:asm-tree-7.0.jar |org.objectweb.asm.tree
|https://repo1.maven.org/maven2/org/ow2/asm/asm-tree[Maven central]
|javax.annotation:javax.annotation-api-1.2.jar |javax.annotation-api
@@ -1099,32 +1096,31 @@ You should see output similar to this on the console, using the `felix:lb` comma
....
ID|State |Level|Name
0|Active | 0|System Bundle (4.4.1)
- 1|Active | 1|ASM (5.0.1)
- 2|Active | 1|ASM commons classes (5.0.1)
- 3|Active | 1|ASM Tree class visitor (5.0.1)
+ 1|Active | 1|ASM (7.0)
+ 2|Active | 1|ASM commons classes (7.0)
+ 3|Active | 1|ASM Tree class visitor (7.0)
4|Active | 1|geronimo-jta_1.1_spec (1.1.1)
5|Active | 1|javax.annotation API (1.2.0)
6|Active | 1|javax.mail bundle from Glassfish (1.4.1.v201005082020)
7|Active | 1|Java Server Pages Standard Tag Library API Bundle (1.2.0.v201105211821)
8|Active | 1|JavaServer Pages (TM) TagLib Implementation (1.2.2)
- 9|Active | 1|Jetty :: Servlet Annotations (9.2.4.SNAPSHOT)
- 10|Active | 1|Jetty :: Deployers (9.2.4.SNAPSHOT)
- 11|Active | 1|Jetty :: Http Utility (9.2.4.SNAPSHOT)
- 12|Active | 1|Jetty :: IO Utility (9.2.4.SNAPSHOT)
- 13|Active | 1|Jetty :: JNDI Naming (9.2.4.SNAPSHOT)
- 14|Active | 1|Jetty :: OSGi :: Boot (9.2.4.SNAPSHOT)
- 15|Resolved | 1|Jetty-OSGi-Jasper Integration (9.2.4.SNAPSHOT)
- 16|Active | 1|Jetty Servlet API and Schemas for OSGi (3.1.0.SNAPSHOT)
- 17|Active | 1|Jetty :: Plus (9.2.4.SNAPSHOT)
- 18|Active | 1|Jetty :: Security (9.2.4.SNAPSHOT)
- 19|Active | 1|Jetty :: Server Core (9.2.4.SNAPSHOT)
- 20|Active | 1|Jetty :: Servlet Handling (9.2.4.SNAPSHOT)
- 21|Active | 1|Jetty :: Utility Servlets and Filters (9.2.4.SNAPSHOT)
- 22|Active | 1|Jetty :: Utilities (9.2.4.SNAPSHOT)
- 23|Active | 1|Jetty :: Webapp Application Support (9.2.4.SNAPSHOT)
- 24|Active | 1|Jetty :: XML utilities (9.2.4.SNAPSHOT)
- 25|Active | 1|Apache Aries SPI Fly Dynamic Weaving Bundle (1.0.1)
- 26|Active | 1|Apache Aries Util (1.0.0)
+ 9|Active | 1|Jetty :: Servlet Annotations (9.4.14)
+ 10|Active | 1|Jetty :: Deployers (9.4.14)
+ 11|Active | 1|Jetty :: Http Utility (9.4.14)
+ 12|Active | 1|Jetty :: IO Utility (9.4.14)
+ 13|Active | 1|Jetty :: JNDI Naming (9.4.14)
+ 14|Active | 1|Jetty :: OSGi :: Boot (9.4.14)
+ 15|Resolved | 1|Jetty-OSGi-Jasper Integration (9.4.14)
+ 16|Active | 1|Jetty Servlet API and Schemas for OSGi (3.1.0)
+ 17|Active | 1|Jetty :: Plus (9.4.14)
+ 18|Active | 1|Jetty :: Security (9.4.14)
+ 19|Active | 1|Jetty :: Server Core (9.4.14)
+ 20|Active | 1|Jetty :: Servlet Handling (9.4.14)
+ 21|Active | 1|Jetty :: Utility Servlets and Filters (9.4.14)
+ 22|Active | 1|Jetty :: Utilities (9.4.14)
+ 23|Active | 1|Jetty :: Webapp Application Support (9.4.14)
+ 24|Active | 1|Jetty :: XML utilities (9.4.14)
+ 25|Active | 1|Apache Aries SPI Fly Dynamic Weaving Bundle (1.1)
27|Active | 1|Apache Felix Bundle Repository (2.0.2)
28|Active | 1|Apache Felix Configuration Admin Service (1.8.0)
29|Active | 1|Apache Felix EventAdmin (1.3.2)
@@ -1132,10 +1128,10 @@ You should see output similar to this on the console, using the `felix:lb` comma
31|Active | 1|Apache Felix Gogo Runtime (0.12.1)
32|Active | 1|Apache Felix Gogo Shell (0.10.0)
33|Active | 1|Apache Felix Log Service (1.0.1)
- 34|Active | 1|Jetty :: Apache JSP (9.2.4.SNAPSHOT)
+ 34|Active | 1|Jetty :: Apache JSP (9.4.14)
35|Active | 1|Eclipse Compiler for Java(TM) (3.8.2.v20130121-145325)
- 36|Active | 1|Mortbay EL API and Implementation (8.0.9)
- 37|Active | 1|Mortbay Jasper (8.0.9)
+ 36|Active | 1|Mortbay EL API and Implementation (8.5.33.1)
+ 37|Active | 1|Mortbay Jasper (8.5.33.1)
....
===== Eclipse
diff --git a/jetty-fcgi/fcgi-client/pom.xml b/jetty-fcgi/fcgi-client/pom.xml
index 3fef8abe2ed..f19dbc4c00d 100644
--- a/jetty-fcgi/fcgi-client/pom.xml
+++ b/jetty-fcgi/fcgi-client/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jetty.fcgifcgi-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-fcgi/fcgi-server/pom.xml b/jetty-fcgi/fcgi-server/pom.xml
index 3d065b8a36d..cb4821b9393 100644
--- a/jetty-fcgi/fcgi-server/pom.xml
+++ b/jetty-fcgi/fcgi-server/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jetty.fcgifcgi-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-fcgi/pom.xml b/jetty-fcgi/pom.xml
index c8bcc7ffb5a..5518b95be0e 100644
--- a/jetty-fcgi/pom.xml
+++ b/jetty-fcgi/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-gcloud/jetty-gcloud-session-manager/pom.xml b/jetty-gcloud/jetty-gcloud-session-manager/pom.xml
index 66c7a9f6430..c8504c6e5fb 100644
--- a/jetty-gcloud/jetty-gcloud-session-manager/pom.xml
+++ b/jetty-gcloud/jetty-gcloud-session-manager/pom.xml
@@ -5,7 +5,7 @@
org.eclipse.jetty.gcloudgcloud-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-gcloud/pom.xml b/jetty-gcloud/pom.xml
index c0d7c073302..36d6e349e86 100644
--- a/jetty-gcloud/pom.xml
+++ b/jetty-gcloud/pom.xml
@@ -3,7 +3,7 @@
jetty-projectorg.eclipse.jetty
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-hazelcast/pom.xml b/jetty-hazelcast/pom.xml
index ce9f253094d..27b42703875 100644
--- a/jetty-hazelcast/pom.xml
+++ b/jetty-hazelcast/pom.xml
@@ -4,7 +4,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-home/pom.xml b/jetty-home/pom.xml
index 298d78ee5be..fb0a49adc3d 100644
--- a/jetty-home/pom.xml
+++ b/jetty-home/pom.xml
@@ -3,7 +3,7 @@
jetty-projectorg.eclipse.jetty
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-home
diff --git a/jetty-http-spi/pom.xml b/jetty-http-spi/pom.xml
index 5070cb4560a..ebbdedb7366 100644
--- a/jetty-http-spi/pom.xml
+++ b/jetty-http-spi/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-http-spi
diff --git a/jetty-http/pom.xml b/jetty-http/pom.xml
index af67747e28d..2858016c396 100644
--- a/jetty-http/pom.xml
+++ b/jetty-http/pom.xml
@@ -3,7 +3,7 @@
jetty-projectorg.eclipse.jetty
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-http
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 579b5ac90e5..a00e3e6c49a 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
@@ -767,7 +767,7 @@ public class HttpParser
case LF:
setState(State.HEADER);
- handle=_responseHandler.startResponse(_version, _responseStatus, null)||handle;
+ handle |= _responseHandler.startResponse(_version, _responseStatus, null);
break;
default:
@@ -789,7 +789,7 @@ public class HttpParser
handle=_requestHandler.startRequest(_methodString,_uri.toString(), HttpVersion.HTTP_0_9);
setState(State.END);
BufferUtil.clear(buffer);
- handle= handleHeaderContentMessage() || handle;
+ handle |= handleHeaderContentMessage();
break;
case ALPHA:
@@ -865,7 +865,7 @@ public class HttpParser
if (_responseHandler!=null)
{
setState(State.HEADER);
- handle=_responseHandler.startResponse(_version, _responseStatus, null)||handle;
+ handle |= _responseHandler.startResponse(_version, _responseStatus, null);
}
else
{
@@ -876,7 +876,7 @@ public class HttpParser
handle=_requestHandler.startRequest(_methodString,_uri.toString(), HttpVersion.HTTP_0_9);
setState(State.END);
BufferUtil.clear(buffer);
- handle= handleHeaderContentMessage() || handle;
+ handle |= handleHeaderContentMessage();
}
break;
@@ -905,7 +905,7 @@ public class HttpParser
setState(State.HEADER);
- handle=_requestHandler.startRequest(_methodString,_uri.toString(), _version)||handle;
+ handle |= _requestHandler.startRequest(_methodString,_uri.toString(), _version);
continue;
case ALPHA:
@@ -927,7 +927,7 @@ public class HttpParser
case LF:
String reason=takeString();
setState(State.HEADER);
- handle=_responseHandler.startResponse(_version, _responseStatus, reason)||handle;
+ handle |= _responseHandler.startResponse(_version, _responseStatus, reason);
continue;
case ALPHA:
@@ -1808,7 +1808,6 @@ public class HttpParser
/* ------------------------------------------------------------------------------- */
public boolean isAtEOF()
-
{
return _eof;
}
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpTester.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpTester.java
index 60d5a50c06e..6b2a2f01acf 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpTester.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpTester.java
@@ -27,7 +27,6 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -110,13 +109,28 @@ public class HttpTester
public static Response parseResponse(InputStream responseStream) throws IOException
{
- ByteArrayOutputStream contentStream = new ByteArrayOutputStream();
- IO.copy(responseStream, contentStream);
-
Response r=new Response();
HttpParser parser =new HttpParser(r);
- parser.parseNext(ByteBuffer.wrap(contentStream.toByteArray()));
- return r;
+
+ // Read and parse a character at a time so we never can read more than we should.
+ byte[] array = new byte[1];
+ ByteBuffer buffer = ByteBuffer.wrap(array);
+ buffer.limit(1);
+
+ while(true)
+ {
+ buffer.position(1);
+ int l = responseStream.read(array);
+ if (l<0)
+ parser.atEOF();
+ else
+ buffer.position(0);
+
+ if (parser.parseNext(buffer))
+ return r;
+ else if (l<0)
+ return null;
+ }
}
public abstract static class Input
diff --git a/jetty-http2/http2-alpn-tests/pom.xml b/jetty-http2/http2-alpn-tests/pom.xml
index 6eff280901f..b32ac4a9461 100644
--- a/jetty-http2/http2-alpn-tests/pom.xml
+++ b/jetty-http2/http2-alpn-tests/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jetty.http2http2-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-http2/http2-client/pom.xml b/jetty-http2/http2-client/pom.xml
index 5d2bd3a3d3d..ec563b87475 100644
--- a/jetty-http2/http2-client/pom.xml
+++ b/jetty-http2/http2-client/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jetty.http2http2-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-http2/http2-common/pom.xml b/jetty-http2/http2-common/pom.xml
index d9bcdda6058..7724411ccb1 100644
--- a/jetty-http2/http2-common/pom.xml
+++ b/jetty-http2/http2-common/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jetty.http2http2-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Connection.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Connection.java
index c3739f7bd7d..d1ee4dd829d 100644
--- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Connection.java
+++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Connection.java
@@ -23,7 +23,6 @@ import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.jetty.http2.frames.DataFrame;
@@ -31,10 +30,10 @@ import org.eclipse.jetty.http2.parser.Parser;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.io.RetainableByteBuffer;
import org.eclipse.jetty.io.WriteFlusher;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
-import org.eclipse.jetty.util.Retainable;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -217,8 +216,8 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
private void setInputBuffer(ByteBuffer byteBuffer)
{
- if (networkBuffer == null)
- networkBuffer = acquireNetworkBuffer();
+ acquireNetworkBuffer();
+ // TODO handle buffer overflow?
networkBuffer.put(byteBuffer);
}
@@ -234,93 +233,104 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
if (isFillInterested() || shutdown || failed)
return null;
- if (networkBuffer == null)
- networkBuffer = acquireNetworkBuffer();
-
- boolean parse = networkBuffer.hasRemaining();
-
- while (true)
+ boolean interested = false;
+ acquireNetworkBuffer();
+ try
{
- if (parse)
+ boolean parse = networkBuffer.hasRemaining();
+
+ while (true)
{
- boolean released;
- networkBuffer.retain();
- try
+ if (parse)
{
while (networkBuffer.hasRemaining())
{
- parser.parse(networkBuffer.buffer);
+ parser.parse(networkBuffer.getBuffer());
if (failed)
return null;
}
- }
- finally
- {
- released = networkBuffer.release();
- if (failed && released)
- releaseNetworkBuffer();
+
+ task = pollTask();
+ if (LOG.isDebugEnabled())
+ LOG.debug("Dequeued new task {}", task);
+ if (task != null)
+ return task;
+
+ // If more references than 1 (ie not just us), don't refill into buffer and risk compaction.
+ if (networkBuffer.getReferences() > 1)
+ reacquireNetworkBuffer();
}
- task = pollTask();
+ // Here we know that this.networkBuffer is not retained by
+ // application code: either it has been released, or it's a new one.
+ int filled = fill(getEndPoint(), networkBuffer.getBuffer());
if (LOG.isDebugEnabled())
- LOG.debug("Dequeued new task {}", task);
- if (task != null)
+ LOG.debug("Filled {} bytes in {}", filled, networkBuffer);
+
+ if (filled > 0)
{
- if (released)
- releaseNetworkBuffer();
- else
- networkBuffer = null;
- return task;
+ bytesIn.addAndGet(filled);
+ parse = true;
+ }
+ else if (filled == 0)
+ {
+ interested = true;
+ return null;
}
else
{
- if (!released)
- networkBuffer = acquireNetworkBuffer();
+ shutdown = true;
+ session.onShutdown();
+ return null;
}
}
-
- // Here we know that this.buffer is not retained:
- // either it has been released, or it's a new one.
-
- int filled = fill(getEndPoint(), networkBuffer.buffer);
- if (LOG.isDebugEnabled())
- LOG.debug("Filled {} bytes in {}", filled, networkBuffer);
-
- if (filled > 0)
- {
- bytesIn.addAndGet(filled);
- parse = true;
- }
- else if (filled == 0)
- {
- releaseNetworkBuffer();
+ }
+ finally
+ {
+ releaseNetworkBuffer();
+ if (interested)
getEndPoint().fillInterested(fillableCallback);
- return null;
- }
- else
- {
- releaseNetworkBuffer();
- shutdown = true;
- session.onShutdown();
- return null;
- }
}
}
- private NetworkBuffer acquireNetworkBuffer()
+ private void acquireNetworkBuffer()
{
- NetworkBuffer networkBuffer = new NetworkBuffer();
+ if (networkBuffer == null)
+ {
+ networkBuffer = new NetworkBuffer();
+ if (LOG.isDebugEnabled())
+ LOG.debug("Acquired {}", networkBuffer);
+ }
+ }
+
+ private void reacquireNetworkBuffer()
+ {
+ NetworkBuffer currentBuffer = networkBuffer;
+ if (currentBuffer == null)
+ throw new IllegalStateException();
+
+ if (currentBuffer.getBuffer().hasRemaining())
+ throw new IllegalStateException();
+
+ currentBuffer.release();
+ networkBuffer = new NetworkBuffer();
if (LOG.isDebugEnabled())
- LOG.debug("Acquired {}", networkBuffer);
- return networkBuffer;
+ LOG.debug("Reacquired {}<-{}", currentBuffer, networkBuffer);
}
private void releaseNetworkBuffer()
{
- if (LOG.isDebugEnabled())
- LOG.debug("Released {}", networkBuffer);
- networkBuffer.recycle();
+ NetworkBuffer currentBuffer = networkBuffer;
+ if (currentBuffer == null)
+ throw new IllegalStateException();
+
+ if (currentBuffer.hasRemaining() && !shutdown && !failed)
+ throw new IllegalStateException();
+
+ currentBuffer.release();
networkBuffer = null;
+ if (LOG.isDebugEnabled())
+ LOG.debug("Released {}", currentBuffer);
}
@Override
@@ -375,56 +385,36 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
}
}
- private class NetworkBuffer implements Callback, Retainable
+ private class NetworkBuffer extends RetainableByteBuffer implements Callback
{
- private final AtomicInteger refCount = new AtomicInteger();
- private final ByteBuffer buffer;
-
private NetworkBuffer()
{
- buffer = byteBufferPool.acquire(bufferSize, false); // TODO: make directness customizable
+ super(byteBufferPool,bufferSize,false);
}
private void put(ByteBuffer source)
{
- BufferUtil.append(buffer, source);
- }
-
- private boolean hasRemaining()
- {
- return buffer.hasRemaining();
- }
-
- @Override
- public void retain()
- {
- refCount.incrementAndGet();
- }
-
- private boolean release()
- {
- return refCount.decrementAndGet() == 0;
+ BufferUtil.append(getBuffer(), source);
}
@Override
public void succeeded()
{
- if (release())
- {
- if (LOG.isDebugEnabled())
- LOG.debug("Released retained {}", this);
- recycle();
- }
+ completed(null);
}
@Override
public void failed(Throwable failure)
{
- if (release())
+ completed(failure);
+ }
+
+ private void completed(Throwable failure)
+ {
+ if (release() == 0)
{
if (LOG.isDebugEnabled())
LOG.debug("Released retained " + this, failure);
- recycle();
}
}
@@ -433,16 +423,5 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
{
return InvocationType.NON_BLOCKING;
}
-
- private void recycle()
- {
- byteBufferPool.release(buffer);
- }
-
- @Override
- public String toString()
- {
- return String.format("%s@%x[%s]", getClass().getSimpleName(), hashCode(), buffer);
- }
}
}
diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Session.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Session.java
index 9c570c37d54..e1079aeb0ff 100644
--- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Session.java
+++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Session.java
@@ -1208,7 +1208,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
@Override
public void dump(Appendable out, String indent) throws IOException
{
- dumpBeans(out, indent, new DumpableCollection("streams", streams.values()));
+ dumpObjects(out, indent, new DumpableCollection("streams", streams.values()));
}
@Override
diff --git a/jetty-http2/http2-hpack/pom.xml b/jetty-http2/http2-hpack/pom.xml
index fe042116485..fd576cb3e57 100644
--- a/jetty-http2/http2-hpack/pom.xml
+++ b/jetty-http2/http2-hpack/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jetty.http2http2-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-http2/http2-http-client-transport/pom.xml b/jetty-http2/http2-http-client-transport/pom.xml
index b25a8a679d1..f1bab72140d 100644
--- a/jetty-http2/http2-http-client-transport/pom.xml
+++ b/jetty-http2/http2-http-client-transport/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jetty.http2http2-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-http2/http2-server/pom.xml b/jetty-http2/http2-server/pom.xml
index 64dcaa4f2f1..9694022d5cd 100644
--- a/jetty-http2/http2-server/pom.xml
+++ b/jetty-http2/http2-server/pom.xml
@@ -4,7 +4,7 @@
org.eclipse.jetty.http2http2-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-http2/pom.xml b/jetty-http2/pom.xml
index 1c711777008..7ddf66e6ce8 100644
--- a/jetty-http2/pom.xml
+++ b/jetty-http2/pom.xml
@@ -3,7 +3,7 @@
jetty-projectorg.eclipse.jetty
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-infinispan/pom.xml b/jetty-infinispan/pom.xml
index 921c93aaf4b..19682871a81 100644
--- a/jetty-infinispan/pom.xml
+++ b/jetty-infinispan/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-infinispan
diff --git a/jetty-io/pom.xml b/jetty-io/pom.xml
index 88a36122609..5b67f9e3dbc 100644
--- a/jetty-io/pom.xml
+++ b/jetty-io/pom.xml
@@ -2,7 +2,7 @@
jetty-projectorg.eclipse.jetty
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-io
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ChannelEndPoint.java
index 0421176298f..84e80276e28 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/ChannelEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ChannelEndPoint.java
@@ -31,7 +31,6 @@ 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.Invocable;
-import org.eclipse.jetty.util.thread.Locker;
import org.eclipse.jetty.util.thread.Scheduler;
/**
@@ -426,21 +425,11 @@ public abstract class ChannelEndPoint extends AbstractEndPoint implements Manage
public String toEndPointString()
{
// We do a best effort to print the right toString() and that's it.
- try
- {
- boolean valid = _key != null && _key.isValid();
- int keyInterests = valid ? _key.interestOps() : -1;
- int keyReadiness = valid ? _key.readyOps() : -1;
- return String.format("%s{io=%d/%d,kio=%d,kro=%d}",
- super.toEndPointString(),
- _currentInterestOps,
- _desiredInterestOps,
- keyInterests,
- keyReadiness);
- }
- catch (Throwable x)
- {
- return String.format("%s{io=%s,kio=-2,kro=-2}", super.toString(), _desiredInterestOps);
- }
+ return String.format("%s{io=%d/%d,kio=%d,kro=%d}",
+ super.toEndPointString(),
+ _currentInterestOps,
+ _desiredInterestOps,
+ ManagedSelector.safeInterestOps(_key),
+ ManagedSelector.safeReadyOps(_key));
}
}
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java
index 3197f2ad1f8..b379c60a25c 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java
@@ -31,7 +31,6 @@ import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
@@ -273,6 +272,34 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
}
}
+ static int safeReadyOps(SelectionKey selectionKey)
+ {
+ try
+ {
+ return selectionKey.readyOps();
+ }
+ catch (Throwable x)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug(x);
+ return -1;
+ }
+ }
+
+ static int safeInterestOps(SelectionKey selectionKey)
+ {
+ try
+ {
+ return selectionKey.interestOps();
+ }
+ catch (Throwable x)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug(x);
+ return -1;
+ }
+ }
+
@Override
public void dump(Appendable out, String indent) throws IOException
{
@@ -297,13 +324,13 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
if (keys==null)
keys = Collections.singletonList("No dump keys retrieved");
- dumpBeans(out, indent,
+ dumpObjects(out, indent,
new DumpableCollection("updates @ "+updatesAt, updates),
new DumpableCollection("keys @ "+keysAt, keys));
}
else
{
- dumpBeans(out, indent);
+ dumpObjects(out, indent);
}
}
@@ -475,7 +502,7 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
{
Object attachment = key.attachment();
if (LOG.isDebugEnabled())
- LOG.debug("selected {} {} {} ",key.readyOps(),key,attachment);
+ LOG.debug("selected {} {} {} ", safeReadyOps(key), key, attachment);
try
{
if (attachment instanceof Selectable)
@@ -491,7 +518,7 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
}
else
{
- throw new IllegalStateException("key=" + key + ", att=" + attachment + ", iOps=" + key.interestOps() + ", rOps=" + key.readyOps());
+ throw new IllegalStateException("key=" + key + ", att=" + attachment + ", iOps=" + safeInterestOps(key) + ", rOps=" + safeReadyOps(key));
}
}
catch (CancelledKeyException x)
@@ -572,19 +599,10 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
List list = new ArrayList<>(selector_keys.size());
for (SelectionKey key : selector_keys)
{
- if (key==null)
- continue;
- try
- {
- list.add(String.format("SelectionKey@%x{i=%d}->%s", key.hashCode(), key.interestOps(), key.attachment()));
- }
- catch (Throwable x)
- {
- list.add(String.format("SelectionKey@%x[%s]->%s", key.hashCode(), x, key.attachment()));
- }
+ if (key != null)
+ list.add(String.format("SelectionKey@%x{i=%d}->%s", key.hashCode(), safeInterestOps(key), key.attachment()));
}
keys = list;
-
latch.countDown();
}
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/RetainableByteBuffer.java b/jetty-io/src/main/java/org/eclipse/jetty/io/RetainableByteBuffer.java
new file mode 100644
index 00000000000..eebf5fb4d5f
--- /dev/null
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/RetainableByteBuffer.java
@@ -0,0 +1,99 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2018 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.io;
+
+import java.nio.ByteBuffer;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.util.Retainable;
+
+/**
+ * A Retainable ByteBuffer.
+ *
Acquires a ByteBuffer from a {@link ByteBufferPool} and maintains a reference count that is
+ * initially 1, incremented with {@link #retain()} and decremented with {@link #release()}. The buffer
+ * is released to the pool when the reference count is decremented to 0.
+ */
+public class RetainableByteBuffer implements Retainable
+{
+ private final ByteBufferPool pool;
+ private final ByteBuffer buffer;
+ private final AtomicInteger references;
+
+ public RetainableByteBuffer(ByteBufferPool pool, int size)
+ {
+ this(pool, size, false);
+ }
+
+ public RetainableByteBuffer(ByteBufferPool pool, int size, boolean direct)
+ {
+ this.pool = pool;
+ this.buffer = pool.acquire(size, direct);
+ this.references = new AtomicInteger(1);
+ }
+
+ public ByteBuffer getBuffer()
+ {
+ return buffer;
+ }
+
+ public int getReferences()
+ {
+ return references.get();
+ }
+
+ @Override
+ public void retain()
+ {
+ while (true)
+ {
+ int r = references.get();
+ if (r == 0)
+ throw new IllegalStateException("released " + this);
+ if (references.compareAndSet(r, r + 1))
+ break;
+ }
+ }
+
+ public int release()
+ {
+ int ref = references.decrementAndGet();
+ if (ref == 0)
+ pool.release(buffer);
+ else if (ref < 0)
+ throw new IllegalStateException("already released " + this);
+ return ref;
+ }
+
+ public boolean hasRemaining()
+ {
+ return buffer.hasRemaining();
+ }
+
+ public boolean isEmpty()
+ {
+ return !buffer.hasRemaining();
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("%s@%x{%s,r=%d}", getClass().getSimpleName(), hashCode(), BufferUtil.toDetailString(buffer), getReferences());
+ }
+}
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java
index 3b1d00c573b..47f81f633e4 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java
@@ -80,28 +80,28 @@ public class SslConnection extends AbstractConnection
{
private static final Logger LOG = Log.getLogger(SslConnection.class);
private static final String TLS_1_3 = "TLSv1.3";
-
+
private enum Handshake
{
INITIAL,
SUCCEEDED,
FAILED
}
-
- private enum FillState
+
+ private enum FillState
{
IDLE, // Not Filling any data
INTERESTED, // We have a pending read interest
WAIT_FOR_FLUSH // Waiting for a flush to happen
}
-
- private enum FlushState
- {
+
+ private enum FlushState
+ {
IDLE, // Not flushing any data
WRITING, // We have a pending write of encrypted data
WAIT_FOR_FILL // Waiting for a fill to happen
}
-
+
private final List handshakeListeners = new ArrayList<>();
private final ByteBufferPool _bufferPool;
private final SSLEngine _sslEngine;
@@ -119,20 +119,20 @@ public class SslConnection extends AbstractConnection
private FillState _fillState = FillState.IDLE;
private AtomicReference _handshake = new AtomicReference<>(Handshake.INITIAL);
private boolean _underflown;
-
- private abstract class RunnableTask implements Runnable, Invocable
+
+ private abstract class RunnableTask implements Runnable, Invocable
{
private final String _operation;
protected RunnableTask(String op)
{
- _operation=op;
+ _operation = op;
}
@Override
public String toString()
{
- return String.format("SSL:%s:%s:%s",SslConnection.this,_operation,getInvocationType());
+ return String.format("SSL:%s:%s:%s", SslConnection.this, _operation, getInvocationType());
}
}
@@ -174,7 +174,7 @@ public class SslConnection extends AbstractConnection
@Override
public String toString()
{
- return String.format("SSLC.NBReadCB@%x{%s}", SslConnection.this.hashCode(),SslConnection.this);
+ return String.format("SSLC.NBReadCB@%x{%s}", SslConnection.this.hashCode(), SslConnection.this);
}
};
@@ -233,7 +233,7 @@ public class SslConnection extends AbstractConnection
/**
* @return The number of renegotions allowed for this connection. When the limit
- * is 0 renegotiation will be denied. If the limit is less than 0 then no limit is applied.
+ * is 0 renegotiation will be denied. If the limit is less than 0 then no limit is applied.
*/
public int getRenegotiationLimit()
{
@@ -241,9 +241,9 @@ public class SslConnection extends AbstractConnection
}
/**
- * @param renegotiationLimit The number of renegotions allowed for this connection.
- * When the limit is 0 renegotiation will be denied. If the limit is less than 0 then no limit is applied.
- * Default -1.
+ * @param renegotiationLimit The number of renegotions allowed for this connection.
+ * When the limit is 0 renegotiation will be denied. If the limit is less than 0 then no limit is applied.
+ * Default -1.
*/
public void setRenegotiationLimit(int renegotiationLimit)
{
@@ -311,26 +311,26 @@ public class SslConnection extends AbstractConnection
@Override
public void onFillInterestedFailed(Throwable cause)
{
- _decryptedEndPoint.onFillableFail(cause==null?new IOException():cause);
+ _decryptedEndPoint.onFillableFail(cause == null ? new IOException() : cause);
}
@Override
public String toConnectionString()
{
ByteBuffer b = _encryptedInput;
- int ei=b==null?-1:b.remaining();
+ int ei = b == null ? -1 : b.remaining();
b = _encryptedOutput;
- int eo=b==null?-1:b.remaining();
+ int eo = b == null ? -1 : b.remaining();
b = _decryptedInput;
- int di=b==null?-1:b.remaining();
+ int di = b == null ? -1 : b.remaining();
Connection connection = _decryptedEndPoint.getConnection();
return String.format("%s@%x{%s,eio=%d/%d,di=%d,fill=%s,flush=%s}~>%s=>%s",
getClass().getSimpleName(),
hashCode(),
_sslEngine.getHandshakeStatus(),
- ei,eo,di,
- _fillState,_flushState,
+ ei, eo, di,
+ _fillState, _flushState,
_decryptedEndPoint.toEndPointString(),
connection instanceof AbstractConnection ? ((AbstractConnection)connection).toConnectionString() : connection);
}
@@ -349,7 +349,7 @@ public class SslConnection extends AbstractConnection
public class DecryptedEndPoint extends AbstractEndPoint
{
private final Callback _incompleteWriteCallback = new IncompleteWriteCallback();
-
+
public DecryptedEndPoint()
{
// Disable idle timeout checking: no scheduler and -1 timeout for this instance.
@@ -399,22 +399,22 @@ public class SslConnection extends AbstractConnection
{
// If we are handshaking, then wake up any waiting write as well as it may have been blocked on the read
boolean waiting_for_fill;
- synchronized(_decryptedEndPoint)
+ synchronized (_decryptedEndPoint)
{
if (LOG.isDebugEnabled())
LOG.debug("onFillable {}", SslConnection.this);
_fillState = FillState.IDLE;
- waiting_for_fill = _flushState==FlushState.WAIT_FOR_FILL;
+ waiting_for_fill = _flushState == FlushState.WAIT_FOR_FILL;
}
-
+
getFillInterest().fillable();
-
+
if (waiting_for_fill)
{
- synchronized(_decryptedEndPoint)
+ synchronized (_decryptedEndPoint)
{
- waiting_for_fill = _flushState==FlushState.WAIT_FOR_FILL;
+ waiting_for_fill = _flushState == FlushState.WAIT_FOR_FILL;
}
if (waiting_for_fill)
fill(BufferUtil.EMPTY_BUFFER);
@@ -430,13 +430,13 @@ public class SslConnection extends AbstractConnection
{
// If we are handshaking, then wake up any waiting write as well as it may have been blocked on the read
boolean fail = false;
- synchronized(_decryptedEndPoint)
+ synchronized (_decryptedEndPoint)
{
if (LOG.isDebugEnabled())
LOG.debug("onFillableFail {}", SslConnection.this, failure);
-
+
_fillState = FillState.IDLE;
- switch(_flushState)
+ switch (_flushState)
{
case WAIT_FOR_FILL:
_flushState = FlushState.IDLE;
@@ -444,12 +444,12 @@ public class SslConnection extends AbstractConnection
break;
default:
break;
- }
+ }
}
// wake up whoever is doing the fill
getFillInterest().onFail(failure);
-
+
// Try to complete the write
if (fail)
{
@@ -464,7 +464,7 @@ public class SslConnection extends AbstractConnection
if (connection instanceof AbstractConnection)
{
AbstractConnection a = (AbstractConnection)connection;
- if (a.getInputBufferSize()<_sslEngine.getSession().getApplicationBufferSize())
+ if (a.getInputBufferSize() < _sslEngine.getSession().getApplicationBufferSize())
a.setInputBufferSize(_sslEngine.getSession().getApplicationBufferSize());
}
super.setConnection(connection);
@@ -480,7 +480,7 @@ public class SslConnection extends AbstractConnection
{
try
{
- synchronized(_decryptedEndPoint)
+ synchronized (_decryptedEndPoint)
{
if (LOG.isDebugEnabled())
LOG.debug(">fill {}", SslConnection.this);
@@ -488,20 +488,20 @@ public class SslConnection extends AbstractConnection
int filled = -2;
try
{
- if (_fillState!=FillState.IDLE)
+ if (_fillState != FillState.IDLE)
return filled = 0;
-
+
// Do we already have some decrypted data?
if (BufferUtil.hasContent(_decryptedInput))
- return filled = BufferUtil.append(buffer,_decryptedInput);
-
+ return filled = BufferUtil.append(buffer, _decryptedInput);
+
// loop filling and unwrapping until we have something
while (true)
{
HandshakeStatus status = _sslEngine.getHandshakeStatus();
if (LOG.isDebugEnabled())
LOG.debug("fill {}", status);
- switch(status)
+ switch (status)
{
case NEED_UNWRAP:
case NOT_HANDSHAKING:
@@ -510,20 +510,25 @@ public class SslConnection extends AbstractConnection
case NEED_TASK:
_sslEngine.getDelegatedTask().run();
continue;
-
+
case NEED_WRAP:
- if (_flushState==FlushState.IDLE && flush(BufferUtil.EMPTY_BUFFER))
+ if (_flushState == FlushState.IDLE && flush(BufferUtil.EMPTY_BUFFER))
+ {
+ if (_sslEngine.isInboundDone())
+ // TODO this is probably a JVM bug, work around it by -1
+ return -1;
continue;
+ }
// handle in needsFillInterest
return filled = 0;
-
+
default:
throw new IllegalStateException("Unexpected HandshakeStatus " + status);
}
-
- if (_encryptedInput==null)
+
+ if (_encryptedInput == null)
_encryptedInput = _bufferPool.acquire(_sslEngine.getSession().getPacketBufferSize(), _encryptedDirectBuffers);
-
+
// can we use the passed buffer if it is big enough
ByteBuffer app_in;
if (_decryptedInput == null)
@@ -538,7 +543,7 @@ public class SslConnection extends AbstractConnection
app_in = _decryptedInput;
BufferUtil.compact(_encryptedInput);
}
-
+
// Let's try reading some encrypted data... even if we have some already.
int net_filled = getEndPoint().fill(_encryptedInput);
@@ -561,26 +566,26 @@ public class SslConnection extends AbstractConnection
{
BufferUtil.flipToFlush(app_in, pos);
}
-
if (LOG.isDebugEnabled())
- LOG.debug("unwrap {} {} unwrapBuffer={} appBuffer={}",
- net_filled,
- unwrapResult.toString().replace('\n',' '),
- BufferUtil.toDetailString(app_in),
- BufferUtil.toDetailString(buffer));
+ LOG.debug("unwrap net_filled={} {} encryptedBuffer={} unwrapBuffer={} appBuffer={}",
+ net_filled,
+ unwrapResult.toString().replace('\n', ' '),
+ BufferUtil.toSummaryString(_encryptedInput),
+ BufferUtil.toDetailString(app_in),
+ BufferUtil.toDetailString(buffer));
SSLEngineResult.Status unwrap = unwrapResult.getStatus();
// Extra check on unwrapResultStatus == OK with zero bytes consumed
// or produced is due to an SSL client on Android (see bug #454773).
- if (unwrap==Status.OK && unwrapResult.bytesConsumed() == 0 && unwrapResult.bytesProduced() == 0)
+ if (unwrap == Status.OK && unwrapResult.bytesConsumed() == 0 && unwrapResult.bytesProduced() == 0)
unwrap = Status.BUFFER_UNDERFLOW;
-
+
switch (unwrap)
{
case CLOSED:
return filled = -1;
-
+
case BUFFER_UNDERFLOW:
if (net_filled > 0)
continue; // try filling some more
@@ -596,7 +601,7 @@ public class SslConnection extends AbstractConnection
{
if (unwrapResult.getHandshakeStatus() == HandshakeStatus.FINISHED)
handshakeSucceeded();
-
+
if (isRenegotiating() && !allowRenegotiate())
return filled = -1;
@@ -605,14 +610,14 @@ public class SslConnection extends AbstractConnection
// another call to fill() or flush().
if (unwrapResult.bytesProduced() > 0)
{
- if (app_in==buffer)
+ if (app_in == buffer)
return filled = unwrapResult.bytesProduced();
- return filled = BufferUtil.append(buffer,_decryptedInput);
+ return filled = BufferUtil.append(buffer, _decryptedInput);
}
-
+
break;
}
-
+
default:
throw new IllegalStateException("Unexpected unwrap result " + unwrap);
}
@@ -622,10 +627,10 @@ public class SslConnection extends AbstractConnection
{
handshakeFailed(x);
- if (_flushState==FlushState.WAIT_FOR_FILL)
+ if (_flushState == FlushState.WAIT_FOR_FILL)
{
- _flushState=FlushState.IDLE;
- getExecutor().execute(()->_decryptedEndPoint.getWriteFlusher().onFail(x));
+ _flushState = FlushState.IDLE;
+ getExecutor().execute(() -> _decryptedEndPoint.getWriteFlusher().onFail(x));
}
throw x;
@@ -637,19 +642,19 @@ public class SslConnection extends AbstractConnection
_bufferPool.release(_encryptedInput);
_encryptedInput = null;
}
-
+
if (_decryptedInput != null && !_decryptedInput.hasRemaining())
{
_bufferPool.release(_decryptedInput);
_decryptedInput = null;
}
- if (_flushState==FlushState.WAIT_FOR_FILL)
+ if (_flushState == FlushState.WAIT_FOR_FILL)
{
- _flushState=FlushState.IDLE;
- getExecutor().execute(()->_decryptedEndPoint.getWriteFlusher().completeWrite());
+ _flushState = FlushState.IDLE;
+ getExecutor().execute(() -> _decryptedEndPoint.getWriteFlusher().completeWrite());
}
-
+
if (LOG.isDebugEnabled())
LOG.debug("needFillInterest uf={} {}", _underflown, SslConnection.this);
- LOG.debug("ei={} di={}",BufferUtil.toDetailString(_encryptedInput),BufferUtil.toDetailString(_decryptedInput));
+ LOG.debug("ei={} di={}", BufferUtil.toDetailString(_encryptedInput), BufferUtil.toDetailString(_decryptedInput));
}
- if (_fillState!=FillState.IDLE)
+ if (_fillState != FillState.IDLE)
return;
// Fillable if we have decrypted Input OR encrypted input that has not yet been underflown.
@@ -720,10 +725,10 @@ public class SslConnection extends AbstractConnection
}
if (LOG.isDebugEnabled())
- LOG.debug("0)
+ if (_renegotiationLimit > 0)
_renegotiationLimit--;
}
}
@@ -799,18 +804,18 @@ public class SslConnection extends AbstractConnection
LOG.ignore(x);
}
}
-
+
@Override
public boolean flush(ByteBuffer... appOuts) throws IOException
{
try
{
- synchronized(_decryptedEndPoint)
+ synchronized (_decryptedEndPoint)
{
if (LOG.isDebugEnabled())
{
LOG.debug(">flush {}", SslConnection.this);
- int i=0;
+ int i = 0;
for (ByteBuffer b : appOuts)
LOG.debug("flush b[{}]={}", i++, BufferUtil.toDetailString(b));
}
@@ -818,7 +823,7 @@ public class SslConnection extends AbstractConnection
Boolean result = null;
try
{
- if (_flushState!=FlushState.IDLE)
+ if (_flushState != FlushState.IDLE)
return result = false;
// Keep going while we can make progress or until we are done
@@ -826,8 +831,8 @@ public class SslConnection extends AbstractConnection
{
HandshakeStatus status = _sslEngine.getHandshakeStatus();
if (LOG.isDebugEnabled())
- LOG.debug("flush {}",status);
- switch(status)
+ LOG.debug("flush {}", status);
+ switch (status)
{
case NEED_WRAP:
case NOT_HANDSHAKING:
@@ -836,18 +841,18 @@ public class SslConnection extends AbstractConnection
case NEED_TASK:
_sslEngine.getDelegatedTask().run();
continue;
-
+
case NEED_UNWRAP:
- if (_fillState==FillState.IDLE)
+ if (_fillState == FillState.IDLE)
{
int filled = fill(BufferUtil.EMPTY_BUFFER);
- if (_sslEngine.getHandshakeStatus()!=status)
+ if (_sslEngine.getHandshakeStatus() != status)
continue;
if (filled < 0)
throw new IOException("Broken pipe");
}
return result = false;
-
+
default:
throw new IllegalStateException("Unexpected HandshakeStatus " + status);
}
@@ -862,19 +867,23 @@ public class SslConnection extends AbstractConnection
try
{
wrapResult = _sslEngine.wrap(appOuts, _encryptedOutput);
- if (LOG.isDebugEnabled())
- LOG.debug("wrap {} {}", wrapResult.toString().replace('\n',' '), BufferUtil.toHexSummary(_encryptedOutput));
}
finally
{
BufferUtil.flipToFlush(_encryptedOutput, pos);
}
-
+ if (LOG.isDebugEnabled())
+ LOG.debug("wrap {} {} ioDone={}/{}",
+ wrapResult.toString().replace('\n', ' '),
+ BufferUtil.toSummaryString(_encryptedOutput),
+ _sslEngine.isInboundDone(),
+ _sslEngine.isOutboundDone());
+
// Was all the data consumed?
- boolean allConsumed=true;
+ boolean allConsumed = true;
for (ByteBuffer b : appOuts)
if (BufferUtil.hasContent(b))
- allConsumed=false;
+ allConsumed = false;
// if we have net bytes, let's try to flush them
boolean flushed = true;
@@ -899,12 +908,12 @@ public class SslConnection extends AbstractConnection
return result = true;
throw new IOException("Broken pipe");
}
-
+
case BUFFER_OVERFLOW:
if (!flushed)
return result = false;
continue;
-
+
case OK:
if (wrapResult.getHandshakeStatus() == HandshakeStatus.FINISHED)
handshakeSucceeded();
@@ -960,24 +969,24 @@ public class SslConnection extends AbstractConnection
{
boolean fillInterest = false;
ByteBuffer write = null;
- synchronized(_decryptedEndPoint)
+ synchronized (_decryptedEndPoint)
{
if (LOG.isDebugEnabled())
LOG.debug(">onIncompleteFlush {} {}", SslConnection.this, BufferUtil.toDetailString(_encryptedOutput));
- if (_flushState!=FlushState.IDLE)
+ if (_flushState != FlushState.IDLE)
return;
- while(true)
+ while (true)
{
HandshakeStatus status = _sslEngine.getHandshakeStatus();
- switch(status)
+ switch (status)
{
case NEED_TASK:
case NEED_WRAP:
case NOT_HANDSHAKING:
// write what we have or an empty buffer to reschedule a call to flush
- write = BufferUtil.hasContent(_encryptedOutput)?_encryptedOutput:BufferUtil.EMPTY_BUFFER;
+ write = BufferUtil.hasContent(_encryptedOutput) ? _encryptedOutput : BufferUtil.EMPTY_BUFFER;
_flushState = FlushState.WRITING;
break;
@@ -990,7 +999,7 @@ public class SslConnection extends AbstractConnection
break;
}
- if (_fillState!=FillState.IDLE)
+ if (_fillState != FillState.IDLE)
{
// Wait for a fill that is happening anyway
_flushState = FlushState.WAIT_FOR_FILL;
@@ -1002,12 +1011,12 @@ public class SslConnection extends AbstractConnection
{
int filled = fill(BufferUtil.EMPTY_BUFFER);
// If this changed the status, let's try again
- if (_sslEngine.getHandshakeStatus()!=status)
+ if (_sslEngine.getHandshakeStatus() != status)
continue;
if (filled < 0)
throw new IOException("Broken pipe");
}
- catch(IOException e)
+ catch (IOException e)
{
LOG.debug(e);
close(e);
@@ -1032,7 +1041,7 @@ public class SslConnection extends AbstractConnection
LOG.debug("
+
+ getExecutor().execute(() ->
{
if (fail_fill_interest)
_decryptedEndPoint.getFillInterest().onFail(x);
_decryptedEndPoint.getWriteFlusher().onFail(x);
});
}
-
+
@Override
public InvocationType getInvocationType()
{
return _decryptedEndPoint.getWriteFlusher().getCallbackInvocationType();
}
-
+
@Override
public String toString()
{
- return String.format("SSL@%h.DEP.writeCallback",SslConnection.this);
+ return String.format("SSL@%h.DEP.writeCallback", SslConnection.this);
}
}
}
diff --git a/jetty-jaas/pom.xml b/jetty-jaas/pom.xml
index 3db46da6f25..30a9da16a34 100644
--- a/jetty-jaas/pom.xml
+++ b/jetty-jaas/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-jaas
diff --git a/jetty-jaspi/pom.xml b/jetty-jaspi/pom.xml
index c536a7709d6..b6616053a9d 100644
--- a/jetty-jaspi/pom.xml
+++ b/jetty-jaspi/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-jmh/pom.xml b/jetty-jmh/pom.xml
index 2e4b9719221..6b6ac794d08 100644
--- a/jetty-jmh/pom.xml
+++ b/jetty-jmh/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-jmh
diff --git a/jetty-jmx/pom.xml b/jetty-jmx/pom.xml
index f7722c06714..d3314526957 100644
--- a/jetty-jmx/pom.xml
+++ b/jetty-jmx/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-jmx
diff --git a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java
index c63b9446d4c..ec1970fba71 100644
--- a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java
+++ b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java
@@ -217,12 +217,15 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable, De
private static Constructor> findConstructor(Class> klass)
{
- String pName = klass.getPackage().getName();
- String cName = klass.getName().substring(pName.length() + 1);
+ Package pkg = klass.getPackage();
+ if (pkg == null)
+ return null;
+ String pName = pkg.getName();
+ String cName = klass.getName().substring(pName.isEmpty() ? 0 : pName.length() + 1);
String mName = pName + ".jmx." + cName + "MBean";
try
{
- Class> mbeanClass = Loader.loadClass(mName);
+ Class> mbeanClass = Loader.loadClass(klass, mName);
Constructor> constructor = ModelMBean.class.isAssignableFrom(mbeanClass)
? mbeanClass.getConstructor()
: mbeanClass.getConstructor(Object.class);
@@ -310,12 +313,19 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable, De
// No override of the mbean's ObjectName, so make a generic one.
if (objectName == null)
{
+ Class> klass = obj.getClass();
+ while (klass.isArray())
+ klass = klass.getComponentType();
+
// If no explicit domain, create one.
String domain = _domain;
if (domain == null)
- domain = obj.getClass().getPackage().getName();
+ {
+ Package pkg = klass.getPackage();
+ domain = pkg == null ? "" : pkg.getName();
+ }
- String type = obj.getClass().getName().toLowerCase(Locale.ENGLISH);
+ String type = klass.getName().toLowerCase(Locale.ENGLISH);
int dot = type.lastIndexOf('.');
if (dot >= 0)
type = type.substring(dot + 1);
diff --git a/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanTest.java b/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanTest.java
index 00b6b81b952..f6db43ad89b 100644
--- a/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanTest.java
+++ b/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanTest.java
@@ -24,6 +24,7 @@ import javax.management.Attribute;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
+import javax.management.ObjectName;
import com.acme.Derived;
import com.acme.Managed;
@@ -34,6 +35,7 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -54,6 +56,46 @@ public class ObjectMBeanTest
container = null;
}
+ @Test
+ public void testMBeanForNull()
+ {
+ Object mBean = container.mbeanFor(null);
+ assertNull(mBean);
+ }
+
+ @Test
+ public void testMBeanForString()
+ {
+ String obj = "foo";
+ Object mbean = container.mbeanFor(obj);
+ assertNotNull(mbean);
+ container.beanAdded(null, obj);
+ ObjectName objectName = container.findMBean(obj);
+ assertNotNull(objectName);
+ }
+
+ @Test
+ public void testMBeanForStringArray()
+ {
+ String[] obj = {"a", "b"};
+ Object mbean = container.mbeanFor(obj);
+ assertNotNull(mbean);
+ container.beanAdded(null, obj);
+ ObjectName objectName = container.findMBean(obj);
+ assertNotNull(objectName);
+ }
+
+ @Test
+ public void testMBeanForIntArray()
+ {
+ int[] obj = {0, 1, 2};
+ Object mbean = container.mbeanFor(obj);
+ assertNotNull(mbean);
+ container.beanAdded(null, obj);
+ ObjectName objectName = container.findMBean(obj);
+ assertNotNull(objectName);
+ }
+
@Test
public void testMetaDataCaching()
{
diff --git a/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanUtilTest.java b/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanUtilTest.java
index 0f1321bbbfe..054f11eea33 100644
--- a/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanUtilTest.java
+++ b/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ObjectMBeanUtilTest.java
@@ -70,13 +70,6 @@ public class ObjectMBeanUtilTest
assertEquals("Test the mbean extended stuff", objectMBeanInfo.getDescription(), "Mbean description must be equal to : Test the mbean extended stuff");
}
- @Test
- public void testMbeanForNullCheck()
- {
- Object mBean = container.mbeanFor(null);
- assertNull(mBean, "As we are passing null value the output should be null");
- }
-
@Test
public void testGetAttributeMBeanException() throws Exception
{
@@ -151,7 +144,7 @@ public class ObjectMBeanUtilTest
}
@Test
- public void testSetAttributesForCollectionTypeAttribue() throws Exception
+ public void testSetAttributesForCollectionTypeAttribute() throws Exception
{
ArrayList aliasNames = new ArrayList<>(Arrays.asList(getArrayTypeAttribute()));
@@ -231,7 +224,7 @@ public class ObjectMBeanUtilTest
ReflectionException e = assertThrows(ReflectionException.class, () ->
objectMBean.invoke("good", new Object[0], new String[]{"int aone"}));
- assertNotNull(e, "An ReflectionException must have occurred by now as we cannot call a methow with wrong signature");
+ assertNotNull(e, "A ReflectionException must have occurred by now as we cannot call a method with wrong signature");
}
@Test
diff --git a/jetty-jndi/pom.xml b/jetty-jndi/pom.xml
index 4e6d764aa8a..f36f315c200 100644
--- a/jetty-jndi/pom.xml
+++ b/jetty-jndi/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-jndi
diff --git a/jetty-jspc-maven-plugin/pom.xml b/jetty-jspc-maven-plugin/pom.xml
index cd2eeb1b88d..e95566fddf4 100644
--- a/jetty-jspc-maven-plugin/pom.xml
+++ b/jetty-jspc-maven-plugin/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-jspc-maven-plugin
diff --git a/jetty-maven-plugin/pom.xml b/jetty-maven-plugin/pom.xml
index d631db23eb0..49644e908e8 100644
--- a/jetty-maven-plugin/pom.xml
+++ b/jetty-maven-plugin/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-maven-plugin
diff --git a/jetty-memcached/jetty-memcached-sessions/pom.xml b/jetty-memcached/jetty-memcached-sessions/pom.xml
index f76ba891883..5f63eb6b90d 100644
--- a/jetty-memcached/jetty-memcached-sessions/pom.xml
+++ b/jetty-memcached/jetty-memcached-sessions/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jetty.memcachedmemcached-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-memcached/pom.xml b/jetty-memcached/pom.xml
index 203343bfd97..55a9f5ec50b 100644
--- a/jetty-memcached/pom.xml
+++ b/jetty-memcached/pom.xml
@@ -3,7 +3,7 @@
jetty-projectorg.eclipse.jetty
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-nosql/pom.xml b/jetty-nosql/pom.xml
index ed0000fcbde..1a476959c56 100644
--- a/jetty-nosql/pom.xml
+++ b/jetty-nosql/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-nosql
diff --git a/jetty-osgi/jetty-osgi-alpn/pom.xml b/jetty-osgi/jetty-osgi-alpn/pom.xml
index 1fe2b2000b5..09d1b44cbf7 100644
--- a/jetty-osgi/jetty-osgi-alpn/pom.xml
+++ b/jetty-osgi/jetty-osgi-alpn/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jetty.osgijetty-osgi-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-osgi-alpn
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
index eb424f2d69d..80f0defe600 100644
--- a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jetty.osgijetty-osgi-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-osgi-boot-jsp
diff --git a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
index 3421edc642b..9e632b6d736 100644
--- a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jetty.osgijetty-osgi-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT../pom.xml4.0.0
diff --git a/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty.xml b/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty.xml
index f47a40a2bc4..fe4fc1d1ab3 100644
--- a/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty.xml
+++ b/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty.xml
@@ -40,7 +40,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- true
- 1000
- false
- false
-
+
+
+
+
diff --git a/jetty-osgi/jetty-osgi-boot/pom.xml b/jetty-osgi/jetty-osgi-boot/pom.xml
index bf52d3592a9..0628aca8cab 100644
--- a/jetty-osgi/jetty-osgi-boot/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jetty.osgijetty-osgi-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-osgi-boot
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java
index ef85bd9e23a..00f0919a023 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java
@@ -49,7 +49,7 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
public AnnotationParser(int javaPlatform)
{
- super(javaPlatform, Opcodes.ASM5);
+ super(javaPlatform, Opcodes.ASM7);
}
/**
diff --git a/jetty-osgi/jetty-osgi-httpservice/pom.xml b/jetty-osgi/jetty-osgi-httpservice/pom.xml
index 332d259616c..269d83bde45 100644
--- a/jetty-osgi/jetty-osgi-httpservice/pom.xml
+++ b/jetty-osgi/jetty-osgi-httpservice/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jetty.osgijetty-osgi-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-httpservice
diff --git a/jetty-osgi/pom.xml b/jetty-osgi/pom.xml
index 503b4cba7e3..517b5ac01cf 100644
--- a/jetty-osgi/pom.xml
+++ b/jetty-osgi/pom.xml
@@ -4,7 +4,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
@@ -15,7 +15,6 @@
pom
- 6.23.6.0.v201005173.2.100.v201005031.0.0-v20070606
diff --git a/jetty-osgi/test-jetty-osgi-context/pom.xml b/jetty-osgi/test-jetty-osgi-context/pom.xml
index 69146e5f38a..e6cfcb2abb5 100644
--- a/jetty-osgi/test-jetty-osgi-context/pom.xml
+++ b/jetty-osgi/test-jetty-osgi-context/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jetty.osgijetty-osgi-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0test-jetty-osgi-context
diff --git a/jetty-osgi/test-jetty-osgi-fragment/pom.xml b/jetty-osgi/test-jetty-osgi-fragment/pom.xml
index 19e44564f78..bd9574bf85e 100644
--- a/jetty-osgi/test-jetty-osgi-fragment/pom.xml
+++ b/jetty-osgi/test-jetty-osgi-fragment/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jetty.osgijetty-osgi-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT../pom.xml4.0.0
diff --git a/jetty-osgi/test-jetty-osgi-server/pom.xml b/jetty-osgi/test-jetty-osgi-server/pom.xml
index 57f376a32a1..53c0a524388 100644
--- a/jetty-osgi/test-jetty-osgi-server/pom.xml
+++ b/jetty-osgi/test-jetty-osgi-server/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jetty.osgijetty-osgi-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0test-jetty-osgi-server
@@ -15,7 +15,7 @@
org.eclipse.jetty
- jetty-server
+ jetty-webapp${project.version}
diff --git a/jetty-osgi/test-jetty-osgi-server/src/main/java/com/acme/osgi/Activator.java b/jetty-osgi/test-jetty-osgi-server/src/main/java/com/acme/osgi/Activator.java
index a45f567d57d..89288615b63 100644
--- a/jetty-osgi/test-jetty-osgi-server/src/main/java/com/acme/osgi/Activator.java
+++ b/jetty-osgi/test-jetty-osgi-server/src/main/java/com/acme/osgi/Activator.java
@@ -23,6 +23,7 @@ import java.util.Hashtable;
import org.eclipse.jetty.util.component.AbstractLifeCycle.AbstractLifeCycleListener;
import org.eclipse.jetty.util.component.LifeCycle;
+import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
@@ -67,6 +68,16 @@ public class Activator implements BundleActivator
});
ContextHandlerCollection contexts = new ContextHandlerCollection();
server.setHandler(contexts);
+ //server.setDumpAfterStart(true);
+
+ Configuration.ClassList list = new Configuration.ClassList(new String[] {"org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration",
+ "org.eclipse.jetty.webapp.WebXmlConfiguration",
+ "org.eclipse.jetty.webapp.MetaInfConfiguration",
+ "org.eclipse.jetty.webapp.FragmentConfiguration",
+ "org.eclipse.jetty.webapp.JettyWebXmlConfiguration"});
+ server.addBean(list);
+ server.setAttribute("org.eclipse.jetty.webapp.configuration", list);
+ list.setServerDefault(server);
Dictionary serverProps = new Hashtable();
//define the unique name of the server instance
diff --git a/jetty-osgi/test-jetty-osgi-webapp/pom.xml b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
index 8eb88115390..fa18b7c52de 100644
--- a/jetty-osgi/test-jetty-osgi-webapp/pom.xml
+++ b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jetty.osgijetty-osgi-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT../pom.xml4.0.0
diff --git a/jetty-osgi/test-jetty-osgi/pom.xml b/jetty-osgi/test-jetty-osgi/pom.xml
index 40340aa2fbb..408a154ea33 100644
--- a/jetty-osgi/test-jetty-osgi/pom.xml
+++ b/jetty-osgi/test-jetty-osgi/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jetty.osgijetty-osgi-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT../pom.xml4.0.0
@@ -78,13 +78,13 @@
org.eclipse.platformorg.eclipse.osgi
- 3.12.50
+ 3.13.100testorg.eclipse.platformorg.eclipse.osgi.services
- 3.6.0
+ 3.7.100test
@@ -148,7 +148,23 @@
org.apache.aries.spiflyorg.apache.aries.spifly.dynamic.bundle
- 1.0.10
+ 1.1
+ test
+
+
+ org.apache.felix
+ org.apache.felix.framework
+
+
+ org.ow2.asm
+ asm-util
+
+
+
+
+ com.sun.activation
+ javax.activation
+ 1.2.0test
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml
index f47a40a2bc4..43e978db7f0 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml
@@ -41,25 +41,34 @@
-
- https
-
- 32768
- 8192
- 8192
- true
- false
- 4096
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- true
- 1000
- false
- false
+
+
+
+
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 ba2b2b2326d..56083be7bb6 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
@@ -101,8 +101,8 @@ public class TestJettyOSGiBootWebAppAsService
@Test
public void assertAllBundlesActiveOrResolved()
{
- //TestOSGiUtil.assertAllBundlesActiveOrResolved(bundleContext);
TestOSGiUtil.debugBundles(bundleContext);
+ TestOSGiUtil.assertAllBundlesActiveOrResolved(bundleContext);
}
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootWithAnnotations.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootWithAnnotations.java
index 358baeab33f..c8e5a57f1a1 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootWithAnnotations.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootWithAnnotations.java
@@ -85,6 +85,7 @@ public class TestJettyOSGiBootWithAnnotations
public static List
diff --git a/jetty-server/src/main/config/modules/server.mod b/jetty-server/src/main/config/modules/server.mod
index 2bd4718fd0d..038f1836b65 100644
--- a/jetty-server/src/main/config/modules/server.mod
+++ b/jetty-server/src/main/config/modules/server.mod
@@ -62,8 +62,11 @@ patch-module: servlet.api=lib/jetty-schemas-3.1.jar
## Maximum number of error dispatches to prevent looping
# jetty.httpConfig.maxErrorDispatches=10
-## Cookie compliance mode of: RFC2965, RFC6265
-# jetty.httpConfig.cookieCompliance=RFC6265
+## Cookie compliance mode for parsing request Cookie headers: RFC2965, RFC6265
+# jetty.httpConfig.requestCookieCompliance=RFC6265
+
+## Cookie compliance mode for generating response Set-Cookie: RFC2965, RFC6265
+# jetty.httpConfig.responseCookieCompliance=RFC6265
## multipart/form-data compliance mode of: LEGACY(slow), RFC7578(fast)
# jetty.httpConfig.multiPartFormDataCompliance=LEGACY
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java
index 623a97b8ffd..4d9537ad024 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java
@@ -31,6 +31,8 @@ import org.eclipse.jetty.util.TreeTrie;
import org.eclipse.jetty.util.Trie;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
+import org.eclipse.jetty.util.component.Dumpable;
+import org.eclipse.jetty.util.component.DumpableCollection;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -46,7 +48,7 @@ import org.eclipse.jetty.util.log.Logger;
*
*/
@ManagedObject("HTTP Configuration")
-public class HttpConfiguration
+public class HttpConfiguration implements Dumpable
{
private static final Logger LOG = Log.getLogger(HttpConfiguration.class);
@@ -70,7 +72,8 @@ public class HttpConfiguration
private int _maxErrorDispatches = 10;
private long _minRequestDataRate;
private long _minResponseDataRate;
- private CookieCompliance _cookieCompliance = CookieCompliance.RFC6265;
+ private CookieCompliance _requestCookieCompliance = CookieCompliance.RFC6265;
+ private CookieCompliance _responseCookieCompliance = CookieCompliance.RFC6265;
private MultiPartFormDataCompliance _multiPartCompliance = MultiPartFormDataCompliance.LEGACY; // TODO change default in jetty-10
private boolean _notifyRemoteAsyncErrors = true;
@@ -133,7 +136,8 @@ public class HttpConfiguration
_maxErrorDispatches=config._maxErrorDispatches;
_minRequestDataRate=config._minRequestDataRate;
_minResponseDataRate=config._minResponseDataRate;
- _cookieCompliance=config._cookieCompliance;
+ _requestCookieCompliance =config._requestCookieCompliance;
+ _responseCookieCompliance =config._responseCookieCompliance;
_notifyRemoteAsyncErrors=config._notifyRemoteAsyncErrors;
}
@@ -531,19 +535,58 @@ public class HttpConfiguration
_minResponseDataRate = bytesPerSecond;
}
- public CookieCompliance getCookieCompliance()
+ /**
+ * @see #getResponseCookieCompliance()
+ * @return The CookieCompliance used for parsing request Cookie headers.
+ */
+ public CookieCompliance getRequestCookieCompliance()
{
- return _cookieCompliance;
- }
-
- public void setCookieCompliance(CookieCompliance cookieCompliance)
- {
- _cookieCompliance = cookieCompliance==null?CookieCompliance.RFC6265:cookieCompliance;
+ return _requestCookieCompliance;
}
+ /**
+ * @see #getRequestCookieCompliance()
+ * @return The CookieCompliance used for generating response Set-Cookie headers
+ */
+ public CookieCompliance getResponseCookieCompliance()
+ {
+ return _responseCookieCompliance;
+ }
+
+ /**
+ * @see #setRequestCookieCompliance(CookieCompliance)
+ * @param cookieCompliance The CookieCompliance to use for parsing request Cookie headers.
+ */
+ public void setRequestCookieCompliance(CookieCompliance cookieCompliance)
+ {
+ _requestCookieCompliance = cookieCompliance==null?CookieCompliance.RFC6265:cookieCompliance;
+ }
+
+ /**
+ * @see #setResponseCookieCompliance(CookieCompliance)
+ * @param cookieCompliance The CookieCompliance to use for generating response Set-Cookie headers
+ */
+ public void setResponseCookieCompliance(CookieCompliance cookieCompliance)
+ {
+ _responseCookieCompliance = cookieCompliance==null?CookieCompliance.RFC6265:cookieCompliance;
+ }
+
+ @Deprecated
+ public void setCookieCompliance(CookieCompliance compliance)
+ {
+ setRequestCookieCompliance(compliance);
+ }
+
+ @Deprecated
+ public CookieCompliance getCookieCompliance()
+ {
+ return getRequestCookieCompliance();
+ }
+
+ @Deprecated
public boolean isCookieCompliance(CookieCompliance compliance)
{
- return _cookieCompliance.equals(compliance);
+ return _requestCookieCompliance.equals(compliance);
}
/**
@@ -579,15 +622,51 @@ public class HttpConfiguration
return _notifyRemoteAsyncErrors;
}
+ @Override public String dump()
+ {
+ return Dumpable.dump(this);
+ }
+
+ @Override public void dump(Appendable out, String indent) throws IOException
+ {
+ Dumpable.dumpObjects(out,indent,this,
+ new DumpableCollection("customizers",_customizers),
+ new DumpableCollection("formEncodedMethods",_formEncodedMethods.keySet()),
+ "outputBufferSize=" + _outputBufferSize,
+ "outputAggregationSize=" + _outputAggregationSize,
+ "requestHeaderSize=" + _requestHeaderSize,
+ "responseHeaderSize=" + _responseHeaderSize,
+ "headerCacheSize=" + _headerCacheSize,
+ "secureScheme=" + _secureScheme,
+ "securePort=" + _securePort,
+ "idleTimeout=" + _idleTimeout,
+ "blockingTimeout=" + _blockingTimeout,
+ "sendDateHeader=" + _sendDateHeader,
+ "sendServerVersion=" + _sendServerVersion,
+ "sendXPoweredBy=" + _sendXPoweredBy,
+ "delayDispatchUntilContent=" + _delayDispatchUntilContent,
+ "persistentConnectionsEnabled=" + _persistentConnectionsEnabled,
+ "maxErrorDispatches=" + _maxErrorDispatches,
+ "minRequestDataRate=" + _minRequestDataRate,
+ "minResponseDataRate=" + _minResponseDataRate,
+ "cookieCompliance=" + _requestCookieCompliance,
+ "setRequestCookieCompliance=" + _responseCookieCompliance,
+ "notifyRemoteAsyncErrors=" + _notifyRemoteAsyncErrors
+ );
+ }
+
@Override
public String toString()
{
return String.format("%s@%x{%d/%d,%d/%d,%s://:%d,%s}",
- this.getClass().getSimpleName(),
- hashCode(),
- _outputBufferSize, _outputAggregationSize,
- _requestHeaderSize,_responseHeaderSize,
- _secureScheme,_securePort,
- _customizers);
+ this.getClass().getSimpleName(),
+ hashCode(),
+ _outputBufferSize,
+ _outputAggregationSize,
+ _requestHeaderSize,
+ _responseHeaderSize,
+ _secureScheme,
+ _securePort,
+ _customizers);
}
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java
index 6eaa6c04e07..97583b4d33d 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java
@@ -263,14 +263,26 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
if (suspended || getEndPoint().getConnection() != this)
break;
}
- else
+ else if (filled==0)
{
- if (filled <= 0)
+ fillInterested();
+ break;
+ }
+ else if (filled<0)
+ {
+ switch(_channel.getState().getState())
{
- if (filled == 0)
- fillInterested();
- break;
+ case COMPLETING:
+ case COMPLETED:
+ case IDLE:
+ case THROWN:
+ case ASYNC_ERROR:
+ getEndPoint().shutdownOutput();
+ break;
+ default:
+ break;
}
+ break;
}
}
}
@@ -310,16 +322,6 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
if (BufferUtil.isEmpty(_requestBuffer))
{
- // Can we fill?
- if(getEndPoint().isInputShutdown())
- {
- // No pretend we read -1
- _parser.atEOF();
- if (LOG.isDebugEnabled())
- LOG.debug("{} filled -1 {}",this,BufferUtil.toDetailString(_requestBuffer));
- return -1;
- }
-
// Get a buffer
// We are not in a race here for the request buffer as we have not yet received a request,
// so there are not an possible legal threads calling #parseContent or #completed.
@@ -411,13 +413,13 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
if (_input.isAsync())
{
if (LOG.isDebugEnabled())
- LOG.debug("unconsumed async input {}", this);
+ LOG.debug("{}unconsumed input {}",_parser.isChunking()?"Possible ":"", this);
_channel.abort(new IOException("unconsumed input"));
}
else
{
if (LOG.isDebugEnabled())
- LOG.debug("unconsumed input {}", this);
+ LOG.debug("{}unconsumed input {}",_parser.isChunking()?"Possible ":"", this);
// Complete reading the request
if (!_input.consumeAll())
_channel.abort(new IOException("unconsumed input"));
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
index b13d1cc0c16..d29d0431d54 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
@@ -770,7 +770,7 @@ public class Request implements HttpServletRequest
if (field.getHeader()==HttpHeader.COOKIE)
{
if (_cookies==null)
- _cookies = new CookieCutter(getHttpChannel().getHttpConfiguration().getCookieCompliance());
+ _cookies = new CookieCutter(getHttpChannel().getHttpConfiguration().getRequestCookieCompliance());
_cookies.addCookieField(field.getValue());
}
}
@@ -2057,7 +2057,7 @@ public class Request implements HttpServletRequest
public void setCookies(Cookie[] cookies)
{
if (_cookies == null)
- _cookies = new CookieCutter(getHttpChannel().getHttpConfiguration().getCookieCompliance());
+ _cookies = new CookieCutter(getHttpChannel().getHttpConfiguration().getRequestCookieCompliance());
_cookies.setCookies(cookies);
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java
index 43876ea13e7..3741ee1b256 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java
@@ -172,7 +172,7 @@ public class Response implements HttpServletResponse
throw new IllegalArgumentException("Cookie.name cannot be blank/null");
}
- if (getHttpChannel().getHttpConfiguration().isCookieCompliance(CookieCompliance.RFC2965))
+ if (getHttpChannel().getHttpConfiguration().getResponseCookieCompliance()==CookieCompliance.RFC2965)
addSetRFC2965Cookie(
cookie.getName(),
cookie.getValue(),
@@ -217,7 +217,7 @@ public class Response implements HttpServletResponse
throw new IllegalArgumentException("Cookie.name cannot be blank/null");
}
- if (getHttpChannel().getHttpConfiguration().isCookieCompliance(CookieCompliance.RFC2965))
+ if (getHttpChannel().getHttpConfiguration().getResponseCookieCompliance()==CookieCompliance.RFC2965)
addSetRFC2965Cookie(cookie.getName(),
cookie.getValue(),
cookie.getDomain(),
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
index cc7f6312a98..aff082efd6e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
@@ -24,7 +24,6 @@ import java.net.InetSocketAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -691,7 +690,7 @@ public class Server extends HandlerWrapper implements Attributes
@Override
public void dump(Appendable out,String indent) throws IOException
{
- dumpBeans(out,indent,new ClassLoaderDump(this.getClass().getClassLoader()),_attributes);
+ dumpObjects(out,indent,new ClassLoaderDump(this.getClass().getClassLoader()),_attributes);
}
/* ------------------------------------------------------------ */
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandler.java
index 330221cd185..a891fdb4e05 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandler.java
@@ -148,12 +148,6 @@ public abstract class AbstractHandler extends ContainerLifeCycle implements Hand
super.destroy();
}
- @Override
- public void dumpThis(Appendable out) throws IOException
- {
- out.append(toString()).append(" - ").append(getState()).append('\n');
- }
-
/**
* An extension of AbstractHandler that handles {@link DispatcherType#ERROR} dispatches.
*
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
index 503147a9963..08839a4f137 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
@@ -256,7 +256,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
@Override
public void dump(Appendable out, String indent) throws IOException
{
- dumpBeans(out, indent,
+ dumpObjects(out, indent,
new ClassLoaderDump(getClassLoader()),
new DumpableCollection("eventListeners " + this, _eventListeners),
new DumpableCollection("handler attributes " + this, ((AttributesMap)getAttributes()).getAttributeEntrySet()),
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/InetAccessHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/InetAccessHandler.java
index 4529f3fa7a8..d3d4137301b 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/InetAccessHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/InetAccessHandler.java
@@ -138,7 +138,7 @@ public class InetAccessHandler extends HandlerWrapper
@Override
public void dump(Appendable out, String indent) throws IOException
{
- dumpBeans(out, indent,
+ dumpObjects(out, indent,
DumpableCollection.from("included",_set.getIncluded()),
DumpableCollection.from("excluded",_set.getExcluded()));
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java
index 49021ba059f..45c11c43b9a 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java
@@ -18,16 +18,6 @@
package org.eclipse.jetty.server;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.greaterThanOrEqualTo;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
-import static org.hamcrest.Matchers.startsWith;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
@@ -58,9 +48,20 @@ import org.eclipse.jetty.util.log.AbstractLogger;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.StacklessLogging;
import org.hamcrest.Matchers;
-
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
+import org.junit.jupiter.api.condition.DisabledOnJre;
+import org.junit.jupiter.api.condition.JRE;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
public abstract class HttpServerTestBase extends HttpServerTestFixture
{
@@ -1692,4 +1693,89 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
client.close();
}
}
+
+ @Test
+ @DisabledOnJre({JRE.JAVA_8, JRE.JAVA_9, JRE.JAVA_10})
+ public void testShutdown() throws Exception
+ {
+ configureServer(new ReadExactHandler());
+ byte[] content = new byte[4096];
+ Arrays.fill(content,(byte)'X');
+
+ try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
+ {
+ OutputStream os = client.getOutputStream();
+
+ // Send two persistent pipelined requests and then shutdown output
+ os.write(("GET / HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ "Content-Length: "+content.length+"\r\n" +
+ "\r\n").getBytes(StandardCharsets.ISO_8859_1));
+ os.write(content);
+ os.write(("GET / HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ "Content-Length: "+content.length+"\r\n" +
+ "\r\n").getBytes(StandardCharsets.ISO_8859_1));
+ os.write(content);
+ os.flush();
+ // Thread.sleep(50);
+ client.shutdownOutput();
+
+ // Read the two pipelined responses
+ HttpTester.Response response = HttpTester.parseResponse(client.getInputStream());
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.getContent(), containsString("Read "+content.length));
+
+ response = HttpTester.parseResponse(client.getInputStream());
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.getContent(), containsString("Read "+content.length));
+
+ // Read the close
+ assertThat(client.getInputStream().read(),is(-1));
+ }
+ }
+
+ @Test
+ @DisabledOnJre({JRE.JAVA_8, JRE.JAVA_9, JRE.JAVA_10})
+ public void testChunkedShutdown() throws Exception
+ {
+ configureServer(new ReadExactHandler(4096));
+ byte[] content = new byte[4096];
+ Arrays.fill(content,(byte)'X');
+
+ try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
+ {
+ OutputStream os = client.getOutputStream();
+
+ // Send two persistent pipelined requests and then shutdown output
+ os.write(("GET / HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ "Transfer-Encoding: chunked\r\n" +
+ "\r\n" +
+ "1000\r\n").getBytes(StandardCharsets.ISO_8859_1));
+ os.write(content);
+ os.write("\r\n0\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1));
+ os.write(("GET / HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ "Transfer-Encoding: chunked\r\n" +
+ "\r\n" +
+ "1000\r\n").getBytes(StandardCharsets.ISO_8859_1));
+ os.write(content);
+ os.write("\r\n0\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1));
+ os.flush();
+ client.shutdownOutput();
+
+ // Read the two pipelined responses
+ HttpTester.Response response = HttpTester.parseResponse(client.getInputStream());
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.getContent(), containsString("Read "+content.length));
+
+ response = HttpTester.parseResponse(client.getInputStream());
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.getContent(), containsString("Read "+content.length));
+
+ // Read the close
+ assertThat(client.getInputStream().read(),is(-1));
+ }
+ }
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java
index b93d761f8e6..c86691db5b2 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java
@@ -27,6 +27,7 @@ import java.net.Socket;
import java.net.URI;
import java.nio.charset.StandardCharsets;
+import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -185,6 +186,54 @@ public class HttpServerTestFixture
response.getOutputStream().print("Hello world\r\n");
}
}
+
+
+ protected static class ReadExactHandler extends AbstractHandler.ErrorDispatchHandler
+ {
+ private int expected;
+
+ public ReadExactHandler()
+ {
+ this(-1);
+ }
+
+ public ReadExactHandler(int expected)
+ {
+ this.expected = expected;
+ }
+
+ @Override
+ public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+ int len = expected<0?request.getContentLength():expected;
+ if (len<0)
+ throw new IllegalStateException();
+ byte[] content = new byte[len];
+ int offset = 0;
+ while (offset 0)
+ {
+ int read = input.read();
+ if (read < 0)
+ throw new IllegalStateException();
+ --length;
+ }
+
+ // Second: write the response.
+ response.setContentLength(bytes.length);
+ response.getOutputStream().write(bytes);
+ response.flushBuffer();
+
+ sleep(idleTimeout / 2);
+
+ // Third, read the EOF.
+ int read = input.read();
+ if (read >= 0)
+ throw new IllegalStateException();
+ }
+ });
+ server.start();
+
+ try
+ {
+ SSLContext sslContext = sslContextFactory.getSslContext();
+ try (Socket client = sslContext.getSocketFactory().createSocket("localhost", connector.getLocalPort()))
+ {
+ client.setSoTimeout(5 * idleTimeout);
+
+ OutputStream output = client.getOutputStream();
+ String request = "" +
+ "POST / HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ "Content-Length: " + content.length() + "\r\n" +
+ "\r\n";
+ output.write(request.getBytes(StandardCharsets.UTF_8));
+ output.write(bytes);
+ output.flush();
+
+ // Read the response.
+ InputStream input = client.getInputStream();
+ int crlfs = 0;
+ while (true)
+ {
+ int read = input.read();
+ assertThat(read, Matchers.greaterThanOrEqualTo(0));
+ if (read == '\r' || read == '\n')
+ ++crlfs;
+ else
+ crlfs = 0;
+ if (crlfs == 4)
+ break;
+ }
+ for (byte b : bytes)
+ assertEquals(b, input.read());
+
+
+ // Shutdown the output so the server reads the TLS close_notify.
+ client.shutdownOutput();
+ // client.close();
+
+ // The connection should now be idle timed out by the server.
+ int read = input.read();
+ assertEquals(-1, read);
+ }
+ }
+ finally
+ {
+ server.stop();
+ }
+ }
+
+ private void sleep(long time) throws IOException
+ {
+ try
+ {
+ Thread.sleep(time);
+ }
+ catch (InterruptedException x)
+ {
+ throw new InterruptedIOException();
+ }
+ }
+}
diff --git a/jetty-server/src/test/resources/jetty-logging.properties b/jetty-server/src/test/resources/jetty-logging.properties
index 581f7a2bbda..3f8368fa054 100644
--- a/jetty-server/src/test/resources/jetty-logging.properties
+++ b/jetty-server/src/test/resources/jetty-logging.properties
@@ -1,5 +1,4 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
#org.eclipse.jetty.LEVEL=DEBUG
-#org.eclipse.jetty.io.ssl.LEVEL=DEBUG
#org.eclipse.jetty.server.ConnectionLimit.LEVEL=DEBUG
#org.eclipse.jetty.server.AcceptRateLimit.LEVEL=DEBUG
\ No newline at end of file
diff --git a/jetty-servlet/pom.xml b/jetty-servlet/pom.xml
index e4ce852271f..90b20903779 100644
--- a/jetty-servlet/pom.xml
+++ b/jetty-servlet/pom.xml
@@ -3,7 +3,7 @@
jetty-projectorg.eclipse.jetty
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-servlet
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
index 48fb06391de..b4196f3197f 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
@@ -1486,10 +1486,14 @@ public class ServletContextHandler extends ContextHandler
throw new IllegalStateException();
if (!_enabled)
throw new UnsupportedOperationException();
- super.addListener(t);
+
+
+ checkListener(t.getClass());
+
ListenerHolder holder = getServletHandler().newListenerHolder(Source.JAVAX_API);
holder.setListener(t);
getServletHandler().addListener(holder);
+ addProgrammaticListener(t);
}
@Override
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
index d64b86c98f7..c4406f3bb2a 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
@@ -137,7 +137,7 @@ public class ServletHandler extends ScopedHandler
@Override
public void dump(Appendable out, String indent) throws IOException
{
- dumpBeans(out,indent,
+ dumpObjects(out,indent,
DumpableCollection.fromArray("listeners "+this,_listeners),
DumpableCollection.fromArray("filters "+this,_filters),
DumpableCollection.fromArray("filterMappings "+this,_filterMappings),
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java
index ecb22584459..9a67a85e5ff 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java
@@ -24,15 +24,20 @@ import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Collections;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.Servlet;
+import javax.servlet.ServletContainerInitializer;
+import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
@@ -60,6 +65,7 @@ import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.Decorator;
+import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@@ -72,6 +78,66 @@ public class ServletContextHandlerTest
private static final AtomicInteger __testServlets = new AtomicInteger();
+ public static class MySCI implements ServletContainerInitializer
+ {
+ @Override
+ public void onStartup(Set> c, ServletContext ctx) throws ServletException
+ {
+ //add a programmatic listener
+ if (ctx.getAttribute("MySCI.startup") != null)
+ throw new IllegalStateException("MySCI already called");
+ ctx.setAttribute("MySCI.startup", Boolean.TRUE);
+ ctx.addListener(new MyContextListener());
+ }
+ }
+
+ public static class MySCIStarter extends AbstractLifeCycle implements ServletContextHandler.ServletContainerInitializerCaller
+ {
+ MySCI _sci = new MySCI();
+ ContextHandler.Context _ctx;
+
+ MySCIStarter (ContextHandler.Context ctx)
+ {
+ _ctx = ctx;
+ }
+
+ @Override
+ protected void doStart() throws Exception
+ {
+ super.doStart();
+ //call the SCI
+ try
+ {
+ _ctx.setExtendedListenerTypes(true);
+ _sci.onStartup(Collections.emptySet(), _ctx);
+ }
+ finally
+ {
+
+ }
+ }
+ }
+
+
+ public static class MyContextListener implements ServletContextListener
+ {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce)
+ {
+ assertNull(sce.getServletContext().getAttribute("MyContextListener.contextInitialized"));
+ sce.getServletContext().setAttribute("MyContextListener.contextInitialized", Boolean.TRUE);
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent sce)
+ {
+ assertNull(sce.getServletContext().getAttribute("MyContextListener.contextDestroyed"));
+ sce.getServletContext().setAttribute("MyContextListener.contextDestroyed", Boolean.TRUE);
+ }
+
+ }
+
public static class MySessionHandler extends SessionHandler
{
public void checkSessionListeners (int size)
@@ -158,6 +224,20 @@ public class ServletContextHandlerTest
sessions.checkSessionListeners(1);
}
+
+ @Test
+ public void testListenerFromSCI() throws Exception
+ {
+ ContextHandlerCollection contexts = new ContextHandlerCollection();
+ _server.setHandler(contexts);
+
+ ServletContextHandler root = new ServletContextHandler(contexts,"/");
+ root.addBean(new MySCIStarter(root.getServletContext()), true);
+ _server.start();
+ assertTrue((Boolean)root.getServletContext().getAttribute("MySCI.startup"));
+ assertTrue((Boolean)root.getServletContext().getAttribute("MyContextListener.contextInitialized"));
+ }
+
@Test
public void testFindContainer() throws Exception
{
diff --git a/jetty-servlets/pom.xml b/jetty-servlets/pom.xml
index 381b06d3ab1..5898c44f260 100644
--- a/jetty-servlets/pom.xml
+++ b/jetty-servlets/pom.xml
@@ -3,7 +3,7 @@
jetty-projectorg.eclipse.jetty
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-servlets
diff --git a/jetty-spring/pom.xml b/jetty-spring/pom.xml
index d90356a713d..6b5cb30aaf1 100644
--- a/jetty-spring/pom.xml
+++ b/jetty-spring/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-spring
diff --git a/jetty-start/pom.xml b/jetty-start/pom.xml
index 395490081a6..f58e58deea2 100644
--- a/jetty-start/pom.xml
+++ b/jetty-start/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-start
diff --git a/jetty-unixsocket/pom.xml b/jetty-unixsocket/pom.xml
index ace136f841d..ed2dbd51a7e 100644
--- a/jetty-unixsocket/pom.xml
+++ b/jetty-unixsocket/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-unixsocket
diff --git a/jetty-util-ajax/pom.xml b/jetty-util-ajax/pom.xml
index 757110eb86d..a5c20410304 100644
--- a/jetty-util-ajax/pom.xml
+++ b/jetty-util-ajax/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-util-ajax
diff --git a/jetty-util/pom.xml b/jetty-util/pom.xml
index 47d3b894916..b777fe549e7 100644
--- a/jetty-util/pom.xml
+++ b/jetty-util/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-util
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java
index fd1f70447cc..4fbe2d255a2 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java
@@ -655,10 +655,21 @@ public class ContainerLifeCycle extends AbstractLifeCycle implements Container,
return Dumpable.dump(this);
}
+ /**
+ * @param dumpable the object to dump
+ * @return the string representation of the given Dumpable
+ * @deprecated use {@link Dumpable#dump(Dumpable)} instead
+ */
+ @Deprecated
+ public static String dump(Dumpable dumpable)
+ {
+ return Dumpable.dump(dumpable);
+ }
+
@Override
public void dump(Appendable out, String indent) throws IOException
{
- dumpBeans(out,indent);
+ dumpObjects(out,indent);
}
/**
@@ -683,6 +694,17 @@ public class ContainerLifeCycle extends AbstractLifeCycle implements Container,
out.append(String.valueOf(this)).append(" - ").append(getState()).append("\n");
}
+ /**
+ * @param out The Appendable to dump to
+ * @param obj The object to dump
+ * @throws IOException May be thrown by the Appendable
+ * @deprecated use {@link Dumpable#dumpObject(Appendable, Object)} instead
+ */
+ @Deprecated
+ public static void dumpObject(Appendable out, Object obj) throws IOException
+ {
+ Dumpable.dumpObject(out, obj);
+ }
/** Dump this object, it's contained beans and additional items to an Appendable
* @param out The appendable to dump to
@@ -690,11 +712,24 @@ public class ContainerLifeCycle extends AbstractLifeCycle implements Container,
* @param items Additional items to be dumped as contained.
* @throws IOException May be thrown by the Appendable
*/
- protected void dumpBeans(Appendable out, String indent, Object... items) throws IOException
+ protected void dumpObjects(Appendable out, String indent, Object... items) throws IOException
{
Dumpable.dumpObjects(out,indent,this, items);
}
+ /**
+ * @param out The appendable to dump to
+ * @param indent The indent to apply after any new lines
+ * @param items Additional collections to be dumped
+ * @throws IOException May be thrown by the Appendable
+ * @deprecated use {@link #dumpObjects(Appendable, String, Object...)}
+ */
+ @Deprecated
+ protected void dumpBeans(Appendable out, String indent, Collection>... items) throws IOException
+ {
+ dump(out, indent, items);
+ }
+
@Deprecated
public static void dump(Appendable out, String indent, Collection>... collections) throws IOException
{
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslSelectionDump.java b/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslSelectionDump.java
index c30dd82a671..e19355ed3e7 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslSelectionDump.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslSelectionDump.java
@@ -27,10 +27,9 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
-class SslSelectionDump extends ContainerLifeCycle implements Dumpable
+class SslSelectionDump implements Dumpable
{
static class CaptionedList extends ArrayList implements Dumpable
{
@@ -66,9 +65,7 @@ class SslSelectionDump extends ContainerLifeCycle implements Dumpable
String[] includedByConfig)
{
this.type = type;
- addBean(enabled);
- addBean(disabled);
-
+
List jvmEnabled = Arrays.asList(enabledByJVM);
List excludedPatterns = Arrays.stream(excludedByConfig)
.map((entry) -> Pattern.compile(entry))
@@ -165,12 +162,12 @@ class SslSelectionDump extends ContainerLifeCycle implements Dumpable
@Override
public void dump(Appendable out, String indent) throws IOException
{
- dumpBeans(out, indent);
+ Dumpable.dumpObjects(out, indent, this, enabled, disabled);
}
-
+
@Override
- protected void dumpThis(Appendable out) throws IOException
+ public String toString()
{
- out.append(type).append(" Selections").append(System.lineSeparator());
+ return String.format("%s Selections", type);
}
}
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ExecutorThreadPool.java b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ExecutorThreadPool.java
index 328a93d8e7f..d7764554710 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ExecutorThreadPool.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ExecutorThreadPool.java
@@ -388,7 +388,7 @@ public class ExecutorThreadPool extends ContainerLifeCycle implements ThreadPool
List jobs = Collections.emptyList();
if (isDetailedDump())
jobs = new ArrayList<>(_executor.getQueue());
- dumpBeans(out, indent, threads, new DumpableCollection("jobs", jobs));
+ dumpObjects(out, indent, threads, new DumpableCollection("jobs", jobs));
}
@Override
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java
index 57f1986cc57..5b2e9d2d132 100755
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java
@@ -627,11 +627,11 @@ public class QueuedThreadPool extends ContainerLifeCycle implements SizedThreadP
if (isDetailedDump())
{
List jobs = new ArrayList<>(getQueue());
- dumpBeans(out, indent, new DumpableCollection("threads", threads), new DumpableCollection("jobs", jobs));
+ dumpObjects(out, indent, new DumpableCollection("threads", threads), new DumpableCollection("jobs", jobs));
}
else
{
- dumpBeans(out, indent, new DumpableCollection("threads", threads));
+ dumpObjects(out, indent, new DumpableCollection("threads", threads));
}
}
diff --git a/jetty-webapp/pom.xml b/jetty-webapp/pom.xml
index 370dec504e1..ccdc76de42f 100644
--- a/jetty-webapp/pom.xml
+++ b/jetty-webapp/pom.xml
@@ -2,7 +2,7 @@
org.eclipse.jettyjetty-project
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0jetty-webapp
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
index 0f735e7933e..41d67a3624f 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
@@ -1067,7 +1067,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
Collections.sort(server_classes);
}
- dumpBeans(out,indent,
+ dumpObjects(out,indent,
new ClassLoaderDump(getClassLoader()),
new DumpableCollection("Systemclasses "+this,system_classes),
new DumpableCollection("Serverclasses "+this,server_classes),
diff --git a/jetty-websocket/javax-websocket-client-impl/pom.xml b/jetty-websocket/javax-websocket-client-impl/pom.xml
index bc578b8bdf7..b52ed7451c9 100644
--- a/jetty-websocket/javax-websocket-client-impl/pom.xml
+++ b/jetty-websocket/javax-websocket-client-impl/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jetty.websocketwebsocket-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-websocket/javax-websocket-server-impl/pom.xml b/jetty-websocket/javax-websocket-server-impl/pom.xml
index e00384408d9..a6dc97a324a 100644
--- a/jetty-websocket/javax-websocket-server-impl/pom.xml
+++ b/jetty-websocket/javax-websocket-server-impl/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jetty.websocketwebsocket-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-websocket/pom.xml b/jetty-websocket/pom.xml
index cdcb6fd7e03..fb6181f5988 100644
--- a/jetty-websocket/pom.xml
+++ b/jetty-websocket/pom.xml
@@ -3,7 +3,7 @@
jetty-projectorg.eclipse.jetty
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-websocket/websocket-api/pom.xml b/jetty-websocket/websocket-api/pom.xml
index c44e13fbac7..0188b065c81 100644
--- a/jetty-websocket/websocket-api/pom.xml
+++ b/jetty-websocket/websocket-api/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jetty.websocketwebsocket-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-websocket/websocket-client/pom.xml b/jetty-websocket/websocket-client/pom.xml
index d2cb9db0824..9a504bb6c8a 100644
--- a/jetty-websocket/websocket-client/pom.xml
+++ b/jetty-websocket/websocket-client/pom.xml
@@ -3,7 +3,7 @@
org.eclipse.jetty.websocketwebsocket-parent
- 9.4.13-SNAPSHOT
+ 9.4.15-SNAPSHOT4.0.0
diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java
index c732e779bd9..c30a5e664c1 100644
--- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java
+++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java
@@ -603,9 +603,9 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
}
/**
- * @param bindAddress
- * the address to bind to
- * @deprecated (this is a bad bad bad typo) use {@link #setBindAddress(SocketAddress)} instead
+ * @param bindAddress the address to bind to
+ * @deprecated (this is a bad bad bad typo) use {@link HttpClient#setBindAddress(SocketAddress)}
+ * on instance passed to {@link #WebSocketClient(HttpClient)}
*/
@Deprecated
public void setBindAdddress(SocketAddress bindAddress)
@@ -613,11 +613,23 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
setBindAddress(bindAddress);
}
+
+ /**
+ * @param bindAddress the address to bind to
+ * @deprecated Use {@link HttpClient#setBindAddress(SocketAddress)}
+ * on instance passed to {@link #WebSocketClient(HttpClient)}
+ */
+ @Deprecated
public void setBindAddress(SocketAddress bindAddress)
{
this.httpClient.setBindAddress(bindAddress);
}
+ /**
+ * @param bufferPool The buffer pool
+ * @deprecated Use {@link HttpClient#setByteBufferPool(ByteBufferPool)}
+ * on the instance passed to {@link #WebSocketClient(HttpClient)}
+ */
public void setBufferPool(ByteBufferPool bufferPool)
{
this.httpClient.setByteBufferPool(bufferPool);
@@ -625,15 +637,21 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
/**
* Set the timeout for connecting to the remote server.
- *
- * @param ms
- * the timeout in milliseconds
+ * @param ms the timeout in millisecondspool
+ * @deprecated Use {@link HttpClient#setConnectTimeout(long)}
+ * on the instance passed to {@link #WebSocketClient(HttpClient)}
*/
public void setConnectTimeout(long ms)
{
this.httpClient.setConnectTimeout(ms);
}
+ /**
+ * @param cookieStore The cookie store
+ * @deprecated Use {@link HttpClient#setCookieStore(CookieStore)} on the HttpClient instance passed
+ * to {@link #WebSocketClient(HttpClient)}
+ */
+ @Deprecated
public void setCookieStore(CookieStore cookieStore)
{
this.httpClient.setCookieStore(cookieStore);
@@ -655,6 +673,12 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
this.httpClient.setDispatchIO(dispatchIO);
}
+ /**
+ * @param executor The executor to use
+ * @deprecated Use {@link HttpClient#setExecutor(Executor)}
+ * on the instance passed to {@link #WebSocketClient(HttpClient)}
+ */
+ @Deprecated
public void setExecutor(Executor executor)
{
this.httpClient.setExecutor(executor);
@@ -680,8 +704,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
*