Splitting out websocket-servlet to make it more friendly for WebAppClassloader

This commit is contained in:
Joakim Erdfelt 2012-11-12 19:42:32 -07:00
parent 26ad9a5def
commit d67fdfdd85
23 changed files with 194 additions and 78 deletions

View File

@ -133,12 +133,24 @@
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
<excludeGroupIds>org.eclipse.jetty.orbit,org.eclipse.jetty.spdy</excludeGroupIds>
<excludeGroupIds>org.eclipse.jetty.orbit,org.eclipse.jetty.spdy,org.eclipse.jetty.websocket,org.eclipse.jetty.drafts</excludeGroupIds>
<excludeArtifactIds>jetty-all,jetty-start,jetty-monitor,jetty-jsp</excludeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-lib-websocket-deps</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty.websocket,org.eclipse.jetty.drafts</includeGroupIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib/websocket</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-orbit-servlet-api-deps</id>
<phase>generate-resources</phase>
@ -346,6 +358,11 @@
<artifactId>jetty-servlets</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>

View File

@ -149,8 +149,7 @@ $(jetty.home)/lib/jetty-client-$(version).jar ! available org.eclipse.jetty.cl
$(jetty.home)/lib/jetty-http-$(version).jar ! available org.eclipse.jetty.http.HttpParser
[All,websocket]
$(jetty.home)/lib/websocket-core-$(version).jar ! available org.eclipse.jetty.websocket.api.WebSocketConnection
$(jetty.home)/lib/websocket-server-$(version).jar ! available org.eclipse.jetty.websocket.server.WebSocketServlet
$(jetty.home)/lib/websocket/**
[All,overlay,overlays]
$(jetty.home)/lib/jetty-overlay-deployer-$(version).jar ! available org.eclipse.jetty.overlay.OverlayedAppProvider

View File

@ -114,7 +114,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
"org.eclipse.jetty.continuation.", // webapp cannot change continuation classes
"org.eclipse.jetty.jndi.", // webapp cannot change naming classes
"org.eclipse.jetty.jaas.", // webapp cannot change jaas classes
"org.eclipse.jetty.websocket.", // WebSocket is a jetty extension
"org.eclipse.jetty.websocket.", // WebSocket is a jetty extension
"org.eclipse.jetty.servlet.DefaultServlet" // webapp cannot change default servlets
} ;
@ -127,7 +127,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
"-org.eclipse.jetty.continuation.", // don't hide continuation classes
"-org.eclipse.jetty.jndi.", // don't hide naming classes
"-org.eclipse.jetty.jaas.", // don't hide jaas classes
"-org.eclipse.jetty.websocket.", // WebSocket is a jetty extension
"-org.eclipse.jetty.servlets.", // don't hide jetty servlets
"-org.eclipse.jetty.servlet.DefaultServlet", // don't hide default servlet
"-org.eclipse.jetty.servlet.listener.", // don't hide useful listeners

View File

@ -20,6 +20,11 @@
<artifactId>websocket-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-servlet</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.servlet</artifactId>

View File

@ -28,6 +28,7 @@ import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
public abstract class WebSocketHandler extends HandlerWrapper
{
@ -45,13 +46,13 @@ public abstract class WebSocketHandler extends HandlerWrapper
}
@Override
public void configure(WebSocketServerFactory factory)
public void configure(WebSocketServletFactory factory)
{
factory.register(websocketPojo);
}
}
private final WebSocketServerFactory webSocketFactory;
private final WebSocketServletFactory webSocketFactory;
public WebSocketHandler()
{
@ -61,7 +62,7 @@ public abstract class WebSocketHandler extends HandlerWrapper
addBean(webSocketFactory);
}
public abstract void configure(WebSocketServerFactory factory);
public abstract void configure(WebSocketServletFactory factory);
public void configurePolicy(WebSocketPolicy policy)
{
@ -75,7 +76,7 @@ public abstract class WebSocketHandler extends HandlerWrapper
configure(webSocketFactory);
}
public WebSocketServerFactory getWebSocketFactory()
public WebSocketServletFactory getWebSocketFactory()
{
return webSocketFactory;
}

View File

@ -45,7 +45,6 @@ import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
import org.eclipse.jetty.websocket.common.LogicalConnection;
import org.eclipse.jetty.websocket.common.WebSocketSession;
@ -54,11 +53,13 @@ import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
import org.eclipse.jetty.websocket.common.extensions.ExtensionStack;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
import org.eclipse.jetty.websocket.server.handshake.HandshakeRFC6455;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
/**
* Factory to create WebSocket connections
*/
public class WebSocketServerFactory extends ContainerLifeCycle implements WebSocketCreator
public class WebSocketServerFactory extends ContainerLifeCycle implements WebSocketCreator, WebSocketServletFactory
{
private static final Logger LOG = Log.getLogger(WebSocketServerFactory.class);
@ -91,6 +92,11 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
private WebSocketCreator creator;
private List<Class<?>> registeredSocketClasses;
public WebSocketServerFactory()
{
this(WebSocketPolicy.newServerPolicy(),new MappedByteBufferPool());
}
public WebSocketServerFactory(WebSocketPolicy policy)
{
this(policy,new MappedByteBufferPool());
@ -127,6 +133,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
supportedVersions = rv.toString();
}
@Override
public boolean acceptWebSocket(HttpServletRequest request, HttpServletResponse response) throws IOException
{
ServletWebSocketRequest sockreq = new ServletWebSocketRequest(request);
@ -163,6 +170,19 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return upgrade(sockreq,sockresp,driver);
}
@Override
public void cleanup()
{
try
{
this.stop();
}
catch (Exception e)
{
LOG.warn(e);
}
}
protected void closeAllConnections()
{
for (WebSocketSession session : sessions)
@ -179,6 +199,12 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
sessions.clear();
}
@Override
public WebSocketServletFactory createFactory(WebSocketPolicy policy)
{
return new WebSocketServerFactory(policy);
}
/**
* Default Creator logic
*/
@ -213,28 +239,31 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
super.doStop();
}
@Override
public WebSocketCreator getCreator()
{
return this.creator;
}
@Override
public ExtensionFactory getExtensionFactory()
{
return extensionFactory;
}
/**
* Get the base policy in use for WebSockets.
* <p>
* Note: individual WebSocket implementations can override some of the values in here by using the {@link WebSocket &#064;WebSocket} annotation.
*
* @return the base policy
*/
@Override
public WebSocketPolicy getPolicy()
{
return basePolicy;
}
@Override
public void init() throws Exception
{
start();
}
@Override
public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response)
{
String upgrade = request.getHeader("Upgrade");
@ -278,14 +307,12 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return protocols;
}
/**
* Register a websocket class pojo with the default {@link WebSocketCreator}.
* <p>
* Note: only required if using the default {@link WebSocketCreator} provided by this factory.
/*
* (non-Javadoc)
*
* @param websocketPojo
* the class to instantiate for each incoming websocket upgrade request.
* @see org.eclipse.jetty.websocket.server.WebSocketServletFactory#register(java.lang.Class)
*/
@Override
public void register(Class<?> websocketPojo)
{
registeredSocketClasses.add(websocketPojo);
@ -312,6 +339,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return ret;
}
@Override
public void setCreator(WebSocketCreator creator)
{
this.creator = creator;
@ -330,7 +358,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
* @param driver
* The websocket handler implementation to use
* @throws IOException
* in case of I/O errors
*/
public boolean upgrade(ServletWebSocketRequest request, ServletWebSocketResponse response, EventDriver driver) throws IOException
{

View File

@ -0,0 +1 @@
org.eclipse.jetty.websocket.server.WebSocketServerFactory

View File

@ -33,6 +33,8 @@ import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.server.blockhead.BlockheadClient;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
@ -45,7 +47,7 @@ public class LoadTest
public static class LoadServlet extends WebSocketServlet
{
@Override
public void configure(WebSocketServerFactory factory)
public void configure(WebSocketServletFactory factory)
{
factory.register(LoadSocket.class);
}

View File

@ -36,6 +36,7 @@ import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.server.blockhead.BlockheadClient;
import org.eclipse.jetty.websocket.server.helper.IncomingFramesCapture;
import org.eclipse.jetty.websocket.server.helper.RFCServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;

View File

@ -18,8 +18,8 @@
package org.eclipse.jetty.websocket.server.ab;
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
import org.eclipse.jetty.websocket.server.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
/**
* Servlet with bigger message policy sizes, with registered simple echo socket.
@ -31,7 +31,7 @@ public class ABServlet extends WebSocketServlet
private static final int MBYTE = KBYTE * KBYTE;
@Override
public void configure(WebSocketServerFactory factory)
public void configure(WebSocketServletFactory factory)
{
// Test cases 9.x uses BIG frame sizes, let policy handle them.
int bigFrameSize = 20 * MBYTE;

View File

@ -25,9 +25,9 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;
import org.eclipse.jetty.websocket.server.WebSocketCreator;
import org.eclipse.jetty.websocket.server.WebSocketHandler;
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
/**
* Tool to help debug websocket circumstances reported around browsers.
@ -104,7 +104,7 @@ public class BrowserDebugTool implements WebSocketCreator
WebSocketHandler wsHandler = new WebSocketHandler()
{
@Override
public void configure(WebSocketServerFactory factory)
public void configure(WebSocketServletFactory factory)
{
LOG.debug("Configuring WebSocketServerFactory ...");
factory.setCreator(BrowserDebugTool.this);

View File

@ -18,8 +18,8 @@
package org.eclipse.jetty.websocket.server.examples;
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
import org.eclipse.jetty.websocket.server.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
/**
* Example servlet for most basic form.
@ -28,7 +28,7 @@ import org.eclipse.jetty.websocket.server.WebSocketServlet;
public class MyEchoServlet extends WebSocketServlet
{
@Override
public void configure(WebSocketServerFactory factory)
public void configure(WebSocketServletFactory factory)
{
factory.register(MyEchoSocket.class);
}

View File

@ -20,7 +20,7 @@ package org.eclipse.jetty.websocket.server.examples.echo;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;
import org.eclipse.jetty.websocket.server.WebSocketCreator;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
/**
* Example of setting up a creator to create appropriately via the proposed and negotiated protocols.

View File

@ -24,7 +24,7 @@ import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.server.WebSocketHandler;
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
/**
* Example server using WebSocket and core Jetty Handlers
@ -99,7 +99,7 @@ public class ExampleEchoServer
wsHandler = new WebSocketHandler()
{
@Override
public void configure(WebSocketServerFactory factory)
public void configure(WebSocketServletFactory factory)
{
factory.setCreator(new EchoCreator());
}

View File

@ -18,8 +18,8 @@
package org.eclipse.jetty.websocket.server.helper;
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
import org.eclipse.jetty.websocket.server.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
/**
* Initialize a simple Echo websocket
@ -28,7 +28,7 @@ import org.eclipse.jetty.websocket.server.WebSocketServlet;
public class EchoServlet extends WebSocketServlet
{
@Override
public void configure(WebSocketServerFactory factory)
public void configure(WebSocketServletFactory factory)
{
factory.register(EchoSocket.class);
}

View File

@ -18,14 +18,14 @@
package org.eclipse.jetty.websocket.server.helper;
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
import org.eclipse.jetty.websocket.server.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@SuppressWarnings("serial")
public class RFCServlet extends WebSocketServlet
{
@Override
public void configure(WebSocketServerFactory factory)
public void configure(WebSocketServletFactory factory)
{
factory.register(RFCSocket.class);
}

View File

@ -19,25 +19,26 @@
package org.eclipse.jetty.websocket.server.helper;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
import org.eclipse.jetty.websocket.server.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@SuppressWarnings("serial")
public class WebSocketCaptureServlet extends WebSocketServlet
{
@Override
public void configure(WebSocketServletFactory factory)
{
factory.register(CaptureSocket.class);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
resp.sendError(404);
}
@Override
public void configure(WebSocketServerFactory factory)
{
factory.register(CaptureSocket.class);
}
}

View File

@ -17,7 +17,7 @@
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-common</artifactId>
<artifactId>websocket-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>

View File

@ -16,7 +16,7 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.server;
package org.eclipse.jetty.websocket.servlet;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;

View File

@ -16,17 +16,16 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.server;
package org.eclipse.jetty.websocket.servlet;
import java.io.IOException;
import java.util.ServiceLoader;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@ -86,22 +85,14 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@SuppressWarnings("serial")
public abstract class WebSocketServlet extends HttpServlet
{
private final Logger LOG = Log.getLogger(getClass());
private WebSocketServerFactory webSocketFactory;
private WebSocketServletFactory factory;
public abstract void configure(WebSocketServerFactory factory);
public abstract void configure(WebSocketServletFactory factory);
@Override
public void destroy()
{
try
{
webSocketFactory.stop();
}
catch (Exception x)
{
LOG.ignore(x);
}
factory.cleanup();
}
/**
@ -137,11 +128,14 @@ public abstract class WebSocketServlet extends HttpServlet
policy.setMaxBinaryMessageSize(Integer.parseInt(max));
}
webSocketFactory = new WebSocketServerFactory(policy);
ServiceLoader<WebSocketServletFactory> loader = ServiceLoader.load(WebSocketServletFactory.class);
WebSocketServletFactory baseFactory = loader.iterator().next();
configure(webSocketFactory);
factory = baseFactory.createFactory(policy);
webSocketFactory.start();
configure(factory);
factory.init();
}
catch (Exception x)
{
@ -155,10 +149,10 @@ public abstract class WebSocketServlet extends HttpServlet
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
if (webSocketFactory.isUpgradeRequest(request,response))
if (factory.isUpgradeRequest(request,response))
{
// We have an upgrade request
if (webSocketFactory.acceptWebSocket(request,response))
if (factory.acceptWebSocket(request,response))
{
// We have a socket instance created
return;

View File

@ -0,0 +1,69 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.servlet;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
/**
* Basic WebSocketServletFactory for working with Jetty-based WebSocketServlets
*/
public interface WebSocketServletFactory
{
public boolean acceptWebSocket(HttpServletRequest request, HttpServletResponse response) throws IOException;
public void cleanup();
public WebSocketServletFactory createFactory(WebSocketPolicy policy);
public abstract WebSocketCreator getCreator();
public abstract ExtensionFactory getExtensionFactory();
/**
* Get the base policy in use for WebSockets.
* <p>
* Note: individual WebSocket implementations can override some of the values in here by using the {@link WebSocket &#064;WebSocket} annotation.
*
* @return the base policy
*/
public WebSocketPolicy getPolicy();
public void init() throws Exception;
public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response);
/**
* Register a websocket class pojo with the default {@link WebSocketCreator}.
* <p>
* Note: only required if using the default {@link WebSocketCreator} provided by this factory.
*
* @param websocketPojo
* the class to instantiate for each incoming websocket upgrade request.
*/
public void register(Class<?> websocketPojo);
public abstract void setCreator(WebSocketCreator creator);
}

View File

@ -168,7 +168,7 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
<artifactId>websocket-servlet</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>

View File

@ -53,9 +53,9 @@ import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.server.WebSocketCreator;
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
import org.eclipse.jetty.websocket.server.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@SuppressWarnings("serial")
public class WebSocketChatServlet extends WebSocketServlet implements WebSocketCreator
@ -76,7 +76,7 @@ public class WebSocketChatServlet extends WebSocketServlet implements WebSocketC
}
@Override
public void configure(WebSocketServerFactory factory)
public void configure(WebSocketServletFactory factory)
{
factory.register(ChatWebSocket.class);
factory.setCreator(this);