Issue #1124 - Fixing up merge issues

+ Making WebSocketServletFactory always load a new
  WebSocketServerFactory
+ Making WebSocketServerFactory need a ServletContext
  to construct it, if appropriate (the WebSocketHandler
  approach doesn't use a ServletContext)
+ NativeWebSocketConfiguration is now a bean of
  ServerContainer
+ Removed WebSocketServletFactory.init(ServletContext) method
+ Renamed WebSocketServletFactory.init() to .start()
+ Renamed WebSocketServletFactory.cleanup() to .stop()
+ CDI & Websocket now works
+ Using a ServletContextListener now works
+ DecoderFactory and EncoderFactory now work
This commit is contained in:
Joakim Erdfelt 2016-11-29 15:46:03 -07:00
parent f54938178e
commit 70247d74d9
16 changed files with 267 additions and 246 deletions

View File

@ -166,6 +166,12 @@ public class DecoderFactory implements Configurable
{ {
LOG.debug("init({})",config); LOG.debug("init({})",config);
} }
if(!containerScope.isRunning())
{
throw new RuntimeException(containerScope.getClass().getName() + " is not running yet");
}
// Instantiate all declared decoders // Instantiate all declared decoders
for (DecoderMetadata metadata : metadatas) for (DecoderMetadata metadata : metadatas)
{ {

View File

@ -59,6 +59,7 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
eventDriverFactory.addImplementation(new JsrServerEndpointImpl()); eventDriverFactory.addImplementation(new JsrServerEndpointImpl());
eventDriverFactory.addImplementation(new JsrServerExtendsEndpointImpl()); eventDriverFactory.addImplementation(new JsrServerExtendsEndpointImpl());
this.configuration.getFactory().addSessionFactory(new JsrSessionFactory(this)); this.configuration.getFactory().addSessionFactory(new JsrSessionFactory(this));
addBean(this.configuration);
} }
public EndpointInstance newClientEndpointInstance(Object endpoint, ServerEndpointConfig config, String path) public EndpointInstance newClientEndpointInstance(Object endpoint, ServerEndpointConfig config, String path)

View File

@ -85,6 +85,8 @@ public class OnPartialTest
URI requestURI = URI.create("ws://localhost/" + id); URI requestURI = URI.create("ws://localhost/" + id);
DummyConnection connection = new DummyConnection(); DummyConnection connection = new DummyConnection();
ClientContainer container = new ClientContainer(); ClientContainer container = new ClientContainer();
container.start();
@SuppressWarnings("resource") @SuppressWarnings("resource")
JsrSession session = new JsrSession(container,id,requestURI,driver,connection); JsrSession session = new JsrSession(container,id,requestURI,driver,connection);
session.setPolicy(policy); session.setPolicy(policy);

View File

@ -67,7 +67,7 @@ public class SessionTrackingTest
serverContainer = WebSocketServerContainerInitializer.configureContext(servletContextHandler); serverContainer = WebSocketServerContainerInitializer.configureContext(servletContextHandler);
serverContainer.addEndpoint(EchoSocket.class); serverContainer.addEndpoint(EchoSocket.class);
wsServerFactory = serverContainer.getBean(WebSocketServerFactory.class); wsServerFactory = serverContainer.getWebSocketServerFactory();
server.start(); server.start();

View File

@ -36,48 +36,54 @@ public interface WebSocketContainerScope
* *
* @return the buffer pool (never null) * @return the buffer pool (never null)
*/ */
public ByteBufferPool getBufferPool(); ByteBufferPool getBufferPool();
/** /**
* Executor in use by the container. * Executor in use by the container.
* *
* @return the Executor in use by the container. * @return the Executor in use by the container.
*/ */
public Executor getExecutor(); Executor getExecutor();
/** /**
* Object Factory used to create objects. * Object Factory used to create objects.
* *
* @return Object Factory used to create instances of objects. * @return Object Factory used to create instances of objects.
*/ */
public DecoratedObjectFactory getObjectFactory(); DecoratedObjectFactory getObjectFactory();
/** /**
* The policy the container is running on. * The policy the container is running on.
* *
* @return the websocket policy * @return the websocket policy
*/ */
public WebSocketPolicy getPolicy(); WebSocketPolicy getPolicy();
/** /**
* The SslContextFactory in use by the container. * The SslContextFactory in use by the container.
* *
* @return the SslContextFactory in use by the container (can be null if no SSL context is defined) * @return the SslContextFactory in use by the container (can be null if no SSL context is defined)
*/ */
public SslContextFactory getSslContextFactory(); SslContextFactory getSslContextFactory();
/**
* Test for if the container has been started.
*
* @return true if container is started and running
*/
boolean isRunning();
/** /**
* A Session has been opened * A Session has been opened
* *
* @param session the session that was opened * @param session the session that was opened
*/ */
public void onSessionOpened(WebSocketSession session); void onSessionOpened(WebSocketSession session);
/** /**
* A Session has been closed * A Session has been closed
* *
* @param session the session that was closed * @param session the session that was closed
*/ */
public void onSessionClosed(WebSocketSession session); void onSessionClosed(WebSocketSession session);
} }

View File

@ -20,6 +20,8 @@ package org.eclipse.jetty.websocket.server;
import java.io.IOException; import java.io.IOException;
import javax.servlet.ServletContext;
import org.eclipse.jetty.http.pathmap.MappedResource; import org.eclipse.jetty.http.pathmap.MappedResource;
import org.eclipse.jetty.http.pathmap.PathMappings; import org.eclipse.jetty.http.pathmap.PathMappings;
import org.eclipse.jetty.http.pathmap.PathSpec; import org.eclipse.jetty.http.pathmap.PathSpec;
@ -44,9 +46,9 @@ public class NativeWebSocketConfiguration extends ContainerLifeCycle implements
private final WebSocketServerFactory factory; private final WebSocketServerFactory factory;
private final PathMappings<WebSocketCreator> mappings = new PathMappings<>(); private final PathMappings<WebSocketCreator> mappings = new PathMappings<>();
public NativeWebSocketConfiguration() public NativeWebSocketConfiguration(ServletContext context)
{ {
this(new WebSocketServerFactory()); this(new WebSocketServerFactory(context));
} }
public NativeWebSocketConfiguration(WebSocketServerFactory webSocketServerFactory) public NativeWebSocketConfiguration(WebSocketServerFactory webSocketServerFactory)

View File

@ -33,7 +33,7 @@ public class NativeWebSocketServletContainerInitializer implements ServletContai
NativeWebSocketConfiguration configuration = (NativeWebSocketConfiguration) context.getAttribute(KEY); NativeWebSocketConfiguration configuration = (NativeWebSocketConfiguration) context.getAttribute(KEY);
if (configuration == null) if (configuration == null)
{ {
configuration = new NativeWebSocketConfiguration(); configuration = new NativeWebSocketConfiguration(context);
context.setAttribute(KEY, configuration); context.setAttribute(KEY, configuration);
} }
return configuration; return configuration;

View File

@ -54,7 +54,8 @@ public abstract class WebSocketHandler extends HandlerWrapper
} }
} }
private final WebSocketServletFactory webSocketFactory; private final ByteBufferPool bufferPool;
private WebSocketServletFactory webSocketFactory;
public WebSocketHandler() public WebSocketHandler()
{ {
@ -63,10 +64,7 @@ public abstract class WebSocketHandler extends HandlerWrapper
public WebSocketHandler(ByteBufferPool bufferPool) public WebSocketHandler(ByteBufferPool bufferPool)
{ {
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); this.bufferPool = bufferPool;
configurePolicy(policy);
webSocketFactory = new WebSocketServerFactory(policy, bufferPool);
addBean(webSocketFactory);
} }
public abstract void configure(WebSocketServletFactory factory); public abstract void configure(WebSocketServletFactory factory);
@ -79,12 +77,18 @@ public abstract class WebSocketHandler extends HandlerWrapper
@Override @Override
protected void doStart() throws Exception protected void doStart() throws Exception
{ {
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
configurePolicy(policy);
webSocketFactory = new WebSocketServerFactory(policy, getServer().getThreadPool(), bufferPool);
addBean(webSocketFactory);
configure(webSocketFactory); configure(webSocketFactory);
super.doStart(); super.doStart();
} }
public WebSocketServletFactory getWebSocketFactory() public WebSocketServletFactory getWebSocketFactory()
{ {
if (!isRunning())
throw new IllegalStateException("Not Started yet");
return webSocketFactory; return webSocketFactory;
} }

View File

@ -28,12 +28,12 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.function.Consumer; import java.util.function.Consumer;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -48,7 +48,6 @@ import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.DecoratedObjectFactory; import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.component.ContainerLifeCycle; import org.eclipse.jetty.util.component.ContainerLifeCycle;
@ -96,29 +95,89 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
private final EventDriverFactory eventDriverFactory; private final EventDriverFactory eventDriverFactory;
private final ByteBufferPool bufferPool; private final ByteBufferPool bufferPool;
private final WebSocketExtensionFactory extensionFactory; private final WebSocketExtensionFactory extensionFactory;
private ServletContext context; // can be null when this factory is used from WebSocketHandler
private Executor executor; private Executor executor;
private List<SessionFactory> sessionFactories; private List<SessionFactory> sessionFactories;
private WebSocketCreator creator; private WebSocketCreator creator;
private List<Class<?>> registeredSocketClasses; private List<Class<?>> registeredSocketClasses;
private DecoratedObjectFactory objectFactory; private DecoratedObjectFactory objectFactory;
public WebSocketServerFactory() public WebSocketServerFactory(ServletContext context)
{ {
this(WebSocketPolicy.newServerPolicy(), new MappedByteBufferPool()); this(context, WebSocketPolicy.newServerPolicy(), new MappedByteBufferPool());
} }
public WebSocketServerFactory(WebSocketPolicy policy) public WebSocketServerFactory(ServletContext context, ByteBufferPool bufferPool)
{ {
this(policy, new MappedByteBufferPool()); this(context, WebSocketPolicy.newServerPolicy(), bufferPool);
} }
public WebSocketServerFactory(ByteBufferPool bufferPool) /**
* Entry point for {@link org.eclipse.jetty.websocket.servlet.WebSocketServletFactory.Loader}
*
* @param context the servlet context
* @param policy the policy to use
*/
public WebSocketServerFactory(ServletContext context, WebSocketPolicy policy)
{ {
this(WebSocketPolicy.newServerPolicy(), bufferPool); this(context, policy, new MappedByteBufferPool());
} }
public WebSocketServerFactory(WebSocketPolicy policy, ByteBufferPool bufferPool) public WebSocketServerFactory(ServletContext context, WebSocketPolicy policy, ByteBufferPool bufferPool)
{ {
Objects.requireNonNull(context, ServletContext.class.getName());
this.context = context;
handshakes.put(HandshakeRFC6455.VERSION, new HandshakeRFC6455());
addBean(scheduler);
addBean(bufferPool);
this.contextClassloader = Thread.currentThread().getContextClassLoader();
this.registeredSocketClasses = new ArrayList<>();
this.defaultPolicy = policy;
this.eventDriverFactory = new EventDriverFactory(defaultPolicy);
this.bufferPool = bufferPool;
this.extensionFactory = new WebSocketExtensionFactory(this);
this.sessionFactories = new ArrayList<>();
this.sessionFactories.add(new WebSocketSessionFactory(this));
this.creator = this;
// Create supportedVersions
List<Integer> versions = new ArrayList<>();
for (int v : handshakes.keySet())
{
versions.add(v);
}
Collections.sort(versions, Collections.reverseOrder()); // newest first
StringBuilder rv = new StringBuilder();
for (int v : versions)
{
if (rv.length() > 0)
{
rv.append(", ");
}
rv.append(v);
}
supportedVersions = rv.toString();
}
/**
* Protected entry point for {@link WebSocketHandler}
*
* @param policy the policy to use
* @param executor the executor to use
* @param bufferPool the buffer pool to use
*/
protected WebSocketServerFactory(WebSocketPolicy policy, Executor executor, ByteBufferPool bufferPool)
{
this.objectFactory = new DecoratedObjectFactory();
this.executor = executor;
handshakes.put(HandshakeRFC6455.VERSION, new HandshakeRFC6455()); handshakes.put(HandshakeRFC6455.VERSION, new HandshakeRFC6455());
addBean(scheduler); addBean(scheduler);
@ -229,22 +288,9 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
} }
@Override @Override
public void cleanup() public WebSocketServletFactory createFactory(ServletContext context, WebSocketPolicy policy)
{ {
try return new WebSocketServerFactory(context, policy, bufferPool);
{
this.stop();
}
catch (Exception e)
{
LOG.warn(e);
}
}
@Override
public WebSocketServletFactory createFactory(WebSocketPolicy policy)
{
return new WebSocketServerFactory(policy, bufferPool);
} }
private WebSocketSession createSession(URI requestURI, EventDriver websocket, LogicalConnection connection) private WebSocketSession createSession(URI requestURI, EventDriver websocket, LogicalConnection connection)
@ -302,10 +348,23 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
@Override @Override
protected void doStart() throws Exception protected void doStart() throws Exception
{ {
if(this.objectFactory == null && context != null)
{
this.objectFactory = (DecoratedObjectFactory) context.getAttribute(DecoratedObjectFactory.ATTR);
if (this.objectFactory == null) if (this.objectFactory == null)
{ {
this.objectFactory = new DecoratedObjectFactory(); throw new RuntimeException("Unable to find required ServletContext attribute: " + DecoratedObjectFactory.ATTR);
} }
}
if(this.executor == null && context != null)
{
ContextHandler contextHandler = ContextHandler.getContextHandler(context);
this.executor = contextHandler.getServer().getThreadPool();
}
Objects.requireNonNull(this.objectFactory, DecoratedObjectFactory.class.getName());
Objects.requireNonNull(this.executor, Executor.class.getName());
super.doStart(); super.doStart();
} }
@ -364,52 +423,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return null; return null;
} }
public void init(ServletContextHandler context) throws ServletException
{
this.objectFactory = (DecoratedObjectFactory)context.getServletContext().getAttribute(DecoratedObjectFactory.ATTR);
if (this.objectFactory == null)
{
this.objectFactory = new DecoratedObjectFactory();
}
this.executor = context.getServer().getThreadPool();
}
@Override
public void init(ServletContext context) throws ServletException
{
// Setup ObjectFactory
this.objectFactory = (DecoratedObjectFactory)context.getAttribute(DecoratedObjectFactory.ATTR);
if (this.objectFactory == null)
{
this.objectFactory = new DecoratedObjectFactory();
}
// Validate Environment
ContextHandler handler = ContextHandler.getContextHandler(context);
if (handler == null)
{
throw new ServletException("Not running on Jetty, WebSocket support unavailable");
}
this.executor = handler.getServer().getThreadPool();
try
{
// start lifecycle
start();
}
catch (ServletException e)
{
throw e;
}
catch (Exception e)
{
throw new ServletException(e);
}
}
@Override @Override
public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response) public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response)
{ {
@ -519,7 +532,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
* @param request The request to upgrade * @param request The request to upgrade
* @param response The response to upgrade * @param response The response to upgrade
* @param driver The websocket handler implementation to use * @param driver The websocket handler implementation to use
* @throws IOException
*/ */
private boolean upgrade(HttpConnection http, ServletUpgradeRequest request, ServletUpgradeResponse response, EventDriver driver) throws IOException private boolean upgrade(HttpConnection http, ServletUpgradeRequest request, ServletUpgradeResponse response, EventDriver driver) throws IOException
{ {

View File

@ -34,7 +34,6 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.pathmap.MappedResource; import org.eclipse.jetty.http.pathmap.MappedResource;
import org.eclipse.jetty.http.pathmap.PathSpec; import org.eclipse.jetty.http.pathmap.PathSpec;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
@ -45,7 +44,6 @@ import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.component.Dumpable;
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.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator; import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@ -55,11 +53,9 @@ import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@ManagedObject("WebSocket Upgrade Filter") @ManagedObject("WebSocket Upgrade Filter")
public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter, MappedWebSocketCreator, Dumpable public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter, MappedWebSocketCreator, Dumpable
{ {
private static final Logger LOG = Log.getLogger(WebSocketUpgradeFilter.class);
public static final String CONTEXT_ATTRIBUTE_KEY = "contextAttributeKey"; public static final String CONTEXT_ATTRIBUTE_KEY = "contextAttributeKey";
public static final String CONFIG_ATTRIBUTE_KEY = "configAttributeKey"; public static final String CONFIG_ATTRIBUTE_KEY = "configAttributeKey";
private static final Logger LOG = Log.getLogger(WebSocketUpgradeFilter.class);
private boolean localMapper;
private boolean localFactory;
public static WebSocketUpgradeFilter configureContext(ServletContextHandler context) throws ServletException public static WebSocketUpgradeFilter configureContext(ServletContextHandler context) throws ServletException
{ {
@ -122,9 +118,9 @@ public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter,
// do nothing // do nothing
} }
public WebSocketUpgradeFilter(WebSocketPolicy policy, ByteBufferPool bufferPool) public WebSocketUpgradeFilter(WebSocketServerFactory factory)
{ {
this(new NativeWebSocketConfiguration(new WebSocketServerFactory(policy, bufferPool))); this(new NativeWebSocketConfiguration(factory));
} }
public WebSocketUpgradeFilter(NativeWebSocketConfiguration configuration) public WebSocketUpgradeFilter(NativeWebSocketConfiguration configuration)

View File

@ -30,20 +30,21 @@ import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper; import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator; import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
public class WebSocketUpgradeHandlerWrapper extends HandlerWrapper implements MappedWebSocketCreator public class WebSocketUpgradeHandlerWrapper extends HandlerWrapper implements MappedWebSocketCreator
{ {
private NativeWebSocketConfiguration configuration; private NativeWebSocketConfiguration configuration;
public WebSocketUpgradeHandlerWrapper() public WebSocketUpgradeHandlerWrapper(ServletContextHandler context)
{ {
this(new MappedByteBufferPool()); this(context, new MappedByteBufferPool());
} }
public WebSocketUpgradeHandlerWrapper(ByteBufferPool bufferPool) public WebSocketUpgradeHandlerWrapper(ServletContextHandler context, ByteBufferPool bufferPool)
{ {
this.configuration = new NativeWebSocketConfiguration(new WebSocketServerFactory(bufferPool)); this.configuration = new NativeWebSocketConfiguration(new WebSocketServerFactory(context.getServletContext(), bufferPool));
} }
@Override @Override

View File

@ -31,7 +31,7 @@ public class InfoContextListener implements WebSocketCreator, ServletContextList
@Override @Override
public void contextInitialized(ServletContextEvent sce) public void contextInitialized(ServletContextEvent sce)
{ {
NativeWebSocketConfiguration configuration = new NativeWebSocketConfiguration(); NativeWebSocketConfiguration configuration = new NativeWebSocketConfiguration(sce.getServletContext());
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024); configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
configuration.addMapping(new ServletPathSpec("/info/*"), this); configuration.addMapping(new ServletPathSpec("/info/*"), this);
sce.getServletContext().setAttribute(NativeWebSocketConfiguration.class.getName(), configuration); sce.getServletContext().setAttribute(NativeWebSocketConfiguration.class.getName(), configuration);

View File

@ -163,7 +163,7 @@ public class WebSocketUpgradeFilterTest
server.setHandler(context); server.setHandler(context);
context.addFilter(WebSocketUpgradeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); context.addFilter(WebSocketUpgradeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
NativeWebSocketConfiguration configuration = new NativeWebSocketConfiguration(); NativeWebSocketConfiguration configuration = new NativeWebSocketConfiguration(context.getServletContext());
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024); configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
configuration.addMapping(new ServletPathSpec("/info/*"), infoCreator); configuration.addMapping(new ServletPathSpec("/info/*"), infoCreator);
context.getServletContext().setAttribute(NativeWebSocketConfiguration.class.getName(), configuration); context.getServletContext().setAttribute(NativeWebSocketConfiguration.class.getName(), configuration);

View File

@ -90,7 +90,14 @@ public abstract class WebSocketServlet extends HttpServlet
@Override @Override
public void destroy() public void destroy()
{ {
factory.cleanup(); try
{
factory.stop();
}
catch (Exception ignore)
{
// ignore;
}
} }
/** /**
@ -127,13 +134,12 @@ public abstract class WebSocketServlet extends HttpServlet
policy.setInputBufferSize(Integer.parseInt(max)); policy.setInputBufferSize(Integer.parseInt(max));
} }
factory = WebSocketServletFactory.Loader.create(policy); ServletContext ctx = getServletContext();
factory = WebSocketServletFactory.Loader.load(ctx, policy);
configure(factory); configure(factory);
ServletContext ctx = getServletContext(); factory.start();
factory.init(ctx);
ctx.setAttribute(WebSocketServletFactory.class.getName(),factory); ctx.setAttribute(WebSocketServletFactory.class.getName(),factory);
} }

View File

@ -19,8 +19,8 @@
package org.eclipse.jetty.websocket.servlet; package org.eclipse.jetty.websocket.servlet;
import java.io.IOException; import java.io.IOException;
import java.util.Iterator; import java.lang.reflect.Constructor;
import java.util.ServiceLoader; import java.lang.reflect.InvocationTargetException;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -35,54 +35,42 @@ import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
*/ */
public interface WebSocketServletFactory public interface WebSocketServletFactory
{ {
public static class Loader class Loader
{ {
private static WebSocketServletFactory INSTANCE; final static String DEFAULT_IMPL = "org.eclipse.jetty.websocket.server.WebSocketServerFactory";
public static WebSocketServletFactory create(WebSocketPolicy policy) throws ClassNotFoundException, InstantiationException, IllegalAccessException public static WebSocketServletFactory load(ServletContext ctx, WebSocketPolicy policy)
{ {
return load().createFactory(policy); try
{
Class<? extends WebSocketServletFactory> wsClazz =
(Class<? extends WebSocketServletFactory>) Class.forName(DEFAULT_IMPL);
Constructor<? extends WebSocketServletFactory> ctor = wsClazz.getDeclaredConstructor(new Class<?>[]{ServletContext.class, WebSocketPolicy.class});
return ctor.newInstance(ctx, policy);
} }
catch (ClassNotFoundException e)
public static WebSocketServletFactory load() throws ClassNotFoundException, InstantiationException, IllegalAccessException
{ {
if (INSTANCE != null) throw new RuntimeException("Unable to load " + DEFAULT_IMPL, e);
{
return INSTANCE;
} }
WebSocketServletFactory baseFactory; catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e)
Iterator<WebSocketServletFactory> factories = ServiceLoader.load(WebSocketServletFactory.class).iterator();
if (factories.hasNext())
{ {
baseFactory = factories.next(); throw new RuntimeException("Unable to instantiate " + DEFAULT_IMPL, e);
} }
else
{
// Load the default class if ServiceLoader mechanism isn't valid in this environment. (such as OSGi)
ClassLoader loader = Thread.currentThread().getContextClassLoader();
@SuppressWarnings("unchecked")
Class<WebSocketServletFactory> wssf = (Class<WebSocketServletFactory>)loader
.loadClass("org.eclipse.jetty.websocket.server.WebSocketServerFactory");
baseFactory = wssf.newInstance();
}
INSTANCE = baseFactory;
return INSTANCE;
} }
} }
public boolean acceptWebSocket(HttpServletRequest request, HttpServletResponse response) throws IOException; boolean acceptWebSocket(HttpServletRequest request, HttpServletResponse response) throws IOException;
public boolean acceptWebSocket(WebSocketCreator creator, HttpServletRequest request, HttpServletResponse response) throws IOException; boolean acceptWebSocket(WebSocketCreator creator, HttpServletRequest request, HttpServletResponse response) throws IOException;
public void cleanup(); void start() throws Exception;
void stop() throws Exception;
public WebSocketServletFactory createFactory(WebSocketPolicy policy); WebSocketServletFactory createFactory(ServletContext context, WebSocketPolicy policy);
public abstract WebSocketCreator getCreator(); WebSocketCreator getCreator();
public abstract ExtensionFactory getExtensionFactory(); ExtensionFactory getExtensionFactory();
/** /**
* Get the base policy in use for WebSockets. * Get the base policy in use for WebSockets.
@ -91,21 +79,18 @@ public interface WebSocketServletFactory
* *
* @return the base policy * @return the base policy
*/ */
public WebSocketPolicy getPolicy(); WebSocketPolicy getPolicy();
public void init(ServletContext servletContext) throws Exception; boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response);
public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response);
/** /**
* Register a websocket class pojo with the default {@link WebSocketCreator}. * Register a websocket class pojo with the default {@link WebSocketCreator}.
* <p> * <p>
* Note: only required if using the default {@link WebSocketCreator} provided by this factory. * Note: only required if using the default {@link WebSocketCreator} provided by this factory.
* *
* @param websocketPojo * @param websocketPojo the class to instantiate for each incoming websocket upgrade request.
* the class to instantiate for each incoming websocket upgrade request.
*/ */
public void register(Class<?> websocketPojo); void register(Class<?> websocketPojo);
public abstract void setCreator(WebSocketCreator creator); void setCreator(WebSocketCreator creator);
} }