diff --git a/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebAppContext.java b/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebAppContext.java
index e46b30941f1..ba71267a162 100644
--- a/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebAppContext.java
+++ b/jetty-ant/src/main/java/org/eclipse/jetty/ant/AntWebAppContext.java
@@ -27,7 +27,6 @@ import java.security.CodeSource;
import java.security.PermissionCollection;
import java.util.ArrayList;
import java.util.Enumeration;
-import java.util.EventListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -615,9 +614,9 @@ public class AntWebAppContext extends WebAppContext
TaskLog.logWithTimestamp("Stopping web application " + this);
Thread.currentThread().sleep(500L);
super.doStop();
- //remove all filters, servlets and listeners. They will be recreated
- //either via application of a context xml file or web.xml or annotation or servlet api
- setEventListeners(new EventListener[0]);
+ // remove all filters and servlets. They will be recreated
+ // either via application of a context xml file or web.xml or annotation or servlet api.
+ // Event listeners are reset in ContextHandler.doStop()
getServletHandler().setFilters(new FilterHolder[0]);
getServletHandler().setFilterMappings(new FilterMapping[0]);
getServletHandler().setServlets(new ServletHolder[0]);
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java
index 8043261e130..c289ab5a481 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java
@@ -22,6 +22,7 @@ import java.io.EOFException;
import java.nio.ByteBuffer;
import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.HttpClientTransport;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.client.HttpReceiver;
import org.eclipse.jetty.client.HttpResponse;
@@ -50,8 +51,13 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
super(channel);
HttpClient httpClient = channel.getHttpDestination().getHttpClient();
parser = new HttpParser(this, -1, httpClient.getHttpCompliance());
- parser.setHeaderCacheSize(((HttpClientTransportOverHTTP)httpClient.getTransport()).getHeaderCacheSize());
- parser.setHeaderCacheCaseSensitive(((HttpClientTransportOverHTTP)httpClient.getTransport()).isHeaderCacheCaseSensitive());
+ HttpClientTransport transport = httpClient.getTransport();
+ if (transport instanceof HttpClientTransportOverHTTP)
+ {
+ HttpClientTransportOverHTTP httpTransport = (HttpClientTransportOverHTTP)transport;
+ parser.setHeaderCacheSize(httpTransport.getHeaderCacheSize());
+ parser.setHeaderCacheCaseSensitive(httpTransport.isHeaderCacheCaseSensitive());
+ }
}
@Override
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/jmx/HttpClientJMXTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/jmx/HttpClientJMXTest.java
index c5d254cc3c3..c852d304b29 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/jmx/HttpClientJMXTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/jmx/HttpClientJMXTest.java
@@ -39,7 +39,6 @@ public class HttpClientJMXTest
String name = "foo";
HttpClient httpClient = new HttpClient();
httpClient.setName(name);
- httpClient.start();
try
{
@@ -47,6 +46,7 @@ public class HttpClientJMXTest
MBeanContainer mbeanContainer = new MBeanContainer(mbeanServer);
// Adding MBeanContainer as a bean will trigger the registration of MBeans.
httpClient.addBean(mbeanContainer);
+ httpClient.start();
String domain = HttpClient.class.getPackage().getName();
ObjectName pattern = new ObjectName(domain + ":type=" + HttpClient.class.getSimpleName().toLowerCase(Locale.ENGLISH) + ",*");
diff --git a/jetty-home/src/main/resources/etc/jetty-setuid.xml b/jetty-home/src/main/resources/etc/jetty-setuid.xml
index 2fd25150b6c..3f2bff2f06b 100644
--- a/jetty-home/src/main/resources/etc/jetty-setuid.xml
+++ b/jetty-home/src/main/resources/etc/jetty-setuid.xml
@@ -6,7 +6,7 @@
-
+
diff --git a/jetty-home/src/main/resources/etc/jetty-started.xml b/jetty-home/src/main/resources/etc/jetty-started.xml
index b8d6007fbcd..11a2e151795 100644
--- a/jetty-home/src/main/resources/etc/jetty-started.xml
+++ b/jetty-home/src/main/resources/etc/jetty-started.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2ClientConnectionFactory.java b/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2ClientConnectionFactory.java
index bede2c57125..626388eb846 100644
--- a/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2ClientConnectionFactory.java
+++ b/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2ClientConnectionFactory.java
@@ -73,7 +73,7 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
final HTTP2ClientConnection connection = new HTTP2ClientConnection(client, byteBufferPool, executor, endPoint,
parser, session, client.getInputBufferSize(), promise, listener);
- connection.addListener(connectionListener);
+ connection.addEventListener(connectionListener);
return customize(connection, context);
}
diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java
index d8ff0c3ee62..cccd7c6f16f 100644
--- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java
+++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java
@@ -261,7 +261,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
connection.setUseInputDirectByteBuffers(isUseInputDirectByteBuffers());
connection.setUseOutputDirectByteBuffers(isUseOutputDirectByteBuffers());
- connection.addListener(sessionContainer);
+ connection.addEventListener(sessionContainer);
return configure(connection, connector, endPoint);
}
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java
index 74ba6f0ed52..f4ee23bd67e 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java
@@ -18,6 +18,7 @@
package org.eclipse.jetty.io;
+import java.util.EventListener;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
@@ -57,13 +58,14 @@ public abstract class AbstractConnection implements Connection
}
@Override
- public void addListener(Listener listener)
+ public void addEventListener(EventListener listener)
{
- _listeners.add(listener);
+ if (listener instanceof Listener)
+ _listeners.add((Listener)listener);
}
@Override
- public void removeListener(Listener listener)
+ public void removeEventListener(EventListener listener)
{
_listeners.remove(listener);
}
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ClientConnectionFactory.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ClientConnectionFactory.java
index 56f71586c63..fd81e7a3245 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/ClientConnectionFactory.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ClientConnectionFactory.java
@@ -19,6 +19,7 @@
package org.eclipse.jetty.io;
import java.io.IOException;
+import java.util.EventListener;
import java.util.List;
import java.util.Map;
@@ -43,7 +44,7 @@ public interface ClientConnectionFactory
{
ContainerLifeCycle client = (ContainerLifeCycle)context.get(CLIENT_CONTEXT_KEY);
if (client != null)
- client.getBeans(Connection.Listener.class).forEach(connection::addListener);
+ client.getBeans(EventListener.class).forEach(connection::addEventListener);
return connection;
}
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java
index 885aee928cd..c8ccb25b73e 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java
@@ -20,6 +20,7 @@ package org.eclipse.jetty.io;
import java.io.Closeable;
import java.nio.ByteBuffer;
+import java.util.EventListener;
import org.eclipse.jetty.util.component.Container;
@@ -38,14 +39,14 @@ public interface Connection extends Closeable
*
* @param listener the listener to add
*/
- public void addListener(Listener listener);
+ public void addEventListener(EventListener listener);
/**
*
Removes a listener of connection events.
*
* @param listener the listener to remove
*/
- public void removeListener(Listener listener);
+ public void removeEventListener(EventListener listener);
/**
*
Callback method invoked when this connection is opened.
@@ -133,7 +134,7 @@ public interface Connection extends Closeable
* the Connector or ConnectionFactory are added as listeners to all new connections
*
*/
- public interface Listener
+ public interface Listener extends EventListener
{
public void onOpened(Connection connection);
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java b/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java
index 4115e471a77..8d51487b7c8 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java
@@ -38,6 +38,7 @@ import java.util.function.IntUnaryOperator;
import org.eclipse.jetty.util.ProcessorUtils;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
+import org.eclipse.jetty.util.component.Container;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
@@ -389,31 +390,37 @@ public abstract class SelectorManager extends ContainerLifeCycle implements Dump
*/
public abstract Connection newConnection(SelectableChannel channel, EndPoint endpoint, Object attachment) throws IOException;
- public void addEventListener(EventListener listener)
+ /**
+ * @param listener An EventListener
+ * @see AcceptListener
+ * @see Container#addEventListener(EventListener)
+ */
+ @Override
+ public boolean addEventListener(EventListener listener)
{
if (isRunning())
throw new IllegalStateException(this.toString());
- if (listener instanceof AcceptListener)
- addAcceptListener(AcceptListener.class.cast(listener));
+ if (super.addEventListener(listener))
+ {
+ if (listener instanceof AcceptListener)
+ _acceptListeners.add((AcceptListener)listener);
+ return true;
+ }
+ return false;
}
- public void removeEventListener(EventListener listener)
+ @Override
+ public boolean removeEventListener(EventListener listener)
{
if (isRunning())
throw new IllegalStateException(this.toString());
- if (listener instanceof AcceptListener)
- removeAcceptListener(AcceptListener.class.cast(listener));
- }
-
- public void addAcceptListener(AcceptListener listener)
- {
- if (!_acceptListeners.contains(listener))
- _acceptListeners.add(listener);
- }
-
- public void removeAcceptListener(AcceptListener listener)
- {
- _acceptListeners.remove(listener);
+ if (super.removeEventListener(listener))
+ {
+ if (listener instanceof AcceptListener)
+ _acceptListeners.remove(listener);
+ return true;
+ }
+ return false;
}
protected void onAccepting(SelectableChannel channel)
@@ -461,12 +468,16 @@ public abstract class SelectorManager extends ContainerLifeCycle implements Dump
}
}
+ public interface SelectorManagerListener extends EventListener
+ {
+ }
+
/**
*
A listener for accept events.
*
This listener is called from either the selector or acceptor thread
* and implementations must be non blocking and fast.
*/
- public interface AcceptListener extends EventListener
+ public interface AcceptListener extends SelectorManagerListener
{
/**
* Called immediately after a new SelectableChannel is accepted, but
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java b/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java
index a1e040754d7..0a39a7bd075 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java
@@ -571,7 +571,8 @@ public abstract class WriteFlusher
}
/**
- *
A listener of {@link WriteFlusher} events.
+ *
A listener of {@link WriteFlusher} events.
+ * If implemented by a Connection class, the {@link #onFlushed(long)} event will be delivered to it.
*/
public interface Listener
{
diff --git a/jetty-maven-plugin/src/it/javax-annotation-api/src/config/jetty.xml b/jetty-maven-plugin/src/it/javax-annotation-api/src/config/jetty.xml
index 4dd58944725..4e43b5305df 100644
--- a/jetty-maven-plugin/src/it/javax-annotation-api/src/config/jetty.xml
+++ b/jetty-maven-plugin/src/it/javax-annotation-api/src/config/jetty.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/jetty-maven-plugin/src/it/jetty-cdi-run-forked/src/main/jetty/jetty.xml b/jetty-maven-plugin/src/it/jetty-cdi-run-forked/src/main/jetty/jetty.xml
index 9e32909fd93..8f1c473fb3f 100644
--- a/jetty-maven-plugin/src/it/jetty-cdi-run-forked/src/main/jetty/jetty.xml
+++ b/jetty-maven-plugin/src/it/jetty-cdi-run-forked/src/main/jetty/jetty.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/jetty-maven-plugin/src/it/jetty-deploy-war-mojo-it/src/config/jetty.xml b/jetty-maven-plugin/src/it/jetty-deploy-war-mojo-it/src/config/jetty.xml
index 4dd58944725..4e43b5305df 100644
--- a/jetty-maven-plugin/src/it/jetty-deploy-war-mojo-it/src/config/jetty.xml
+++ b/jetty-maven-plugin/src/it/jetty-deploy-war-mojo-it/src/config/jetty.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/jetty-maven-plugin/src/it/jetty-maven-plugin-provided-module-dep/web/src/config/jetty.xml b/jetty-maven-plugin/src/it/jetty-maven-plugin-provided-module-dep/web/src/config/jetty.xml
index de81416a934..7df44bd5ad7 100644
--- a/jetty-maven-plugin/src/it/jetty-maven-plugin-provided-module-dep/web/src/config/jetty.xml
+++ b/jetty-maven-plugin/src/it/jetty-maven-plugin-provided-module-dep/web/src/config/jetty.xml
@@ -30,7 +30,7 @@
-
+
diff --git a/jetty-maven-plugin/src/it/jetty-run-distro-mojo-it/jetty-simple-webapp/src/base/etc/test-jetty.xml b/jetty-maven-plugin/src/it/jetty-run-distro-mojo-it/jetty-simple-webapp/src/base/etc/test-jetty.xml
index 08d848ec4c6..c3df301c562 100644
--- a/jetty-maven-plugin/src/it/jetty-run-distro-mojo-it/jetty-simple-webapp/src/base/etc/test-jetty.xml
+++ b/jetty-maven-plugin/src/it/jetty-run-distro-mojo-it/jetty-simple-webapp/src/base/etc/test-jetty.xml
@@ -3,7 +3,7 @@
-
+
diff --git a/jetty-maven-plugin/src/it/jetty-run-forked-mojo-it/jetty-simple-webapp/src/config/jetty.xml b/jetty-maven-plugin/src/it/jetty-run-forked-mojo-it/jetty-simple-webapp/src/config/jetty.xml
index 4dd58944725..4e43b5305df 100644
--- a/jetty-maven-plugin/src/it/jetty-run-forked-mojo-it/jetty-simple-webapp/src/config/jetty.xml
+++ b/jetty-maven-plugin/src/it/jetty-run-forked-mojo-it/jetty-simple-webapp/src/config/jetty.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/jetty-maven-plugin/src/it/jetty-run-mojo-it/jetty-simple-webapp/src/config/jetty.xml b/jetty-maven-plugin/src/it/jetty-run-mojo-it/jetty-simple-webapp/src/config/jetty.xml
index 4dd58944725..4e43b5305df 100644
--- a/jetty-maven-plugin/src/it/jetty-run-mojo-it/jetty-simple-webapp/src/config/jetty.xml
+++ b/jetty-maven-plugin/src/it/jetty-run-mojo-it/jetty-simple-webapp/src/config/jetty.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/jetty-maven-plugin/src/it/jetty-run-mojo-jsp/src/config/jetty.xml b/jetty-maven-plugin/src/it/jetty-run-mojo-jsp/src/config/jetty.xml
index 4dd58944725..4e43b5305df 100644
--- a/jetty-maven-plugin/src/it/jetty-run-mojo-jsp/src/config/jetty.xml
+++ b/jetty-maven-plugin/src/it/jetty-run-mojo-jsp/src/config/jetty.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/jetty-maven-plugin/src/it/jetty-run-mojo-multi-module-single-war-it/webapp-war/src/config/jetty.xml b/jetty-maven-plugin/src/it/jetty-run-mojo-multi-module-single-war-it/webapp-war/src/config/jetty.xml
index 4dd58944725..4e43b5305df 100644
--- a/jetty-maven-plugin/src/it/jetty-run-mojo-multi-module-single-war-it/webapp-war/src/config/jetty.xml
+++ b/jetty-maven-plugin/src/it/jetty-run-mojo-multi-module-single-war-it/webapp-war/src/config/jetty.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/jetty-maven-plugin/src/it/jetty-run-war-exploded-mojo-it/jetty-simple-webapp/src/config/jetty.xml b/jetty-maven-plugin/src/it/jetty-run-war-exploded-mojo-it/jetty-simple-webapp/src/config/jetty.xml
index 4dd58944725..4e43b5305df 100644
--- a/jetty-maven-plugin/src/it/jetty-run-war-exploded-mojo-it/jetty-simple-webapp/src/config/jetty.xml
+++ b/jetty-maven-plugin/src/it/jetty-run-war-exploded-mojo-it/jetty-simple-webapp/src/config/jetty.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/jetty-maven-plugin/src/it/jetty-run-war-mojo-it/jetty-simple-webapp/src/config/jetty.xml b/jetty-maven-plugin/src/it/jetty-run-war-mojo-it/jetty-simple-webapp/src/config/jetty.xml
index 4dd58944725..4e43b5305df 100644
--- a/jetty-maven-plugin/src/it/jetty-run-war-mojo-it/jetty-simple-webapp/src/config/jetty.xml
+++ b/jetty-maven-plugin/src/it/jetty-run-war-mojo-it/jetty-simple-webapp/src/config/jetty.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/jetty-maven-plugin/src/it/jetty-start-mojo-it/jetty-simple-webapp/src/config/jetty.xml b/jetty-maven-plugin/src/it/jetty-start-mojo-it/jetty-simple-webapp/src/config/jetty.xml
index 4dd58944725..4e43b5305df 100644
--- a/jetty-maven-plugin/src/it/jetty-start-mojo-it/jetty-simple-webapp/src/config/jetty.xml
+++ b/jetty-maven-plugin/src/it/jetty-start-mojo-it/jetty-simple-webapp/src/config/jetty.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/jetty-maven-plugin/src/it/run-mojo-gwt-it/beer-server/src/config/jetty.xml b/jetty-maven-plugin/src/it/run-mojo-gwt-it/beer-server/src/config/jetty.xml
index 4dd58944725..4e43b5305df 100644
--- a/jetty-maven-plugin/src/it/run-mojo-gwt-it/beer-server/src/config/jetty.xml
+++ b/jetty-maven-plugin/src/it/run-mojo-gwt-it/beer-server/src/config/jetty.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java
index 302d267f00d..2714997a8ed 100644
--- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java
+++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java
@@ -23,7 +23,6 @@ import java.io.IOException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.util.ArrayList;
-import java.util.EventListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -356,11 +355,9 @@ public class JettyWebAppContext extends WebAppContext
super.doStop();
- // remove all listeners, servlets and filters. This is because we will
- // re-apply
- // any context xml file, which means they would potentially be added
- // multiple times.
- setEventListeners(new EventListener[0]);
+ // remove all servlets and filters. This is because we will
+ // re-appy any context xml file, which means they would potentially be
+ // added multiple times.
getServletHandler().setFilters(new FilterHolder[0]);
getServletHandler().setFilterMappings(new FilterMapping[0]);
getServletHandler().setServlets(new ServletHolder[0]);
diff --git a/jetty-maven-plugin/src/main/resources/jetty-maven.xml b/jetty-maven-plugin/src/main/resources/jetty-maven.xml
index 8ee79fbec55..47d10a84d4f 100644
--- a/jetty-maven-plugin/src/main/resources/jetty-maven.xml
+++ b/jetty-maven-plugin/src/main/resources/jetty-maven.xml
@@ -2,7 +2,7 @@
-
+
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 0c688fe393c..6b3d9fa24f4 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
@@ -46,7 +46,7 @@ public class Activator implements BundleActivator
{
//For test purposes, use a random port
Server server = new Server(0);
- server.getConnectors()[0].addLifeCycleListener(new AbstractLifeCycleListener()
+ server.getConnectors()[0].addEventListener(new AbstractLifeCycleListener()
{
/**
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-context-as-service.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-context-as-service.xml
index e5baeae8106..5333433aab7 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-context-as-service.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-context-as-service.xml
@@ -31,7 +31,7 @@
-
+ boot.context.service.port
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-webapp-as-service.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-webapp-as-service.xml
index 3f034f1334b..b90533d0b60 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-webapp-as-service.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-webapp-as-service.xml
@@ -31,7 +31,7 @@
-
+ boot.webapp.service.port
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-annotations.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-annotations.xml
index ccb14c09de9..271f12e042c 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-annotations.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-annotations.xml
@@ -31,7 +31,7 @@
-
+ boot.annotations.port
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-bundle.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-bundle.xml
index 80335e9184a..6cb5d15395a 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-bundle.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-bundle.xml
@@ -31,7 +31,7 @@
-
+ boot.bundle.port
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-javax-websocket.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-javax-websocket.xml
index 6f28312891c..4ff583996c4 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-javax-websocket.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-javax-websocket.xml
@@ -31,7 +31,7 @@
-
+ boot.javax.websocket.port
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-jsp.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-jsp.xml
index 5ae769fca57..9edaf7b56c0 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-jsp.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-jsp.xml
@@ -31,7 +31,7 @@
-
+ boot.jsp.port
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-websocket.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-websocket.xml
index 20bb83b2765..e1b37e7c70f 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-websocket.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http-boot-with-websocket.xml
@@ -31,7 +31,7 @@
-
+ boot.websocket.port
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http.xml
index 8995bfc70ce..6b883c59a0e 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-http.xml
@@ -31,7 +31,7 @@
-
+ foo.foo
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-https.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-https.xml
index 41fb957e7f0..941216afee1 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-https.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-https.xml
@@ -16,7 +16,7 @@
-
+ boot.https.port
diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java
index 25b6dbe6235..b1fbd915252 100644
--- a/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java
+++ b/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java
@@ -125,6 +125,31 @@ public class SpnegoAuthenticatorTest
assertEquals(HttpHeader.NEGOTIATE.asString(), res.getHeader(HttpHeader.WWW_AUTHENTICATE.asString()));
assertEquals(HttpServletResponse.SC_UNAUTHORIZED, res.getStatus());
}
+
+ class MockConnector extends AbstractConnector
+ {
+ public MockConnector()
+ {
+ super(new Server() , null, null, null, 0);
+ }
+
+ @Override
+ protected void accept(int acceptorID) throws IOException, InterruptedException
+ {
+ }
+
+ @Override
+ public Object getTransport()
+ {
+ return null;
+ }
+
+ @Override
+ public String dumpSelf()
+ {
+ return null;
+ }
+ }
}
class MockConnector extends AbstractConnector
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnectionFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnectionFactory.java
index af5bf1f0ec9..74c3402e3da 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnectionFactory.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnectionFactory.java
@@ -23,7 +23,6 @@ import java.util.Collections;
import java.util.List;
import org.eclipse.jetty.io.AbstractConnection;
-import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.ArrayUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
@@ -32,17 +31,7 @@ import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory;
/**
- *
Provides the common handling for {@link ConnectionFactory} implementations including:
- *
- *
Protocol identification
- *
Configuration of new Connections:
- *
- *
Setting inputbuffer size
- *
Calling {@link Connection#addListener(Connection.Listener)} for all
- * Connection.Listener instances found as beans on the {@link Connector}
- * and this {@link ConnectionFactory}
- *
- *
+ *
Provides the common handling for {@link ConnectionFactory} implementations.
*/
@ManagedObject
public abstract class AbstractConnectionFactory extends ContainerLifeCycle implements ConnectionFactory
@@ -92,19 +81,10 @@ public abstract class AbstractConnectionFactory extends ContainerLifeCycle imple
connection.setInputBufferSize(getInputBufferSize());
// Add Connection.Listeners from Connector
- if (connector instanceof ContainerLifeCycle)
- {
- ContainerLifeCycle aggregate = (ContainerLifeCycle)connector;
- for (Connection.Listener listener : aggregate.getBeans(Connection.Listener.class))
- {
- connection.addListener(listener);
- }
- }
+ connector.getEventListeners().forEach(connection::addEventListener);
+
// Add Connection.Listeners from this factory
- for (Connection.Listener listener : getBeans(Connection.Listener.class))
- {
- connection.addListener(listener);
- }
+ getEventListeners().forEach(connection::addEventListener);
return connection;
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
index 536fe39a16e..c2300504210 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
@@ -104,7 +104,6 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
_state = new HttpChannelState(this);
_request = new Request(this, newHttpInput(_state));
_response = new Response(this, newHttpOutput());
-
_executor = connector.getServer().getThreadPool();
_requestLog = connector.getServer().getRequestLog();
_combinedListener = (connector instanceof AbstractConnector)
@@ -1224,15 +1223,16 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
public void succeeded()
{
_written += _length;
- if (_complete)
- _response.getHttpOutput().closed();
- super.succeeded();
if (_commit)
_combinedListener.onResponseCommit(_request);
if (_length > 0)
_combinedListener.onResponseContent(_request, _content);
if (_complete && _state.completeResponse())
+ {
+ _response.getHttpOutput().closed();
_combinedListener.onResponseEnd(_request);
+ }
+ super.succeeded();
}
@Override
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
index feaf21afd12..030499d8b2a 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
@@ -386,22 +386,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
if (!_state.compareAndSet(state, State.CLOSED))
break;
- // Just make sure write and output stream really are closed
- try
- {
- _channel.getResponse().closeOutput();
- }
- catch (Throwable x)
- {
- if (LOG.isDebugEnabled())
- LOG.debug(x);
- abort(x);
- }
- finally
- {
- releaseBuffer();
- }
- // Return even if an exception is thrown by closeOutput().
+ releaseBuffer();
return;
}
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java
index e7aec0ea14e..4f11e3df363 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java
@@ -223,10 +223,8 @@ public class ServerConnector extends AbstractNetworkConnector
@Override
protected void doStart() throws Exception
{
- for (EventListener l : getBeans(EventListener.class))
- {
+ for (EventListener l : getBeans(SelectorManager.SelectorManagerListener.class))
_manager.addEventListener(l);
- }
super.doStart();
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 875b532cfb3..0050e2fd8da 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
@@ -198,7 +198,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
private boolean _compactPath = false;
private boolean _usingSecurityManager = System.getSecurityManager() != null;
- private final List _eventListeners = new CopyOnWriteArrayList<>();
private final List _programmaticListeners = new CopyOnWriteArrayList<>();
private final List _servletContextListeners = new CopyOnWriteArrayList<>();
private final List _destroySerletContextListeners = new ArrayList<>();
@@ -206,7 +205,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
private final List _servletRequestListeners = new CopyOnWriteArrayList<>();
private final List _servletRequestAttributeListeners = new CopyOnWriteArrayList<>();
private final List _contextListeners = new CopyOnWriteArrayList<>();
- private final List _durableListeners = new CopyOnWriteArrayList<>();
+ private final Set _durableListeners = new HashSet<>();
private String[] _protectedTargets;
private final CopyOnWriteArrayList _aliasChecks = new CopyOnWriteArrayList();
@@ -260,7 +259,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
{
dumpObjects(out, indent,
new ClassLoaderDump(getClassLoader()),
- new DumpableCollection("eventListeners " + this, _eventListeners),
new DumpableCollection("handler attributes " + this, ((AttributesMap)getAttributes()).getAttributeEntrySet()),
new DumpableCollection("context attributes " + this, ((Context)getServletContext()).getAttributeEntrySet()),
new DumpableCollection("initparams " + this, getInitParams().entrySet()));
@@ -606,101 +604,68 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
return _displayName;
}
- public EventListener[] getEventListeners()
- {
- return _eventListeners.toArray(new EventListener[_eventListeners.size()]);
- }
-
- /**
- * Set the context event listeners.
- *
- * @param eventListeners the event listeners
- * @see ServletContextListener
- * @see ServletContextAttributeListener
- * @see ServletRequestListener
- * @see ServletRequestAttributeListener
- */
- public void setEventListeners(EventListener[] eventListeners)
- {
- _contextListeners.clear();
- _servletContextListeners.clear();
- _servletContextAttributeListeners.clear();
- _servletRequestListeners.clear();
- _servletRequestAttributeListeners.clear();
- _eventListeners.clear();
-
- if (eventListeners != null)
- for (EventListener listener : eventListeners)
- {
- addEventListener(listener);
- }
- }
-
/**
* Add a context event listeners.
*
* @param listener the event listener to add
+ * @return true if the listener was added
+ * @see ContextScopeListener
* @see ServletContextListener
* @see ServletContextAttributeListener
* @see ServletRequestListener
* @see ServletRequestAttributeListener
*/
- public void addEventListener(EventListener listener)
+ @Override
+ public boolean addEventListener(EventListener listener)
{
- _eventListeners.add(listener);
-
- if (!(isStarted() || isStarting()))
+ if (super.addEventListener(listener))
{
- _durableListeners.add(listener);
+ if (listener instanceof ContextScopeListener)
+ {
+ _contextListeners.add((ContextScopeListener)listener);
+ if (__context.get() != null)
+ ((ContextScopeListener)listener).enterScope(__context.get(), null, "Listener registered");
+ }
+
+ if (listener instanceof ServletContextListener)
+ _servletContextListeners.add((ServletContextListener)listener);
+
+ if (listener instanceof ServletContextAttributeListener)
+ _servletContextAttributeListeners.add((ServletContextAttributeListener)listener);
+
+ if (listener instanceof ServletRequestListener)
+ _servletRequestListeners.add((ServletRequestListener)listener);
+
+ if (listener instanceof ServletRequestAttributeListener)
+ _servletRequestAttributeListeners.add((ServletRequestAttributeListener)listener);
+
+ return true;
}
-
- if (listener instanceof ContextScopeListener)
- {
- _contextListeners.add((ContextScopeListener)listener);
- if (__context.get() != null)
- ((ContextScopeListener)listener).enterScope(__context.get(), null, "Listener registered");
- }
-
- if (listener instanceof ServletContextListener)
- _servletContextListeners.add((ServletContextListener)listener);
-
- if (listener instanceof ServletContextAttributeListener)
- _servletContextAttributeListeners.add((ServletContextAttributeListener)listener);
-
- if (listener instanceof ServletRequestListener)
- _servletRequestListeners.add((ServletRequestListener)listener);
-
- if (listener instanceof ServletRequestAttributeListener)
- _servletRequestAttributeListeners.add((ServletRequestAttributeListener)listener);
+ return false;
}
- /**
- * Remove a context event listeners.
- *
- * @param listener the event listener to remove
- * @see ServletContextListener
- * @see ServletContextAttributeListener
- * @see ServletRequestListener
- * @see ServletRequestAttributeListener
- */
- public void removeEventListener(EventListener listener)
+ @Override
+ public boolean removeEventListener(EventListener listener)
{
- _eventListeners.remove(listener);
+ if (super.removeEventListener(listener))
+ {
+ if (listener instanceof ContextScopeListener)
+ _contextListeners.remove(listener);
- if (listener instanceof ContextScopeListener)
- _contextListeners.remove(listener);
+ if (listener instanceof ServletContextListener)
+ _servletContextListeners.remove(listener);
- if (listener instanceof ServletContextListener)
- _servletContextListeners.remove(listener);
+ if (listener instanceof ServletContextAttributeListener)
+ _servletContextAttributeListeners.remove(listener);
- if (listener instanceof ServletContextAttributeListener)
- _servletContextAttributeListeners.remove(listener);
+ if (listener instanceof ServletRequestListener)
+ _servletRequestListeners.remove(listener);
- if (listener instanceof ServletRequestListener)
- _servletRequestListeners.remove(listener);
-
- if (listener instanceof ServletRequestAttributeListener)
- _servletRequestAttributeListeners.remove(listener);
+ if (listener instanceof ServletRequestAttributeListener)
+ _servletRequestAttributeListeners.remove(listener);
+ return true;
+ }
+ return false;
}
/**
@@ -720,7 +685,11 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
public boolean isDurableListener(EventListener listener)
{
- return _durableListeners.contains(listener);
+ // The durable listeners are those set when the context is started
+ if (isStarted())
+ return _durableListeners.contains(listener);
+ // If we are not yet started then all set listeners are durable
+ return getEventListeners().contains(listener);
}
/**
@@ -800,6 +769,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
if (_mimeTypes == null)
_mimeTypes = new MimeTypes();
+ _durableListeners.addAll(getEventListeners());
+
try
{
// Set the classloader, context and enter scope
@@ -975,7 +946,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
stopContext();
// retain only durable listeners
- setEventListeners(_durableListeners.toArray(new EventListener[_durableListeners.size()]));
+ setEventListeners(_durableListeners);
_durableListeners.clear();
if (_errorHandler != null)
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java
index 86241449c95..789dc903236 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java
@@ -261,33 +261,26 @@ public class SessionHandler extends ScopedHandler
* Individual SessionManagers implementations may accept arbitrary listener types,
* but they are expected to at least handle HttpSessionActivationListener,
* HttpSessionAttributeListener, HttpSessionBindingListener and HttpSessionListener.
+ * @return true if the listener was added
* @see #removeEventListener(EventListener)
+ * @see HttpSessionAttributeListener
+ * @see HttpSessionListener
+ * @see HttpSessionIdListener
*/
- public void addEventListener(EventListener listener)
+ @Override
+ public boolean addEventListener(EventListener listener)
{
- if (listener instanceof HttpSessionAttributeListener)
- _sessionAttributeListeners.add((HttpSessionAttributeListener)listener);
- if (listener instanceof HttpSessionListener)
- _sessionListeners.add((HttpSessionListener)listener);
- if (listener instanceof HttpSessionIdListener)
- _sessionIdListeners.add((HttpSessionIdListener)listener);
- addBean(listener, false);
- }
-
- /**
- * Removes all event listeners for session-related events.
- *
- * @see #removeEventListener(EventListener)
- */
- public void clearEventListeners()
- {
- for (EventListener e : getBeans(EventListener.class))
+ if (super.addEventListener(listener))
{
- removeBean(e);
+ if (listener instanceof HttpSessionAttributeListener)
+ _sessionAttributeListeners.add((HttpSessionAttributeListener)listener);
+ if (listener instanceof HttpSessionListener)
+ _sessionListeners.add((HttpSessionListener)listener);
+ if (listener instanceof HttpSessionIdListener)
+ _sessionIdListeners.add((HttpSessionIdListener)listener);
+ return true;
}
- _sessionAttributeListeners.clear();
- _sessionListeners.clear();
- _sessionIdListeners.clear();
+ return false;
}
/**
@@ -785,21 +778,20 @@ public class SessionHandler extends ScopedHandler
}
}
- /**
- * Removes an event listener for for session-related events.
- *
- * @param listener the session event listener to remove
- * @see #addEventListener(EventListener)
- */
- public void removeEventListener(EventListener listener)
+ @Override
+ public boolean removeEventListener(EventListener listener)
{
- if (listener instanceof HttpSessionAttributeListener)
- _sessionAttributeListeners.remove(listener);
- if (listener instanceof HttpSessionListener)
- _sessionListeners.remove(listener);
- if (listener instanceof HttpSessionIdListener)
- _sessionIdListeners.remove(listener);
- removeBean(listener);
+ if (super.removeEventListener(listener))
+ {
+ if (listener instanceof HttpSessionAttributeListener)
+ _sessionAttributeListeners.remove(listener);
+ if (listener instanceof HttpSessionListener)
+ _sessionListeners.remove(listener);
+ if (listener instanceof HttpSessionIdListener)
+ _sessionIdListeners.remove(listener);
+ return true;
+ }
+ return false;
}
/**
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/DelayedServerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/DelayedServerTest.java
new file mode 100644
index 00000000000..ba11cf4f979
--- /dev/null
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/DelayedServerTest.java
@@ -0,0 +1,112 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2019 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.server;
+
+import java.nio.ByteBuffer;
+
+import org.eclipse.jetty.http.HttpCompliance;
+import org.eclipse.jetty.http.MetaData;
+import org.eclipse.jetty.io.Connection;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.util.Callback;
+import org.eclipse.jetty.util.thread.ThreadPool;
+import org.junit.jupiter.api.BeforeEach;
+
+/**
+ * Extended Server Tester.
+ */
+public class DelayedServerTest extends HttpServerTestBase
+{
+ @BeforeEach
+ public void init() throws Exception
+ {
+ startServer(new ServerConnector(_server, new HttpConnectionFactory()
+ {
+ @Override
+ public Connection newConnection(Connector connector, EndPoint endPoint)
+ {
+ return configure(new DelayedHttpConnection(getHttpConfiguration(), connector, endPoint), connector, endPoint);
+ }
+ }));
+ }
+
+ private static class DelayedHttpConnection extends HttpConnection
+ {
+ public DelayedHttpConnection(HttpConfiguration config, Connector connector, EndPoint endPoint)
+ {
+ super(config, connector, endPoint, false);
+ }
+
+ @Override
+ public void send(MetaData.Request request, MetaData.Response response, ByteBuffer content, boolean lastContent, Callback callback)
+ {
+ DelayedCallback delay = new DelayedCallback(callback, getServer().getThreadPool());
+ super.send(request, response, content, lastContent, delay);
+ }
+ }
+
+ private static class DelayedCallback extends Callback.Nested
+ {
+ final ThreadPool pool;
+
+ public DelayedCallback(Callback callback, ThreadPool threadPool)
+ {
+ super(callback);
+ pool = threadPool;
+ }
+
+ @Override
+ public void succeeded()
+ {
+ pool.execute(()->
+ {
+ try
+ {
+ Thread.sleep(10);
+ }
+ catch (InterruptedException e)
+ {
+ }
+ finally
+ {
+ super.succeeded();
+ }
+ });
+ }
+
+ @Override
+ public void failed(Throwable x)
+ {
+ pool.execute(()->
+ {
+ try
+ {
+ Thread.sleep(20);
+ }
+ catch (InterruptedException e)
+ {
+ }
+ finally
+ {
+ super.failed(x);
+ }
+ });
+ }
+ }
+}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ExtendedServerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ExtendedServerTest.java
index 3f37bcaa233..24311ba0f48 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ExtendedServerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ExtendedServerTest.java
@@ -21,7 +21,6 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
-import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
@@ -73,11 +72,6 @@ public class ExtendedServerTest extends HttpServerTestBase
{
private volatile long _lastSelected;
- public ExtendedEndPoint(SelectableChannel channel, ManagedSelector selector, SelectionKey key, Scheduler scheduler)
- {
- super(channel, selector, key, scheduler);
- }
-
public ExtendedEndPoint(SocketChannel channel, ManagedSelector selector, SelectionKey key, Scheduler scheduler)
{
super(channel, selector, key, scheduler);
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 e37d334d55d..6377df45ee0 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
@@ -28,10 +28,12 @@ import java.io.LineNumberReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URL;
+import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.concurrent.Exchanger;
import java.util.concurrent.atomic.AtomicBoolean;
+import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
@@ -42,6 +44,8 @@ import org.eclipse.jetty.http.tools.HttpTester;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.AbstractLogger;
import org.eclipse.jetty.util.log.Log;
@@ -1816,4 +1820,53 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
assertThat(client.getInputStream().read(), is(-1));
}
}
+
+ @Test
+ public void testSendAsyncContent() throws Exception
+ {
+ int size = 64 * 1024;
+ configureServer(new SendAsyncContentHandler(size));
+
+ try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
+ {
+ OutputStream os = client.getOutputStream();
+ os.write(("GET / HTTP/1.1\r\nHost: localhost\r\n\r\n").getBytes(StandardCharsets.ISO_8859_1));
+ os.flush();
+
+ HttpTester.Response response = HttpTester.parseResponse(client.getInputStream());
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.getContentBytes().length, is(size));
+
+ // Try again to check previous request completed OK
+ os.write(("GET / HTTP/1.1\r\nHost: localhost\r\n\r\n").getBytes(StandardCharsets.ISO_8859_1));
+ os.flush();
+ response = HttpTester.parseResponse(client.getInputStream());
+ assertThat(response.getStatus(), is(200));
+ assertThat(response.getContentBytes().length, is(size));
+ }
+ }
+
+ private class SendAsyncContentHandler extends AbstractHandler
+ {
+ final ByteBuffer content;
+
+ public SendAsyncContentHandler(int size)
+ {
+ content = BufferUtil.allocate(size);
+ Arrays.fill(content.array(),0,size,(byte)'X');
+ content.position(0);
+ content.limit(size);
+ }
+
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+ response.setStatus(200);
+ response.setContentType("application/unknown");
+ response.setContentLength(content.remaining());
+ AsyncContext async = request.startAsync();
+ ((HttpOutput)response.getOutputStream()).sendContent(content.slice(), Callback.from(async::complete));
+ }
+ }
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ShutdownHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ShutdownHandlerTest.java
index 04101fabc6a..c8bb17e6d7f 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ShutdownHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ShutdownHandlerTest.java
@@ -70,7 +70,7 @@ public class ShutdownHandlerTest
start(null);
CountDownLatch stopLatch = new CountDownLatch(1);
- server.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener()
+ server.addEventListener(new AbstractLifeCycle.AbstractLifeCycleListener()
{
@Override
public void lifeCycleStopped(LifeCycle event)
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ListenerHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ListenerHolder.java
index 9313237ea4e..f61014503d2 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ListenerHolder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ListenerHolder.java
@@ -61,6 +61,7 @@ public class ListenerHolder extends BaseHolder
* just like ServletHolder and FilterHolder,
* the listener will not be introspected for
* annotations like Resource etc.
+ * @param listener The listener instance
*/
public void setListener(EventListener listener)
{
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 9f69fce9b3d..a08bfb5ba45 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
@@ -196,24 +196,33 @@ public class ServletContextHandler extends ContextHandler
/**
* Add EventListener
- * Adds an EventListener to the list. @see org.eclipse.jetty.server.handler.ContextHandler#addEventListener().
- * Also adds any listeners that are session related to the SessionHandler.
*
* @param listener the listener to add
+ * @return true if the listener was added
+ * @see HttpSessionAttributeListener
+ * @see HttpSessionActivationListener
+ * @see HttpSessionBindingListener
+ * @see HttpSessionListener
+ * @see HttpSessionIdListener
+ * @see ContextHandler#addEventListener(EventListener)
*/
@Override
- public void addEventListener(EventListener listener)
+ public boolean addEventListener(EventListener listener)
{
- super.addEventListener(listener);
- if ((listener instanceof HttpSessionActivationListener) ||
- (listener instanceof HttpSessionAttributeListener) ||
- (listener instanceof HttpSessionBindingListener) ||
- (listener instanceof HttpSessionListener) ||
- (listener instanceof HttpSessionIdListener))
+ if (super.addEventListener(listener))
{
- if (_sessionHandler != null)
- _sessionHandler.addEventListener(listener);
+ if ((listener instanceof HttpSessionActivationListener) ||
+ (listener instanceof HttpSessionAttributeListener) ||
+ (listener instanceof HttpSessionBindingListener) ||
+ (listener instanceof HttpSessionListener) ||
+ (listener instanceof HttpSessionIdListener))
+ {
+ if (_sessionHandler != null)
+ _sessionHandler.addEventListener(listener);
+ }
+ return true;
}
+ return false;
}
@Override
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
index feb16756019..266363431cd 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
@@ -670,7 +670,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope
//Register a listener to delete tmp files that are created as a result of this
//servlet calling Request.getPart() or Request.getParts()
ContextHandler ch = ContextHandler.getContextHandler(getServletHandler().getServletContext());
- if (!Arrays.asList(ch.getEventListeners()).contains(MultiPartCleanerListener.INSTANCE))
+ if (!ch.getEventListeners().contains(MultiPartCleanerListener.INSTANCE))
ch.addEventListener(MultiPartCleanerListener.INSTANCE);
}
}
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 080e045eca2..67bf4b71b44 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
@@ -29,7 +29,6 @@ import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@@ -462,11 +461,9 @@ public class ServletContextHandlerTest
assertTrue(root.isProgrammaticListener(l.getListener()));
}
}
-
- EventListener[] listeners = root.getEventListeners();
- assertNotNull(listeners);
+
List listenerClassNames = new ArrayList<>();
- for (EventListener l : listeners)
+ for (EventListener l : root.getEventListeners())
listenerClassNames.add(l.getClass().getName());
assertTrue(listenerClassNames.contains("org.eclipse.jetty.servlet.ServletContextHandlerTest$MySCAListener"));
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletLifeCycleTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletLifeCycleTest.java
index 01100eb8b03..eb79854e970 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletLifeCycleTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletLifeCycleTest.java
@@ -21,6 +21,7 @@ package org.eclipse.jetty.servlet;
import java.io.IOException;
import java.util.EnumSet;
import java.util.EventListener;
+import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.servlet.DispatcherType;
@@ -120,9 +121,19 @@ public class ServletLifeCycleTest
"Destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestListener"));
// Listener added before start is not destroyed
- EventListener[] listeners = context.getEventListeners();
- assertThat(listeners.length, is(1));
- assertThat(listeners[0].getClass(), is(TestListener2.class));
+ List listeners = context.getEventListeners();
+ assertThat(listeners.size(), is(1));
+ assertThat(listeners.get(0).getClass(), is(TestListener2.class));
+
+ server.start();
+ context.addEventListener(new EventListener() {});listeners = context.getEventListeners();
+ listeners = context.getEventListeners();
+ assertThat(listeners.size(), is(3));
+
+ server.stop();
+ listeners = context.getEventListeners();
+ assertThat(listeners.size(), is(1));
+ assertThat(listeners.get(0).getClass(), is(TestListener2.class));
}
public static class TestDecorator implements Decorator
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/Decorator.java b/jetty-util/src/main/java/org/eclipse/jetty/util/Decorator.java
index 3346aa5f183..556451b56a0 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/Decorator.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/Decorator.java
@@ -19,10 +19,7 @@
package org.eclipse.jetty.util;
/**
- * Interface for 3rd party libraries to decorate recently created objects in Jetty.
- *
- * Most common use is weld/CDI.
- *
+ * Interface to decorate objects created by the {@link DecoratedObjectFactory}
*/
public interface Decorator
{
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/AbstractLifeCycle.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/AbstractLifeCycle.java
index 75b9aa9f74f..96474dc22c0 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/AbstractLifeCycle.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/AbstractLifeCycle.java
@@ -18,6 +18,9 @@
package org.eclipse.jetty.util.component;
+import java.util.Collection;
+import java.util.EventListener;
+import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.jetty.util.Uptime;
@@ -49,7 +52,7 @@ public abstract class AbstractLifeCycle implements LifeCycle
public static final String STARTED = State.STARTED.toString();
public static final String STOPPING = State.STOPPING.toString();
- private final CopyOnWriteArrayList _listeners = new CopyOnWriteArrayList();
+ private final List _eventListener = new CopyOnWriteArrayList<>();
private final Object _lock = new Object();
private volatile State _state = State.STOPPED;
private long _stopTimeout = 30000;
@@ -186,16 +189,39 @@ public abstract class AbstractLifeCycle implements LifeCycle
return _state == State.FAILED;
}
- @Override
- public void addLifeCycleListener(LifeCycle.Listener listener)
+ public List getEventListeners()
{
- _listeners.add(listener);
+ return _eventListener;
+ }
+
+ public void setEventListeners(Collection eventListeners)
+ {
+ for (EventListener l : _eventListener)
+ {
+ if (!eventListeners.contains(l))
+ removeEventListener(l);
+ }
+
+ for (EventListener l : eventListeners)
+ {
+ if (!_eventListener.contains(l))
+ addEventListener(l);
+ }
}
@Override
- public void removeLifeCycleListener(LifeCycle.Listener listener)
+ public boolean addEventListener(EventListener listener)
{
- _listeners.remove(listener);
+ if (_eventListener.contains(listener))
+ return false;
+ _eventListener.add(listener);
+ return true;
+ }
+
+ @Override
+ public boolean removeEventListener(EventListener listener)
+ {
+ return _eventListener.remove(listener);
}
@ManagedAttribute(value = "Lifecycle State for this instance", readonly = true)
@@ -226,8 +252,9 @@ public abstract class AbstractLifeCycle implements LifeCycle
_state = State.STARTED;
if (LOG.isDebugEnabled())
LOG.debug("STARTED @{}ms {}", Uptime.getUptime(), this);
- for (Listener listener : _listeners)
- listener.lifeCycleStarted(this);
+ for (EventListener listener : _eventListener)
+ if (listener instanceof Listener)
+ ((Listener)listener).lifeCycleStarted(this);
}
}
@@ -236,8 +263,9 @@ public abstract class AbstractLifeCycle implements LifeCycle
if (LOG.isDebugEnabled())
LOG.debug("STARTING {}", this);
_state = State.STARTING;
- for (Listener listener : _listeners)
- listener.lifeCycleStarting(this);
+ for (EventListener listener : _eventListener)
+ if (listener instanceof Listener)
+ ((Listener)listener).lifeCycleStarting(this);
}
private void setStopping()
@@ -245,8 +273,9 @@ public abstract class AbstractLifeCycle implements LifeCycle
if (LOG.isDebugEnabled())
LOG.debug("STOPPING {}", this);
_state = State.STOPPING;
- for (Listener listener : _listeners)
- listener.lifeCycleStopping(this);
+ for (EventListener listener : _eventListener)
+ if (listener instanceof Listener)
+ ((Listener)listener).lifeCycleStopping(this);
}
private void setStopped()
@@ -256,10 +285,9 @@ public abstract class AbstractLifeCycle implements LifeCycle
_state = State.STOPPED;
if (LOG.isDebugEnabled())
LOG.debug("STOPPED {}", this);
- for (Listener listener : _listeners)
- {
- listener.lifeCycleStopped(this);
- }
+ for (EventListener listener : _eventListener)
+ if (listener instanceof Listener)
+ ((Listener)listener).lifeCycleStopped(this);
}
}
@@ -268,9 +296,10 @@ public abstract class AbstractLifeCycle implements LifeCycle
_state = State.FAILED;
if (LOG.isDebugEnabled())
LOG.warn("FAILED " + this + ": " + th, th);
- for (Listener listener : _listeners)
+ for (EventListener listener : _eventListener)
{
- listener.lifeCycleFailure(this, th);
+ if (listener instanceof Listener)
+ ((Listener)listener).lifeCycleFailure(this, th);
}
}
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Container.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Container.java
index af5c52d2cf0..0b1de9bb5b6 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Container.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Container.java
@@ -18,25 +18,28 @@
package org.eclipse.jetty.util.component;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.List;
/**
* A Container
*/
public interface Container
{
-
/**
- * Add a bean. If the bean is-a {@link Listener}, then also do an implicit {@link #addEventListener(Listener)}.
+ * Add a bean. If the bean is-a {@link EventListener}, then also do an implicit {@link #addEventListener(EventListener)}.
*
* @param o the bean object to add
* @return true if the bean was added, false if it was already present
*/
- public boolean addBean(Object o);
+ boolean addBean(Object o);
/**
* Adds the given bean, explicitly managing it or not.
- *
+ * If the bean is-a {@link EventListener}, then also do an implicit {@link #addEventListener(EventListener)}.
* @param o The bean object to add
* @param managed whether to managed the lifecycle of the bean
* @return true if the bean was added, false if it was already present
@@ -47,7 +50,7 @@ public interface Container
* @return the list of beans known to this aggregate
* @see #getBean(Class)
*/
- public Collection