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 1b8ef91a8e2..8ec0ca5a17d 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
@@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.jsr356.server.deploy;
import java.util.HashSet;
import java.util.Set;
+
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
@@ -30,12 +31,18 @@ import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
+import org.eclipse.jetty.io.ByteBufferPool;
+import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
+import org.eclipse.jetty.websocket.server.DefaultMappedWebSocketCreator;
+import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
+import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
@HandlesTypes(
@@ -43,28 +50,87 @@ import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
public class WebSocketServerContainerInitializer implements ServletContainerInitializer
{
public static final String ENABLE_KEY = "org.eclipse.jetty.websocket.jsr356";
+ public static final String ADD_DYNAMIC_FILTER_KEY = "org.eclipse.jetty.websocket.jsr356.addDynamicFilter";
private static final Logger LOG = Log.getLogger(WebSocketServerContainerInitializer.class);
-
+
/**
- * Jetty Native approach.
- *
- * Note: this will add the Upgrade filter to the existing list, with no regard for order. It will just be tacked onto the end of the list.
+ * Test a ServletContext for {@code init-param} or {@code attribute} at {@code keyName} for
+ * true or false setting that determines if the specified feature is enabled (or not).
+ *
+ * @param context the context to search
+ * @param keyName the key name
+ * @param defValue the default value, if the value is not specified in the context
+ * @return the value for the feature key
+ */
+ public static boolean isEnabledViaContext(ServletContext context, String keyName, boolean defValue)
+ {
+ // Try context parameters first
+ String cp = context.getInitParameter(keyName);
+
+ if(cp != null)
+ {
+ if (TypeUtil.isTrue(cp))
+ {
+ return true;
+ }
+
+ if (TypeUtil.isFalse(cp))
+ {
+ return false;
+ }
+
+ return defValue;
+ }
+
+ // Next, try attribute on context
+ Object enable = context.getAttribute(ENABLE_KEY);
+
+ if(enable != null)
+ {
+ if (TypeUtil.isTrue(enable))
+ {
+ return true;
+ }
+
+ if (TypeUtil.isFalse(enable))
+ {
+ return false;
+ }
+ }
+
+ return defValue;
+ }
+
+ /**
+ * Embedded Jetty approach for non-bytecode scanning.
*/
public static ServerContainer configureContext(ServletContextHandler context) throws ServletException
{
- // Create Filter
- WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context);
+ // Create Basic components
+ WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
+ ByteBufferPool bufferPool = new MappedByteBufferPool();
+ MappedWebSocketCreator creator = new DefaultMappedWebSocketCreator();
+ WebSocketServerFactory factory = new WebSocketServerFactory(policy, bufferPool);
// Create the Jetty ServerContainer implementation
- ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),context.getServer().getThreadPool());
+ ServerContainer jettyContainer = new ServerContainer(creator,factory,context.getServer().getThreadPool());
context.addBean(jettyContainer);
+
+ context.setAttribute(WebSocketUpgradeFilter.CREATOR_KEY, creator);
+ context.setAttribute(WebSocketUpgradeFilter.FACTORY_KEY, factory);
// Store a reference to the ServerContainer per javax.websocket spec 1.0 final section 6.4 Programmatic Server Deployment
context.setAttribute(javax.websocket.server.ServerContainer.class.getName(),jettyContainer);
-
+
+ // Create Filter
+ if(isEnabledViaContext(context.getServletContext(), ADD_DYNAMIC_FILTER_KEY, true))
+ {
+ WebSocketUpgradeFilter.configureContext(context);
+ }
+
return jettyContainer;
}
-
+
/**
* @deprecated use {@link #configureContext(ServletContextHandler)} instead
*/
@@ -74,56 +140,10 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
return configureContext(jettyContext);
}
- private boolean isEnabled(Set> c, ServletContext context)
- {
- // Try context parameters first
- String cp = context.getInitParameter(ENABLE_KEY);
- if(TypeUtil.isTrue(cp))
- {
- // forced on
- return true;
- }
-
- if(TypeUtil.isFalse(cp))
- {
- // forced off
- LOG.warn("JSR-356 support disabled via parameter on context {} - {}",context.getContextPath(),context);
- return false;
- }
-
- // Next, try attribute on context
- Object enable = context.getAttribute(ENABLE_KEY);
-
- if(TypeUtil.isTrue(enable))
- {
- // forced on
- return true;
- }
-
- if (TypeUtil.isFalse(enable))
- {
- // forced off
- LOG.warn("JSR-356 support disabled via attribute on context {} - {}",context.getContextPath(),context);
- return false;
- }
-
- // if not forced on or off, determine behavior based on annotations.
- if (c.isEmpty())
- {
- if (LOG.isDebugEnabled())
- {
- LOG.debug("No JSR-356 annotations or interfaces discovered. JSR-356 support disabled",context.getContextPath(),context);
- }
- return false;
- }
-
- return true;
- }
-
@Override
public void onStartup(Set> c, ServletContext context) throws ServletException
{
- if(!isEnabled(c,context))
+ if(!isEnabledViaContext(context, ENABLE_KEY, true))
{
return;
}
@@ -146,18 +166,27 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
try
{
Thread.currentThread().setContextClassLoader(context.getClassLoader());
-
+
// Create the Jetty ServerContainer implementation
ServerContainer jettyContainer = configureContext(jettyContext);
// Store a reference to the ServerContainer per javax.websocket spec 1.0 final section 6.4 Programmatic Server Deployment
context.setAttribute(javax.websocket.server.ServerContainer.class.getName(),jettyContainer);
+ if (c.isEmpty())
+ {
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("No JSR-356 annotations or interfaces discovered");
+ }
+ return;
+ }
+
if (LOG.isDebugEnabled())
{
LOG.debug("Found {} classes",c.size());
}
-
+
// Now process the incoming classes
Set> discoveredExtendedEndpoints = new HashSet<>();
Set> discoveredAnnotatedEndpoints = new HashSet<>();
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/AltFilterTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/AltFilterTest.java
new file mode 100644
index 00000000000..6c0025e0e18
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/AltFilterTest.java
@@ -0,0 +1,97 @@
+//
+// ========================================================================
+// 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.jsr356.server;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+import java.net.URI;
+import java.util.Queue;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.toolchain.test.TestingDir;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.websocket.api.Session;
+import org.eclipse.jetty.websocket.client.WebSocketClient;
+import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule;
+import org.eclipse.jetty.websocket.jsr356.server.samples.echo.BasicEchoSocket;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ * Testing the use of an alternate {@link org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter}
+ * defined in the WEB-INF/web.xml
+ */
+public class AltFilterTest
+{
+ @Rule
+ public TestingDir testdir = new TestingDir();
+
+ @Rule
+ public LeakTrackingBufferPoolRule bufferPool = new LeakTrackingBufferPoolRule("Test");
+
+ @Test
+ public void testEcho() throws Exception
+ {
+ WSServer wsb = new WSServer(testdir,"app");
+ wsb.copyWebInf("alt-filter-web.xml");
+ // the endpoint (extends javax.websocket.Endpoint)
+ wsb.copyClass(BasicEchoSocket.class);
+
+ try
+ {
+ wsb.start();
+ URI uri = wsb.getServerBaseURI();
+
+ WebAppContext webapp = wsb.createWebAppContext();
+ wsb.deployWebapp(webapp);
+
+ FilterHolder filterWebXml = webapp.getServletHandler().getFilter("wsuf-test");
+ assertThat("Filter[wsuf-test]", filterWebXml, notNullValue());
+
+ FilterHolder filterSCI = webapp.getServletHandler().getFilter("Jetty_WebSocketUpgradeFilter");
+ assertThat("Filter[Jetty_WebSocketUpgradeFilter]", filterSCI, nullValue());
+
+ WebSocketClient client = new WebSocketClient(bufferPool);
+ try
+ {
+ client.start();
+ JettyEchoSocket clientEcho = new JettyEchoSocket();
+ Future future = client.connect(clientEcho,uri.resolve("echo"));
+ // wait for connect
+ future.get(1,TimeUnit.SECONDS);
+ clientEcho.sendMessage("Hello Echo");
+ Queue msgs = clientEcho.awaitMessages(1);
+ Assert.assertEquals("Expected message","Hello Echo",msgs.poll());
+ }
+ finally
+ {
+ client.stop();
+ }
+ }
+ finally
+ {
+ wsb.stop();
+ }
+ }
+}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ExtensionStackProcessingTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ExtensionStackProcessingTest.java
index a14daef82e3..89e0498914d 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ExtensionStackProcessingTest.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ExtensionStackProcessingTest.java
@@ -58,21 +58,18 @@ public class ExtensionStackProcessingTest
{
private Server server;
private ServerConnector connector;
- private ExtensionFactory serverExtensionFactory;
private WebSocketContainer client;
-
+ private ServletContextHandler servletContextHandler;
+
@Before
public void prepare() throws Exception
{
server = new Server();
connector = new ServerConnector(server);
server.addConnector(connector);
-
- ServletContextHandler context = new ServletContextHandler(server, "/", true, false);
- ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
-
- WebSocketUpgradeFilter filter = (WebSocketUpgradeFilter)context.getAttribute(WebSocketUpgradeFilter.class.getName());
- serverExtensionFactory = filter.getFactory().getExtensionFactory();
+
+ servletContextHandler = new ServletContextHandler(server, "/", true, false);
+ ServerContainer container = WebSocketServerContainerInitializer.configureContext(servletContextHandler);
ServerEndpointConfig config = ServerEndpointConfig.Builder.create(BasicEchoEndpoint.class, "/").build();
container.addEndpoint(config);
@@ -88,11 +85,18 @@ public class ExtensionStackProcessingTest
{
server.stop();
}
+
+ private void assumeDeflateFrameAvailable()
+ {
+ WebSocketUpgradeFilter filter = (WebSocketUpgradeFilter)servletContextHandler.getAttribute(WebSocketUpgradeFilter.class.getName());
+ ExtensionFactory serverExtensionFactory = filter.getFactory().getExtensionFactory();
+ Assume.assumeTrue("Server has permessage-deflate extension registered",serverExtensionFactory.isAvailable("permessage-deflate"));
+ }
@Test
public void testDeflateFrameExtension() throws Exception
{
- Assume.assumeTrue("Server has deflate-frame extension registered",serverExtensionFactory.isAvailable("deflate-frame"));
+ assumeDeflateFrameAvailable();
ClientEndpointConfig config = ClientEndpointConfig.Builder.create()
.extensions(Arrays.asList(new JsrExtension("deflate-frame")))
@@ -140,7 +144,7 @@ public class ExtensionStackProcessingTest
@Test
public void testPerMessageDeflateExtension() throws Exception
{
- Assume.assumeTrue("Server has permessage-deflate extension registered",serverExtensionFactory.isAvailable("permessage-deflate"));
+ assumeDeflateFrameAvailable();
ClientEndpointConfig config = ClientEndpointConfig.Builder.create()
.extensions(Arrays.asList(new JsrExtension("permessage-deflate")))
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/WSServer.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/WSServer.java
index e974ea7e152..ccf65963701 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/WSServer.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/WSServer.java
@@ -18,6 +18,8 @@
package org.eclipse.jetty.websocket.jsr356.server;
+import static org.hamcrest.Matchers.notNullValue;
+
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
@@ -47,8 +49,6 @@ import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
import org.junit.Assert;
-import static org.hamcrest.Matchers.notNullValue;
-
/**
* Utility to build out exploded directory WebApps, in the /target/tests/ directory, for testing out servers that use javax.websocket endpoints.
*
@@ -151,6 +151,11 @@ public class WSServer
{
return serverUri;
}
+
+ public Server getServer()
+ {
+ return server;
+ }
public File getWebAppDir()
{
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpointConfigContextListener.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpointConfigContextListener.java
index c56585a5eb5..6b2a6b38bf6 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpointConfigContextListener.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpointConfigContextListener.java
@@ -25,7 +25,7 @@ import javax.websocket.server.ServerContainer;
import javax.websocket.server.ServerEndpointConfig;
/**
- * Example of adding a server WebSocket (extending {@link Endpoint}) programmatically via config
+ * Example of adding a server WebSocket (extending {@link javax.websocket.Endpoint}) programmatically via config
*/
public class BasicEchoEndpointConfigContextListener implements ServletContextListener
{
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/resources/alt-filter-web.xml b/jetty-websocket/javax-websocket-server-impl/src/test/resources/alt-filter-web.xml
new file mode 100644
index 00000000000..24c506eb389
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/resources/alt-filter-web.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ org.eclipse.jetty.websocket.jsr356.addDynamicFilter
+ false
+
+
+
+ wsuf-test
+ org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter
+
+
+
+ wsuf-test
+ /echo/*
+
+
diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/DefaultMappedWebSocketCreator.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/DefaultMappedWebSocketCreator.java
new file mode 100644
index 00000000000..fcbd5419703
--- /dev/null
+++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/DefaultMappedWebSocketCreator.java
@@ -0,0 +1,40 @@
+//
+// ========================================================================
+// 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 org.eclipse.jetty.websocket.server.pathmap.PathMappings;
+import org.eclipse.jetty.websocket.server.pathmap.PathSpec;
+import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
+
+public class DefaultMappedWebSocketCreator implements MappedWebSocketCreator
+{
+ private final PathMappings mappings = new PathMappings<>();
+
+ @Override
+ public void addMapping(PathSpec spec, WebSocketCreator creator)
+ {
+ this.mappings.put(spec, creator);
+ }
+
+ @Override
+ public PathMappings getMappings()
+ {
+ return this.mappings;
+ }
+}
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 6a0829f52a2..1178c35c578 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
@@ -57,48 +57,35 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
{
public static final String CONTEXT_ATTRIBUTE_KEY = "contextAttributeKey";
private static final Logger LOG = Log.getLogger(WebSocketUpgradeFilter.class);
-
+
public static WebSocketUpgradeFilter configureContext(ServletContextHandler context) throws ServletException
{
// Prevent double configure
- WebSocketUpgradeFilter filter = (WebSocketUpgradeFilter)context.getAttribute(WebSocketUpgradeFilter.class.getName());
+ WebSocketUpgradeFilter filter = (WebSocketUpgradeFilter) context.getAttribute(WebSocketUpgradeFilter.class.getName());
if (filter != null)
{
return filter;
}
-
- // Use WEB-INF/web.xml instantiated version, if present
- FilterHolder filters[] = context.getServletHandler().getFilters();
- for (FilterHolder registeredFilter: filters)
- {
- if (WebSocketUpgradeFilter.class.isAssignableFrom(registeredFilter.getClass()))
- {
- WebSocketUpgradeFilter wsuf = (WebSocketUpgradeFilter) registeredFilter.getFilter();
- // need async supported
- context.setAttribute(WebSocketUpgradeFilter.class.getName(), wsuf);
- return wsuf;
- }
- }
// Dynamically add filter
filter = new WebSocketUpgradeFilter();
filter.setToAttribute(context, WebSocketUpgradeFilter.class.getName());
-
+
String name = "Jetty_WebSocketUpgradeFilter";
String pathSpec = "/*";
EnumSet dispatcherTypes = EnumSet.of(DispatcherType.REQUEST);
-
+
FilterHolder fholder = new FilterHolder(filter);
fholder.setName(name);
fholder.setAsyncSupported(true);
- fholder.setInitParameter(CONTEXT_ATTRIBUTE_KEY,WebSocketUpgradeFilter.class.getName());
- context.addFilter(fholder,pathSpec,dispatcherTypes);
-
+ fholder.setInitParameter(CONTEXT_ATTRIBUTE_KEY, WebSocketUpgradeFilter.class.getName());
+ context.addFilter(fholder, pathSpec, dispatcherTypes);
+
if (LOG.isDebugEnabled())
{
- LOG.debug("Adding [{}] {} mapped to {} to {}",name,filter,pathSpec,context);
+ LOG.debug("Adding [{}] {} mapped to {} to {}", name, filter, pathSpec, context);
}
-
+
return filter;
}
@@ -109,12 +96,12 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
public static WebSocketUpgradeFilter configureContext(ServletContext context) throws ServletException
{
ContextHandler handler = ContextHandler.getContextHandler(context);
-
+
if (handler == null)
{
throw new ServletException("Not running on Jetty, WebSocket support unavailable");
}
-
+
if (!(handler instanceof ServletContextHandler))
{
throw new ServletException("Not running in Jetty ServletContextHandler, WebSocket support via " + WebSocketUpgradeFilter.class.getName() + " unavailable");
@@ -122,40 +109,41 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
return configureContext((ServletContextHandler) handler);
}
-
- private final WebSocketServerFactory factory;
- private final PathMappings pathmap = new PathMappings<>();
+
+ public static final String CREATOR_KEY = "org.eclipse.jetty.websocket.server.creator";
+ public static final String FACTORY_KEY = "org.eclipse.jetty.websocket.server.factory";
+
+ private final WebSocketPolicy policy;
+ private final ByteBufferPool bufferPool;
+ private WebSocketServerFactory factory;
+ private MappedWebSocketCreator mappedWebSocketCreator;
private String fname;
private boolean alreadySetToAttribute = false;
-
+
public WebSocketUpgradeFilter()
{
- this(WebSocketPolicy.newServerPolicy(),new MappedByteBufferPool());
+ this(WebSocketPolicy.newServerPolicy(), new MappedByteBufferPool());
}
-
+
public WebSocketUpgradeFilter(WebSocketPolicy policy, ByteBufferPool bufferPool)
{
- factory = new WebSocketServerFactory(policy,bufferPool);
- addBean(factory,true);
+ this.policy = policy;
+ this.bufferPool = bufferPool;
}
-
+
@Override
public void addMapping(PathSpec spec, WebSocketCreator creator)
{
- // TODO: ideally should throw warning/error if attempting to map to something
- // not covered by the filter pathSpec/url-patterns. But how do we get the filter mappings
- // in a sane way? and then apply them to the PathSpec object properly?
- pathmap.put(spec,creator);
+ mappedWebSocketCreator.addMapping(spec, creator);
}
-
+
@Override
public void destroy()
{
factory.cleanup();
- pathmap.reset();
super.destroy();
}
-
+
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
@@ -163,10 +151,10 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
{
// no factory, cannot operate
LOG.debug("WebSocketUpgradeFilter is not operational - no WebSocketServletFactory configured");
- chain.doFilter(request,response);
+ chain.doFilter(request, response);
return;
}
-
+
try
{
HttpServletRequest httpreq = (HttpServletRequest) request;
@@ -178,7 +166,7 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
chain.doFilter(request, response);
return;
}
-
+
// Since this is a filter, we need to be smart about determining the target path
String contextPath = httpreq.getContextPath();
String target = httpreq.getRequestURI();
@@ -186,37 +174,37 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
{
target = target.substring(contextPath.length());
}
-
- MappedResource resource = pathmap.getMatch(target);
+
+ MappedResource resource = mappedWebSocketCreator.getMappings().getMatch(target);
if (resource == null)
{
if (LOG.isDebugEnabled())
{
LOG.debug("WebSocket Upgrade on {} has no associated endpoint", target);
- LOG.debug("PathMappings: {}", pathmap.dump());
+ LOG.debug("PathMappings: {}", mappedWebSocketCreator.getMappings().dump());
}
// no match.
chain.doFilter(request, response);
return;
}
- if(LOG.isDebugEnabled())
+ if (LOG.isDebugEnabled())
{
LOG.debug("WebSocket Upgrade detected on {} for endpoint {}", target, resource);
}
-
+
WebSocketCreator creator = resource.getResource();
-
+
// Store PathSpec resource mapping as request attribute
httpreq.setAttribute(PathSpec.class.getName(), resource.getPathSpec());
-
+
// We have an upgrade request
if (factory.acceptWebSocket(creator, httpreq, httpresp))
{
// We have a socket instance created
return;
}
-
+
// If we reach this point, it means we had an incoming request to upgrade
// but it was either not a proper websocket upgrade, or it was possibly rejected
// due to incoming request constraints (controlled by WebSocketCreator)
@@ -234,69 +222,82 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
LOG.debug("Not a HttpServletRequest, skipping WebSocketUpgradeFilter");
}
}
-
+
// not an Upgrade request
- chain.doFilter(request,response);
+ chain.doFilter(request, response);
}
-
+
@Override
public String dump()
{
return ContainerLifeCycle.dump(this);
}
-
+
@Override
public void dump(Appendable out, String indent) throws IOException
{
- out.append(indent).append(" +- pathmap=").append(pathmap.toString()).append("\n");
- pathmap.dump(out,indent + " ");
+ out.append(indent).append(" +- pathmap=").append(mappedWebSocketCreator.toString()).append("\n");
+ mappedWebSocketCreator.getMappings().dump(out, indent + " ");
}
-
+
public WebSocketServerFactory getFactory()
{
return factory;
}
-
+
@ManagedAttribute(value = "mappings", readonly = true)
@Override
public PathMappings getMappings()
{
- return pathmap;
+ return mappedWebSocketCreator.getMappings();
}
-
+
@Override
public void init(FilterConfig config) throws ServletException
{
fname = config.getFilterName();
-
+
try
{
- WebSocketPolicy policy = factory.getPolicy();
-
+ mappedWebSocketCreator = (MappedWebSocketCreator) config.getServletContext().getAttribute(CREATOR_KEY);
+ if (mappedWebSocketCreator == null)
+ {
+ mappedWebSocketCreator = new DefaultMappedWebSocketCreator();
+ }
+
+ factory = (WebSocketServerFactory) config.getServletContext().getAttribute(FACTORY_KEY);
+ if (factory == null)
+ {
+ factory = new WebSocketServerFactory(policy, bufferPool);
+ }
+ addBean(factory, true);
+
+ // TODO: Policy isn't from attributes
+
String max = config.getInitParameter("maxIdleTime");
if (max != null)
{
- policy.setIdleTimeout(Long.parseLong(max));
+ factory.getPolicy().setIdleTimeout(Long.parseLong(max));
}
-
+
max = config.getInitParameter("maxTextMessageSize");
if (max != null)
{
- policy.setMaxTextMessageSize(Integer.parseInt(max));
+ factory.getPolicy().setMaxTextMessageSize(Integer.parseInt(max));
}
-
+
max = config.getInitParameter("maxBinaryMessageSize");
if (max != null)
{
- policy.setMaxBinaryMessageSize(Integer.parseInt(max));
+ factory.getPolicy().setMaxBinaryMessageSize(Integer.parseInt(max));
}
-
+
max = config.getInitParameter("inputBufferSize");
if (max != null)
{
- policy.setInputBufferSize(Integer.parseInt(max));
+ factory.getPolicy().setInputBufferSize(Integer.parseInt(max));
}
-
+
String key = config.getInitParameter(CONTEXT_ATTRIBUTE_KEY);
if (key == null)
{
@@ -305,7 +306,7 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
}
setToAttribute(config.getServletContext(), key);
-
+
factory.start();
}
catch (Exception x)
@@ -316,45 +317,45 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
private void setToAttribute(ServletContextHandler context, String key) throws ServletException
{
- if(alreadySetToAttribute)
+ if (alreadySetToAttribute)
{
return;
}
if (context.getAttribute(key) != null)
{
- throw new ServletException(WebSocketUpgradeFilter.class.getName() +
+ throw new ServletException(WebSocketUpgradeFilter.class.getName() +
" is defined twice for the same context attribute key '" + key
- + "'. Make sure you have different init-param '" +
+ + "'. Make sure you have different init-param '" +
CONTEXT_ATTRIBUTE_KEY + "' values set");
}
- context.setAttribute(key,this);
-
+ context.setAttribute(key, this);
+
alreadySetToAttribute = true;
}
-
+
public void setToAttribute(ServletContext context, String key) throws ServletException
{
- if(alreadySetToAttribute)
+ if (alreadySetToAttribute)
{
return;
}
if (context.getAttribute(key) != null)
{
- throw new ServletException(WebSocketUpgradeFilter.class.getName() +
+ throw new ServletException(WebSocketUpgradeFilter.class.getName() +
" is defined twice for the same context attribute key '" + key
- + "'. Make sure you have different init-param '" +
+ + "'. Make sure you have different init-param '" +
CONTEXT_ATTRIBUTE_KEY + "' values set");
}
- context.setAttribute(key,this);
-
+ context.setAttribute(key, this);
+
alreadySetToAttribute = true;
}
-
+
@Override
public String toString()
{
- return String.format("%s[factory=%s,pathmap=%s]",this.getClass().getSimpleName(),factory,pathmap);
+ return String.format("%s[factory=%s,creator=%s]", this.getClass().getSimpleName(), factory, mappedWebSocketCreator);
}
}