diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java index f40f633fb61..67cf9ad6c5e 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java @@ -146,7 +146,6 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit if(isEnabledViaContext(context.getServletContext(), ADD_DYNAMIC_FILTER_KEY, true)) { WebSocketUpgradeFilter.configureContext(context); - NativeWebSocketServletContainerInitializer.getDefaultFrom(context.getServletContext()); } return jettyContainer; diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java index 49f9b5f6cd4..a0c32eee7b0 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java @@ -85,9 +85,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc private final ClassLoader contextClassloader; private final Map handshakes = new HashMap<>(); - /** - * Have the factory maintain 1 and only 1 scheduler. All connections share this scheduler. - */ + // TODO: obtain shared (per server scheduler, somehow) private final Scheduler scheduler = new ScheduledExecutorScheduler(); private final List listeners = new CopyOnWriteArrayList<>(); private final String supportedVersions; @@ -95,12 +93,12 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc private final EventDriverFactory eventDriverFactory; private final ByteBufferPool bufferPool; private final WebSocketExtensionFactory extensionFactory; - private ServletContext context; // can be null when this factory is used from WebSocketHandler + private final ServletContext context; // can be null when this factory is used from WebSocketHandler + private final List sessionFactories = new ArrayList<>(); + private final List> registeredSocketClasses = new ArrayList<>(); private Executor executor; - private List sessionFactories; - private WebSocketCreator creator; - private List> registeredSocketClasses; private DecoratedObjectFactory objectFactory; + private WebSocketCreator creator; public WebSocketServerFactory(ServletContext context) { @@ -125,45 +123,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc 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 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(); + this(Objects.requireNonNull(context, ServletContext.class.getName()), policy, null, null, bufferPool); } /** @@ -175,7 +135,13 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc */ protected WebSocketServerFactory(WebSocketPolicy policy, Executor executor, ByteBufferPool bufferPool) { - this.objectFactory = new DecoratedObjectFactory(); + this(null, policy, new DecoratedObjectFactory(), executor, bufferPool); + } + + private WebSocketServerFactory(ServletContext context, WebSocketPolicy policy, DecoratedObjectFactory objectFactory, Executor executor, ByteBufferPool bufferPool) + { + this.context = context; + this.objectFactory = objectFactory; this.executor = executor; handshakes.put(HandshakeRFC6455.VERSION, new HandshakeRFC6455()); @@ -185,14 +151,11 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc 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; @@ -287,12 +250,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc this.sessionFactories.add(sessionFactory); } - @Override - public WebSocketServletFactory createFactory(ServletContext context, WebSocketPolicy policy) - { - return new WebSocketServerFactory(context, policy, bufferPool); - } - private WebSocketSession createSession(URI requestURI, EventDriver websocket, LogicalConnection connection) { if (websocket == null) @@ -353,7 +310,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc this.objectFactory = (DecoratedObjectFactory) context.getAttribute(DecoratedObjectFactory.ATTR); if (this.objectFactory == null) { - throw new RuntimeException("Unable to find required ServletContext attribute: " + DecoratedObjectFactory.ATTR); + throw new IllegalStateException("Unable to find required ServletContext attribute: " + DecoratedObjectFactory.ATTR); } } diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java index 039ce962506..85f97b3b52e 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java @@ -39,7 +39,6 @@ import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedObject; -import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.ContainerLifeCycle; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.log.Log; @@ -51,7 +50,7 @@ import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; * Inline Servlet Filter to capture WebSocket upgrade requests and perform path mappings to {@link WebSocketCreator} objects. */ @ManagedObject("WebSocket Upgrade Filter") -public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter, MappedWebSocketCreator, Dumpable +public class WebSocketUpgradeFilter implements Filter, MappedWebSocketCreator, Dumpable { private static final Logger LOG = Log.getLogger(WebSocketUpgradeFilter.class); public static final String CONTEXT_ATTRIBUTE_KEY = "contextAttributeKey"; @@ -111,6 +110,7 @@ public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter, } private NativeWebSocketConfiguration configuration; + private boolean localConfiguration = false; private boolean alreadySetToAttribute = false; public WebSocketUpgradeFilter() @@ -150,7 +150,10 @@ public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter, try { alreadySetToAttribute = false; - configuration.stop(); + if(localConfiguration) + { + configuration.stop(); + } } catch (Exception e) { @@ -310,7 +313,11 @@ public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter, } } - this.configuration.start(); + if(!this.configuration.isRunning()) + { + localConfiguration = true; + this.configuration.start(); + } String max = config.getInitParameter("maxIdleTime"); if (max != null) diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/InfoContextAltAttributeListener.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/InfoContextAltAttributeListener.java new file mode 100644 index 00000000000..09b5da07ca2 --- /dev/null +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/InfoContextAltAttributeListener.java @@ -0,0 +1,52 @@ +// +// ======================================================================== +// Copyright (c) 1995-2016 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.websocket.server; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.eclipse.jetty.http.pathmap.ServletPathSpec; +import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; +import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; +import org.eclipse.jetty.websocket.servlet.WebSocketCreator; + +public class InfoContextAltAttributeListener implements WebSocketCreator, ServletContextListener +{ + private static final String ATTR = "alt.config"; + + @Override + public void contextInitialized(ServletContextEvent sce) + { + NativeWebSocketConfiguration configuration = new NativeWebSocketConfiguration(sce.getServletContext()); + configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024); + configuration.addMapping(new ServletPathSpec("/info/*"), this); + sce.getServletContext().setAttribute(ATTR, configuration); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) + { + } + + @Override + public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp) + { + return new InfoSocket(); + } +} diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilterTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilterTest.java index f08e417ef63..fabffcc3405 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilterTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilterTest.java @@ -208,10 +208,10 @@ public class WebSocketUpgradeFilterTest File testDir = MavenTestingUtils.getTargetTestingDir("WSUF-webxml"); WSServer server = new WSServer(testDir, "/"); - + + server.copyWebInf("wsuf-config-via-listener.xml"); server.copyClass(InfoSocket.class); server.copyClass(InfoContextAttributeListener.class); - server.copyWebInf("wsuf-config-via-listener.xml"); server.start(); WebAppContext webapp = server.createWebAppContext(); @@ -231,10 +231,33 @@ public class WebSocketUpgradeFilterTest File testDir = MavenTestingUtils.getTargetTestingDir("WSUF-webxml"); WSServer server = new WSServer(testDir, "/"); - + + server.copyWebInf("wsuf-config-via-servlet-init.xml"); server.copyClass(InfoSocket.class); server.copyClass(InfoServlet.class); - server.copyWebInf("wsuf-config-via-servlet-init.xml"); + server.start(); + + WebAppContext webapp = server.createWebAppContext(); + server.deployWebapp(webapp); + + return server.getServer(); + } + }}); + + // xml based, wsuf, on alternate url-pattern and config attribute location + + cases.add(new Object[]{"wsuf/WebAppContext/web.xml/ServletContextListener/alt-config", new ServerProvider() + { + @Override + public Server newServer() throws Exception + { + File testDir = MavenTestingUtils.getTargetTestingDir("WSUF-webxml"); + + WSServer server = new WSServer(testDir, "/"); + + server.copyWebInf("wsuf-alt-config-via-listener.xml"); + server.copyClass(InfoSocket.class); + server.copyClass(InfoContextAltAttributeListener.class); server.start(); WebAppContext webapp = server.createWebAppContext(); diff --git a/jetty-websocket/websocket-server/src/test/resources/wsuf-alt-config-via-listener.xml b/jetty-websocket/websocket-server/src/test/resources/wsuf-alt-config-via-listener.xml new file mode 100644 index 00000000000..4321a5cb0f6 --- /dev/null +++ b/jetty-websocket/websocket-server/src/test/resources/wsuf-alt-config-via-listener.xml @@ -0,0 +1,26 @@ + + + + + org.eclipse.jetty.websocket.server.InfoContextAltAttributeListener + + + + wsuf-alt + org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter + + configAttributeKey + alt.config + + + + + wsuf-alt + /info/* + + diff --git a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServletFactory.java b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServletFactory.java index c7f6de5d382..72c14782346 100644 --- a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServletFactory.java +++ b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServletFactory.java @@ -66,8 +66,6 @@ public interface WebSocketServletFactory void start() throws Exception; void stop() throws Exception; - WebSocketServletFactory createFactory(ServletContext context, WebSocketPolicy policy); - WebSocketCreator getCreator(); ExtensionFactory getExtensionFactory();