diff --git a/jetty-websocket/javax-websocket-server/src/main/java/org/eclipse/jetty/websocket/javax/server/JavaxWebSocketServerContainer.java b/jetty-websocket/javax-websocket-server/src/main/java/org/eclipse/jetty/websocket/javax/server/JavaxWebSocketServerContainer.java index 9ecab9976d1..22e12c6c6f7 100644 --- a/jetty-websocket/javax-websocket-server/src/main/java/org/eclipse/jetty/websocket/javax/server/JavaxWebSocketServerContainer.java +++ b/jetty-websocket/javax-websocket-server/src/main/java/org/eclipse/jetty/websocket/javax/server/JavaxWebSocketServerContainer.java @@ -22,6 +22,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; + import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.websocket.DeploymentException; @@ -44,6 +45,7 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.core.FrameHandler; import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry; +import org.eclipse.jetty.websocket.core.WebSocketResources; import org.eclipse.jetty.websocket.core.client.WebSocketCoreClient; import org.eclipse.jetty.websocket.javax.client.JavaxWebSocketClientContainer; import org.eclipse.jetty.websocket.javax.common.InvalidWebSocketException; @@ -106,7 +108,9 @@ public class JavaxWebSocketServerContainer // Create the Jetty ServerContainer implementation container = new JavaxWebSocketServerContainer( - WebSocketMapping.ensureMapping(servletContext), httpClient, executor); + WebSocketMapping.ensureMapping(servletContext), + WebSocketResources.ensureWebSocketResources(servletContext), + httpClient, executor); contextHandler.addManaged(container); contextHandler.addLifeCycleListener(container); } @@ -116,6 +120,7 @@ public class JavaxWebSocketServerContainer } private final WebSocketMapping webSocketMapping; + private final WebSocketResources webSocketResources; private final JavaxWebSocketServerFrameHandlerFactory frameHandlerFactory; private final Executor executor; private final FrameHandler.ConfigurationCustomizer customizer = new FrameHandler.ConfigurationCustomizer(); @@ -123,12 +128,19 @@ public class JavaxWebSocketServerContainer private List> deferredEndpointClasses; private List deferredEndpointConfigs; + + public JavaxWebSocketServerContainer(WebSocketMapping webSocketMapping, HttpClient httpClient, Executor executor) + { + this(webSocketMapping, new WebSocketResources(), httpClient, executor); + } + /** * Main entry point for {@link JavaxWebSocketServletContainerInitializer}. * @param webSocketMapping the {@link WebSocketMapping} that this container belongs to - * @param httpClient the {@link HttpClient} instance to use + * @param webSocketResources the {@link WebSocketResources} instance to use + * @param httpClient the {@link HttpClient} instance to use */ - public JavaxWebSocketServerContainer(WebSocketMapping webSocketMapping, HttpClient httpClient, Executor executor) + public JavaxWebSocketServerContainer(WebSocketMapping webSocketMapping, WebSocketResources webSocketResources, HttpClient httpClient, Executor executor) { super(() -> { @@ -138,6 +150,7 @@ public class JavaxWebSocketServerContainer return client; }); this.webSocketMapping = webSocketMapping; + this.webSocketResources = webSocketResources; this.executor = executor; this.frameHandlerFactory = new JavaxWebSocketServerFrameHandlerFactory(this); } @@ -158,7 +171,7 @@ public class JavaxWebSocketServerContainer @Override public ByteBufferPool getBufferPool() { - return this.webSocketMapping.getBufferPool(); + return webSocketResources.getBufferPool(); } @Override @@ -170,7 +183,7 @@ public class JavaxWebSocketServerContainer @Override public WebSocketExtensionRegistry getExtensionRegistry() { - return this.webSocketMapping.getExtensionRegistry(); + return webSocketResources.getExtensionRegistry(); } @Override @@ -182,7 +195,7 @@ public class JavaxWebSocketServerContainer @Override public DecoratedObjectFactory getObjectFactory() { - return this.webSocketMapping.getObjectFactory(); + return webSocketResources.getObjectFactory(); } @Override @@ -276,7 +289,7 @@ public class JavaxWebSocketServerContainer { frameHandlerFactory.getMetadata(config.getEndpointClass(), config); - JavaxWebSocketCreator creator = new JavaxWebSocketCreator(this, config, webSocketMapping + JavaxWebSocketCreator creator = new JavaxWebSocketCreator(this, config, webSocketResources .getExtensionRegistry()); diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/WebSocketResources.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/WebSocketResources.java new file mode 100644 index 00000000000..4e07a04f34a --- /dev/null +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/WebSocketResources.java @@ -0,0 +1,59 @@ +package org.eclipse.jetty.websocket.core; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.io.MappedByteBufferPool; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.util.DecoratedObjectFactory; + +public class WebSocketResources +{ + public static WebSocketResources ensureWebSocketResources(ServletContext servletContext) throws ServletException + { + ContextHandler contextHandler = ContextHandler.getContextHandler(servletContext); + + // Ensure a mapping exists + WebSocketResources resources = contextHandler.getBean(WebSocketResources.class); + if (resources == null) + { + resources = new WebSocketResources(); + contextHandler.addBean(resources); + } + + return resources; + } + + public WebSocketResources() + { + this(new WebSocketExtensionRegistry(), new DecoratedObjectFactory(), new MappedByteBufferPool()); + } + + public WebSocketResources(WebSocketExtensionRegistry extensionRegistry, DecoratedObjectFactory objectFactory, ByteBufferPool bufferPool) + { + this.extensionRegistry = extensionRegistry; + this.objectFactory = objectFactory; + this.bufferPool = bufferPool; + } + + private DecoratedObjectFactory objectFactory; + private WebSocketExtensionRegistry extensionRegistry; + private ByteBufferPool bufferPool; + + + public ByteBufferPool getBufferPool() + { + return bufferPool; + } + + public WebSocketExtensionRegistry getExtensionRegistry() + { + return extensionRegistry; + } + + public DecoratedObjectFactory getObjectFactory() + { + return objectFactory; + } +} \ No newline at end of file diff --git a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketMapping.java b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketMapping.java index 8a484622c98..82c0550bda8 100644 --- a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketMapping.java +++ b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketMapping.java @@ -27,18 +27,20 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.pathmap.*; -import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.io.MappedByteBufferPool; +import org.eclipse.jetty.http.pathmap.MappedResource; +import org.eclipse.jetty.http.pathmap.PathMappings; +import org.eclipse.jetty.http.pathmap.PathSpec; +import org.eclipse.jetty.http.pathmap.RegexPathSpec; +import org.eclipse.jetty.http.pathmap.ServletPathSpec; +import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec; import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.server.handler.ContextHandler; -import org.eclipse.jetty.util.DecoratedObjectFactory; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.core.FrameHandler; -import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry; +import org.eclipse.jetty.websocket.core.WebSocketResources; import org.eclipse.jetty.websocket.core.server.Handshaker; import org.eclipse.jetty.websocket.core.server.Negotiation; import org.eclipse.jetty.websocket.core.server.WebSocketNegotiator; @@ -67,8 +69,7 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener WebSocketMapping mapping = contextHandler.getBean(WebSocketMapping.class); if (mapping == null) { - mapping = new WebSocketMapping(); - mapping.setContextClassLoader(servletContext.getClassLoader()); + mapping = new WebSocketMapping(WebSocketResources.ensureWebSocketResources(servletContext)); contextHandler.addBean(mapping); contextHandler.addLifeCycleListener(mapping); } @@ -77,23 +78,17 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener } private final PathMappings mappings = new PathMappings<>(); + private final WebSocketResources resources; private final Handshaker handshaker = Handshaker.newInstance(); - private DecoratedObjectFactory objectFactory; - private ClassLoader contextClassLoader; - private WebSocketExtensionRegistry extensionRegistry; - private ByteBufferPool bufferPool; - public WebSocketMapping() { - this(new WebSocketExtensionRegistry(), new DecoratedObjectFactory(), new MappedByteBufferPool()); + this(new WebSocketResources()); } - public WebSocketMapping(WebSocketExtensionRegistry extensionRegistry, DecoratedObjectFactory objectFactory, ByteBufferPool bufferPool) + public WebSocketMapping(WebSocketResources resources) { - this.extensionRegistry = extensionRegistry; - this.objectFactory = objectFactory; - this.bufferPool = bufferPool; + this.resources = resources; } @Override @@ -152,31 +147,6 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener Dumpable.dumpObjects(out, indent, this, mappings); } - public ByteBufferPool getBufferPool() - { - return bufferPool; - } - - public void setContextClassLoader(ClassLoader classLoader) - { - this.contextClassLoader = classLoader; - } - - public ClassLoader getContextClassloader() - { - return contextClassLoader; - } - - public WebSocketExtensionRegistry getExtensionRegistry() - { - return this.extensionRegistry; - } - - public DecoratedObjectFactory getObjectFactory() - { - return this.objectFactory; - } - /** * Get the matching {@link MappedResource} for the provided target. * @@ -275,9 +245,7 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener public Negotiator(WebSocketCreator creator, FrameHandlerFactory factory, FrameHandler.Customizer customizer) { - super(WebSocketMapping.this.getExtensionRegistry(), WebSocketMapping.this.getObjectFactory(), - WebSocketMapping.this.getBufferPool(), - customizer); + super(resources.getExtensionRegistry(), resources.getObjectFactory(), resources.getBufferPool(), customizer); this.creator = creator; this.factory = factory; } @@ -291,10 +259,13 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener @Override public FrameHandler negotiate(Negotiation negotiation) { + //TODO what about a null context + ClassLoader loader = negotiation.getRequest().getServletContext().getClassLoader(); ClassLoader old = Thread.currentThread().getContextClassLoader(); + try { - Thread.currentThread().setContextClassLoader(getContextClassloader()); + Thread.currentThread().setContextClassLoader(loader); ServletUpgradeRequest upgradeRequest = new ServletUpgradeRequest(negotiation); ServletUpgradeResponse upgradeResponse = new ServletUpgradeResponse(negotiation); diff --git a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServlet.java b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServlet.java index 47dfb5c8c33..1155fa40f86 100644 --- a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServlet.java +++ b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServlet.java @@ -34,6 +34,7 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.core.FrameHandler; import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry; +import org.eclipse.jetty.websocket.core.WebSocketResources; /** * Abstract Servlet used to bridge the Servlet API to the WebSocket API. @@ -94,6 +95,7 @@ public abstract class WebSocketServlet extends HttpServlet private final CustomizedWebSocketServletFactory customizer = new CustomizedWebSocketServletFactory(); private WebSocketMapping mapping; + private WebSocketResources resources; /** * Configure the WebSocketServletFactory for this servlet instance by setting default @@ -112,6 +114,7 @@ public abstract class WebSocketServlet extends HttpServlet ServletContext servletContext = getServletContext(); mapping = WebSocketMapping.ensureMapping(servletContext); + resources = WebSocketResources.ensureWebSocketResources(servletContext); String max = getInitParameter("maxIdleTime"); if (max != null) @@ -176,7 +179,7 @@ public abstract class WebSocketServlet extends HttpServlet { public WebSocketExtensionRegistry getExtensionRegistry() { - return mapping.getExtensionRegistry(); + return resources.getExtensionRegistry(); } @Override