separate out resources from the WebSocketMapping

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2019-01-22 11:39:53 +11:00
parent 0f2f1c1e92
commit e1674cf4b6
4 changed files with 100 additions and 54 deletions

View File

@ -22,6 +22,7 @@ import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.websocket.DeploymentException; 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.util.log.Logger;
import org.eclipse.jetty.websocket.core.FrameHandler; import org.eclipse.jetty.websocket.core.FrameHandler;
import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry; 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.core.client.WebSocketCoreClient;
import org.eclipse.jetty.websocket.javax.client.JavaxWebSocketClientContainer; import org.eclipse.jetty.websocket.javax.client.JavaxWebSocketClientContainer;
import org.eclipse.jetty.websocket.javax.common.InvalidWebSocketException; import org.eclipse.jetty.websocket.javax.common.InvalidWebSocketException;
@ -106,7 +108,9 @@ public class JavaxWebSocketServerContainer
// Create the Jetty ServerContainer implementation // Create the Jetty ServerContainer implementation
container = new JavaxWebSocketServerContainer( container = new JavaxWebSocketServerContainer(
WebSocketMapping.ensureMapping(servletContext), httpClient, executor); WebSocketMapping.ensureMapping(servletContext),
WebSocketResources.ensureWebSocketResources(servletContext),
httpClient, executor);
contextHandler.addManaged(container); contextHandler.addManaged(container);
contextHandler.addLifeCycleListener(container); contextHandler.addLifeCycleListener(container);
} }
@ -116,6 +120,7 @@ public class JavaxWebSocketServerContainer
} }
private final WebSocketMapping webSocketMapping; private final WebSocketMapping webSocketMapping;
private final WebSocketResources webSocketResources;
private final JavaxWebSocketServerFrameHandlerFactory frameHandlerFactory; private final JavaxWebSocketServerFrameHandlerFactory frameHandlerFactory;
private final Executor executor; private final Executor executor;
private final FrameHandler.ConfigurationCustomizer customizer = new FrameHandler.ConfigurationCustomizer(); private final FrameHandler.ConfigurationCustomizer customizer = new FrameHandler.ConfigurationCustomizer();
@ -123,12 +128,19 @@ public class JavaxWebSocketServerContainer
private List<Class<?>> deferredEndpointClasses; private List<Class<?>> deferredEndpointClasses;
private List<ServerEndpointConfig> deferredEndpointConfigs; private List<ServerEndpointConfig> deferredEndpointConfigs;
public JavaxWebSocketServerContainer(WebSocketMapping webSocketMapping, HttpClient httpClient, Executor executor)
{
this(webSocketMapping, new WebSocketResources(), httpClient, executor);
}
/** /**
* Main entry point for {@link JavaxWebSocketServletContainerInitializer}. * Main entry point for {@link JavaxWebSocketServletContainerInitializer}.
* @param webSocketMapping the {@link WebSocketMapping} that this container belongs to * @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(() -> super(() ->
{ {
@ -138,6 +150,7 @@ public class JavaxWebSocketServerContainer
return client; return client;
}); });
this.webSocketMapping = webSocketMapping; this.webSocketMapping = webSocketMapping;
this.webSocketResources = webSocketResources;
this.executor = executor; this.executor = executor;
this.frameHandlerFactory = new JavaxWebSocketServerFrameHandlerFactory(this); this.frameHandlerFactory = new JavaxWebSocketServerFrameHandlerFactory(this);
} }
@ -158,7 +171,7 @@ public class JavaxWebSocketServerContainer
@Override @Override
public ByteBufferPool getBufferPool() public ByteBufferPool getBufferPool()
{ {
return this.webSocketMapping.getBufferPool(); return webSocketResources.getBufferPool();
} }
@Override @Override
@ -170,7 +183,7 @@ public class JavaxWebSocketServerContainer
@Override @Override
public WebSocketExtensionRegistry getExtensionRegistry() public WebSocketExtensionRegistry getExtensionRegistry()
{ {
return this.webSocketMapping.getExtensionRegistry(); return webSocketResources.getExtensionRegistry();
} }
@Override @Override
@ -182,7 +195,7 @@ public class JavaxWebSocketServerContainer
@Override @Override
public DecoratedObjectFactory getObjectFactory() public DecoratedObjectFactory getObjectFactory()
{ {
return this.webSocketMapping.getObjectFactory(); return webSocketResources.getObjectFactory();
} }
@Override @Override
@ -276,7 +289,7 @@ public class JavaxWebSocketServerContainer
{ {
frameHandlerFactory.getMetadata(config.getEndpointClass(), config); frameHandlerFactory.getMetadata(config.getEndpointClass(), config);
JavaxWebSocketCreator creator = new JavaxWebSocketCreator(this, config, webSocketMapping JavaxWebSocketCreator creator = new JavaxWebSocketCreator(this, config, webSocketResources
.getExtensionRegistry()); .getExtensionRegistry());

View File

@ -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;
}
}

View File

@ -27,18 +27,20 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.pathmap.*; import org.eclipse.jetty.http.pathmap.MappedResource;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.http.pathmap.PathMappings;
import org.eclipse.jetty.io.MappedByteBufferPool; 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.io.RuntimeIOException;
import org.eclipse.jetty.server.handler.ContextHandler; 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.Dumpable;
import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.core.FrameHandler; 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.Handshaker;
import org.eclipse.jetty.websocket.core.server.Negotiation; import org.eclipse.jetty.websocket.core.server.Negotiation;
import org.eclipse.jetty.websocket.core.server.WebSocketNegotiator; 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); WebSocketMapping mapping = contextHandler.getBean(WebSocketMapping.class);
if (mapping == null) if (mapping == null)
{ {
mapping = new WebSocketMapping(); mapping = new WebSocketMapping(WebSocketResources.ensureWebSocketResources(servletContext));
mapping.setContextClassLoader(servletContext.getClassLoader());
contextHandler.addBean(mapping); contextHandler.addBean(mapping);
contextHandler.addLifeCycleListener(mapping); contextHandler.addLifeCycleListener(mapping);
} }
@ -77,23 +78,17 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener
} }
private final PathMappings<Negotiator> mappings = new PathMappings<>(); private final PathMappings<Negotiator> mappings = new PathMappings<>();
private final WebSocketResources resources;
private final Handshaker handshaker = Handshaker.newInstance(); private final Handshaker handshaker = Handshaker.newInstance();
private DecoratedObjectFactory objectFactory;
private ClassLoader contextClassLoader;
private WebSocketExtensionRegistry extensionRegistry;
private ByteBufferPool bufferPool;
public WebSocketMapping() 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.resources = resources;
this.objectFactory = objectFactory;
this.bufferPool = bufferPool;
} }
@Override @Override
@ -152,31 +147,6 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener
Dumpable.dumpObjects(out, indent, this, mappings); 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. * 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) public Negotiator(WebSocketCreator creator, FrameHandlerFactory factory, FrameHandler.Customizer customizer)
{ {
super(WebSocketMapping.this.getExtensionRegistry(), WebSocketMapping.this.getObjectFactory(), super(resources.getExtensionRegistry(), resources.getObjectFactory(), resources.getBufferPool(), customizer);
WebSocketMapping.this.getBufferPool(),
customizer);
this.creator = creator; this.creator = creator;
this.factory = factory; this.factory = factory;
} }
@ -291,10 +259,13 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener
@Override @Override
public FrameHandler negotiate(Negotiation negotiation) public FrameHandler negotiate(Negotiation negotiation)
{ {
//TODO what about a null context
ClassLoader loader = negotiation.getRequest().getServletContext().getClassLoader();
ClassLoader old = Thread.currentThread().getContextClassLoader(); ClassLoader old = Thread.currentThread().getContextClassLoader();
try try
{ {
Thread.currentThread().setContextClassLoader(getContextClassloader()); Thread.currentThread().setContextClassLoader(loader);
ServletUpgradeRequest upgradeRequest = new ServletUpgradeRequest(negotiation); ServletUpgradeRequest upgradeRequest = new ServletUpgradeRequest(negotiation);
ServletUpgradeResponse upgradeResponse = new ServletUpgradeResponse(negotiation); ServletUpgradeResponse upgradeResponse = new ServletUpgradeResponse(negotiation);

View File

@ -34,6 +34,7 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.core.FrameHandler; import org.eclipse.jetty.websocket.core.FrameHandler;
import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry; 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. * 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 final CustomizedWebSocketServletFactory customizer = new CustomizedWebSocketServletFactory();
private WebSocketMapping mapping; private WebSocketMapping mapping;
private WebSocketResources resources;
/** /**
* Configure the WebSocketServletFactory for this servlet instance by setting default * Configure the WebSocketServletFactory for this servlet instance by setting default
@ -112,6 +114,7 @@ public abstract class WebSocketServlet extends HttpServlet
ServletContext servletContext = getServletContext(); ServletContext servletContext = getServletContext();
mapping = WebSocketMapping.ensureMapping(servletContext); mapping = WebSocketMapping.ensureMapping(servletContext);
resources = WebSocketResources.ensureWebSocketResources(servletContext);
String max = getInitParameter("maxIdleTime"); String max = getInitParameter("maxIdleTime");
if (max != null) if (max != null)
@ -176,7 +179,7 @@ public abstract class WebSocketServlet extends HttpServlet
{ {
public WebSocketExtensionRegistry getExtensionRegistry() public WebSocketExtensionRegistry getExtensionRegistry()
{ {
return mapping.getExtensionRegistry(); return resources.getExtensionRegistry();
} }
@Override @Override