Using Jetty component listeners for CDI

This commit is contained in:
Joakim Erdfelt 2015-03-10 10:27:07 -07:00
parent 31ee46d482
commit dc81cda742
20 changed files with 418 additions and 266 deletions

View File

@ -57,8 +57,6 @@ public class JettyWeldInitializer
public static void initContext(ContextHandler handler) throws NamingException
{
// TODO: handler.addLifeCycleListener(new WebSocketServerLifecycleListener(handler));
// Add context specific weld container reference.
// See https://issues.jboss.org/browse/WELD-1710
// and https://github.com/weld/core/blob/2.2.5.Final/environments/servlet/core/src/main/java/org/jboss/weld/environment/servlet/WeldServletLifecycle.java#L244-L253

View File

@ -0,0 +1,74 @@
//
// ========================================================================
// Copyright (c) 1995-2015 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.cdi.websocket;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.websocket.common.util.ThreadClassLoaderScope;
public class WebSocketCdiInitializer implements ServletContainerInitializer
{
public static void configureContext(ServletContextHandler context) throws ServletException
{
try (ThreadClassLoaderScope scope = new ThreadClassLoaderScope(context.getClassLoader()))
{
addListeners(context);
}
}
@Override
public void onStartup(Set<Class<?>> c, ServletContext context) throws ServletException
{
ContextHandler handler = ContextHandler.getContextHandler(context);
if (handler == null)
{
throw new ServletException("Not running on Jetty, WebSocket+CDI support unavailable");
}
if (!(handler instanceof ServletContextHandler))
{
throw new ServletException("Not running in Jetty ServletContextHandler, WebSocket+CDI support unavailable");
}
ServletContextHandler jettyContext = (ServletContextHandler)handler;
try (ThreadClassLoaderScope scope = new ThreadClassLoaderScope(context.getClassLoader()))
{
addListeners(jettyContext);
}
}
private static void addListeners(ContainerLifeCycle container)
{
WebSocketCdiListener listener = new WebSocketCdiListener(container);
if (listener != null)
{
container.addLifeCycleListener(listener);
container.addEventListener(listener);
}
}
}

View File

@ -0,0 +1,138 @@
package org.eclipse.jetty.cdi.websocket;
import java.util.Set;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.CDI;
import org.eclipse.jetty.cdi.core.AnyLiteral;
import org.eclipse.jetty.cdi.core.ScopedInstance;
import org.eclipse.jetty.util.component.Container;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketSessionScope;
public class WebSocketCdiListener implements LifeCycle.Listener, Container.InheritedListener
{
private static final Logger LOG = Log.getLogger(WebSocketCdiListener.class);
private final ContainerLifeCycle container;
public WebSocketCdiListener(ContainerLifeCycle container)
{
this.container = container;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static <T> ScopedInstance<T> newInstance(Class<T> clazz)
{
BeanManager bm = CDI.current().getBeanManager();
ScopedInstance sbean = new ScopedInstance();
Set<Bean<?>> beans = bm.getBeans(clazz,AnyLiteral.INSTANCE);
if (beans.size() > 0)
{
sbean.bean = beans.iterator().next();
sbean.creationalContext = bm.createCreationalContext(sbean.bean);
sbean.instance = bm.getReference(sbean.bean,clazz,sbean.creationalContext);
return sbean;
}
else
{
throw new RuntimeException(String.format("Can't find class %s",clazz));
}
}
private ScopedInstance<WebSocketScopeContext> wsScope;
private synchronized ScopedInstance<WebSocketScopeContext> getWebSocketScope()
{
if (wsScope == null)
{
wsScope = newInstance(WebSocketScopeContext.class);
}
return wsScope;
}
@Override
public void lifeCycleStarting(LifeCycle event)
{
if (event instanceof WebSocketContainerScope)
{
if (LOG.isDebugEnabled())
{
LOG.debug("starting websocket container [{}]", event);
}
getWebSocketScope().instance.begin();
}
else if (event instanceof WebSocketSessionScope)
{
if (LOG.isDebugEnabled())
{
LOG.debug("starting websocket session [{}]", event);
}
getWebSocketScope().instance.setSession((Session)event);
}
}
@Override
public void lifeCycleStarted(LifeCycle event)
{
}
@Override
public void lifeCycleFailure(LifeCycle event, Throwable cause)
{
}
@Override
public void lifeCycleStopping(LifeCycle event)
{
}
@Override
public void lifeCycleStopped(LifeCycle event)
{
if (event instanceof WebSocketContainerScope)
{
if (LOG.isDebugEnabled())
{
LOG.debug("stopped websocket container [{}]", event);
}
getWebSocketScope().instance.end();
}
else if (event == container)
{
if (LOG.isDebugEnabled())
{
LOG.debug("stopped parent container [{}]", event);
}
if (wsScope != null)
{
wsScope.destroy();
}
}
}
@Override
public void beanAdded(Container parent, Object child)
{
if (child instanceof LifeCycle)
{
((LifeCycle)child).addLifeCycleListener(this);
}
}
@Override
public void beanRemoved(Container parent, Object child)
{
if (child instanceof LifeCycle)
{
((LifeCycle)child).removeLifeCycleListener(this);
}
}
}

View File

@ -52,7 +52,7 @@ public class WebSocketScopeContext
public void begin()
{
LOG.debug("begin()");
LOG.debug("begin()", new Throwable("Trace"));
if (state.get() != null)
{
throw new IllegalAccessError("Already in WebSocketScope");
@ -102,7 +102,7 @@ public class WebSocketScopeContext
public void setSession(Session sess)
{
LOG.debug("setSession()");
LOG.debug("setSession({})",sess);
jettySessionProducer.setSession(sess);
if(sess instanceof javax.websocket.Session)
{

View File

@ -0,0 +1 @@
org.eclipse.jetty.cdi.websocket.WebSocketCdiInitializer

View File

@ -49,6 +49,7 @@ public class BasicAppTest
private static final Logger LOG = Log.getLogger(BasicAppTest.class);
private static Server server;
@SuppressWarnings("unused")
private static URI serverHttpURI;
private static URI serverWebsocketURI;

View File

@ -29,6 +29,7 @@ import javax.websocket.server.ServerContainer;
import org.eclipse.jetty.cdi.servlet.EmbeddedCdiHandler;
import org.eclipse.jetty.cdi.websocket.CheckSocket;
import org.eclipse.jetty.cdi.websocket.WebSocketCdiInitializer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
@ -60,6 +61,7 @@ public class CdiAppTest
server.addConnector(connector);
EmbeddedCdiHandler context = new EmbeddedCdiHandler();
WebSocketCdiInitializer.configureContext(context);
File baseDir = MavenTestingUtils.getTestResourcesDir();
@ -69,6 +71,7 @@ public class CdiAppTest
// Add some websockets
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
container.addEndpoint(EchoSocket.class);
container.addEndpoint(InfoSocket.class);
server.start();
@ -120,7 +123,7 @@ public class CdiAppTest
}
@Test
public void testWebSocketInfo() throws Exception
public void testWebSocket_Info_FieldPresence() throws Exception
{
WebSocketClient client = new WebSocketClient();
try
@ -150,4 +153,31 @@ public class CdiAppTest
client.stop();
}
}
@Test
public void testWebSocket_Info_DataFromCdi() throws Exception
{
WebSocketClient client = new WebSocketClient();
try
{
client.start();
CheckSocket socket = new CheckSocket();
client.connect(socket,serverWebsocketURI.resolve("/cdi-info"));
socket.awaitOpen(2,TimeUnit.SECONDS);
socket.sendText("data|stuff");
socket.close(StatusCode.NORMAL,"Test complete");
socket.awaitClose(2,TimeUnit.SECONDS);
assertThat("Messages received",socket.getTextMessages().size(),is(1));
String response = socket.getTextMessages().poll();
System.err.println(response);
assertThat("Message[0]",response,containsString("Hello there data"));
}
finally
{
client.stop();
}
}
}

View File

@ -20,15 +20,22 @@ package org.eclipse.jetty.cdi.websocket.cdiapp;
import javax.inject.Inject;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.Session;
public class DataMaker
{
private static final Logger LOG = Log.getLogger(DataMaker.class);
@Inject
private Session session;
public void processMessage(String msg)
{
LOG.debug(".processMessage({})",msg);
LOG.debug("session = {}",session);
session.getRemote().sendStringByFuture("Hello there " + msg);
}
}

View File

@ -0,0 +1,57 @@
//
// ========================================================================
// Copyright (c) 1995-2015 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.cdi.websocket.cdiapp;
import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ServerEndpoint("/echo")
public class EchoSocket
{
private static final Logger LOG = Log.getLogger(EchoSocket.class);
@SuppressWarnings("unused")
private Session session;
@OnOpen
public void onOpen(Session session)
{
LOG.debug("onOpen(): {}",session);
this.session = session;
}
@OnClose
public void onClose(CloseReason close)
{
LOG.debug("onClose(): {}",close);
this.session = null;
}
@OnMessage
public String onMessage(String msg)
{
return msg;
}
}

View File

@ -69,8 +69,10 @@ public class InfoSocket
{
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
String args[] = msg.split("\\|");
switch (msg)
switch (args[0])
{
case "info":
out.printf("websocketSession is %s%n",asPresent(session));
@ -78,7 +80,7 @@ public class InfoSocket
out.printf("servletContext is %s%n",asPresent(servletContext));
break;
case "data":
dataMaker.processMessage(msg);
dataMaker.processMessage(args[1]);
break;
}

View File

@ -22,7 +22,6 @@ import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@ -59,8 +58,6 @@ import org.eclipse.jetty.websocket.common.SessionListener;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketScopeEvents;
import org.eclipse.jetty.websocket.common.scopes.WebSocketScopeListener;
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
import org.eclipse.jetty.websocket.jsr356.client.AnnotatedClientEndpointMetadata;
import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig;
@ -119,12 +116,6 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
ShutdownThread.register(this);
}
@Override
public void addScopeListener(WebSocketScopeListener listener)
{
this.scopeDelegate.addScopeListener(listener);
}
private Session connect(EndpointInstance instance, URI path) throws IOException
{
Objects.requireNonNull(instance,"EndpointInstance cannot be null");
@ -351,17 +342,6 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
return scopeDelegate.getPolicy();
}
public WebSocketScopeEvents getScopeEvents()
{
return scopeDelegate.getScopeEvents();
}
@Override
public List<WebSocketScopeListener> getScopeListeners()
{
return scopeDelegate.getScopeListeners();
}
@Override
public SslContextFactory getSslContextFactory()
{
@ -426,12 +406,6 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
}
}
@Override
public void removeScopeListener(WebSocketScopeListener listener)
{
scopeDelegate.removeScopeListener(listener);
}
@Override
public void setAsyncSendTimeout(long ms)
{

View File

@ -148,6 +148,7 @@ public class JsrEvents<T extends Annotation, C extends EndpointConfig>
{
if (onError == null)
{
LOG.warn("Unable to report throwable to websocket (no @OnError handler declared): " + websocket.getClass().getName(), cause);
return;
}
onError.call(websocket,cause);

View File

@ -24,7 +24,6 @@ import java.net.SocketAddress;
import java.net.URI;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.Executor;
@ -61,8 +60,6 @@ import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketScopeEvents;
import org.eclipse.jetty.websocket.common.scopes.WebSocketScopeListener;
/**
* WebSocketClient provides a means of establishing connections to remote websocket endpoints.
@ -74,7 +71,6 @@ public class WebSocketClient extends ContainerLifeCycle implements SessionListen
private final WebSocketPolicy policy = WebSocketPolicy.newClientPolicy();
private final SslContextFactory sslContextFactory;
private final WebSocketExtensionFactory extensionRegistry;
private WebSocketScopeEvents scopeEvents = new WebSocketScopeEvents();
private boolean daemon = false;
private EventDriverFactory eventDriverFactory;
private SessionFactory sessionFactory;
@ -150,12 +146,6 @@ public class WebSocketClient extends ContainerLifeCycle implements SessionListen
addBean(this.bufferPool);
}
@Override
public void addScopeListener(WebSocketScopeListener listener)
{
this.scopeEvents.addScopeListener(listener);
}
public Future<Session> connect(Object websocket, URI toUri) throws IOException
{
ClientUpgradeRequest request = new ClientUpgradeRequest(toUri);
@ -291,8 +281,6 @@ public class WebSocketClient extends ContainerLifeCycle implements SessionListen
super.doStart();
scopeEvents.fireContainerActivated(this);
if (LOG.isDebugEnabled())
LOG.debug("Started {}",this);
}
@ -316,8 +304,6 @@ public class WebSocketClient extends ContainerLifeCycle implements SessionListen
super.doStop();
scopeEvents.fireContainerDeactivated(this);
if (LOG.isDebugEnabled())
LOG.debug("Stopped {}",this);
}
@ -453,17 +439,6 @@ public class WebSocketClient extends ContainerLifeCycle implements SessionListen
return scheduler;
}
public WebSocketScopeEvents getScopeEvents()
{
return scopeEvents;
}
@Override
public List<WebSocketScopeListener> getScopeListeners()
{
return this.scopeEvents.getScopeListeners();
}
public SessionFactory getSessionFactory()
{
return sessionFactory;
@ -531,12 +506,6 @@ public class WebSocketClient extends ContainerLifeCycle implements SessionListen
LOG.debug("Session Opened: {}",session);
}
@Override
public void removeScopeListener(WebSocketScopeListener listener)
{
this.scopeEvents.removeScopeListener(listener);
}
public void setAsyncWriteTimeout(long ms)
{
this.policy.setAsyncWriteTimeout(ms);

View File

@ -275,7 +275,9 @@ public class UpgradeConnection extends AbstractConnection
// Validate Response Status Code
if (response.getStatusCode() != SWITCHING_PROTOCOLS)
{
throw new UpgradeException(request.getRequestURI(),response.getStatusCode(),"Didn't switch protocols");
// TODO: use jetty-http and org.eclipse.jetty.http.HttpStatus for more meaningful exception messages
throw new UpgradeException(request.getRequestURI(),response.getStatusCode(),"Didn't switch protocols, expected status <" + SWITCHING_PROTOCOLS
+ ">, but got <" + response.getStatusCode() + ">");
}
// Validate Connection header

View File

@ -18,7 +18,6 @@
package org.eclipse.jetty.websocket.common.scopes;
import java.util.List;
import java.util.concurrent.Executor;
import org.eclipse.jetty.io.ByteBufferPool;
@ -36,7 +35,6 @@ public class SimpleContainerScope extends ContainerLifeCycle implements WebSocke
private final WebSocketPolicy policy;
private Executor executor;
private SslContextFactory sslContextFactory;
private WebSocketScopeEvents scopeEvents = new WebSocketScopeEvents();
public SimpleContainerScope(WebSocketPolicy policy)
{
@ -65,14 +63,12 @@ public class SimpleContainerScope extends ContainerLifeCycle implements WebSocke
protected void doStart() throws Exception
{
super.doStart();
scopeEvents.fireContainerActivated(this);
}
@Override
protected void doStop() throws Exception
{
super.doStop();
scopeEvents.fireContainerDeactivated(this);
}
@Override
@ -109,27 +105,4 @@ public class SimpleContainerScope extends ContainerLifeCycle implements WebSocke
{
this.sslContextFactory = sslContextFactory;
}
public WebSocketScopeEvents getScopeEvents()
{
return scopeEvents;
}
@Override
public void addScopeListener(WebSocketScopeListener listener)
{
this.scopeEvents.addScopeListener(listener);
}
@Override
public void removeScopeListener(WebSocketScopeListener listener)
{
this.scopeEvents.removeScopeListener(listener);
}
@Override
public List<WebSocketScopeListener> getScopeListeners()
{
return this.scopeEvents.getScopeListeners();
}
}

View File

@ -18,7 +18,6 @@
package org.eclipse.jetty.websocket.common.scopes;
import java.util.List;
import java.util.concurrent.Executor;
import org.eclipse.jetty.io.ByteBufferPool;
@ -31,32 +30,6 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy;
*/
public interface WebSocketContainerScope
{
/**
* Add a {@link WebSocketScopeListener} for this container.
*
* @param listener
* the listener to receive container scope events
*/
public void addScopeListener(WebSocketScopeListener listener);
/**
* Remove a {@link WebSocketScopeListener} from this container
*
* @param listener
* the listener to receive websocket scope events
*/
public void removeScopeListener(WebSocketScopeListener listener);
/**
* Get the current list of {@link WebSocketScopeListener}s for this container
*/
public List<WebSocketScopeListener> getScopeListeners();
/**
* Get the WebSocketScopeEvents handler, for firing {@link WebSocketScopeListener} events.
*/
public WebSocketScopeEvents getScopeEvents();
/**
* The configured Container Buffer Pool.
*

View File

@ -1,99 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2015 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.common.scopes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class WebSocketScopeEvents
{
private List<WebSocketScopeListener> scopeListeners;
public void addScopeListener(WebSocketScopeListener listener)
{
if (scopeListeners == null)
{
scopeListeners = new ArrayList<>();
}
scopeListeners.add(listener);
}
public void fireContainerActivated(WebSocketContainerScope container)
{
if (scopeListeners != null)
{
for (WebSocketScopeListener listener : scopeListeners)
{
listener.onWebSocketContainerActivated(container);
}
}
}
public void fireContainerDeactivated(WebSocketContainerScope container)
{
if (scopeListeners != null)
{
for (WebSocketScopeListener listener : scopeListeners)
{
listener.onWebSocketContainerDeactivated(container);
}
}
}
public void fireSessionActivated(WebSocketSessionScope session)
{
if (scopeListeners != null)
{
for (WebSocketScopeListener listener : scopeListeners)
{
listener.onWebSocketSessionActivated(session);
}
}
}
public void fireSessionDeactivated(WebSocketSessionScope session)
{
if (scopeListeners != null)
{
for (WebSocketScopeListener listener : scopeListeners)
{
listener.onWebSocketSessionDeactivated(session);
}
}
}
public List<WebSocketScopeListener> getScopeListeners()
{
if (scopeListeners == null)
{
return Collections.emptyList();
}
return Collections.unmodifiableList(scopeListeners);
}
public void removeScopeListener(WebSocketScopeListener listener)
{
if (scopeListeners == null)
{
return;
}
scopeListeners.remove(listener);
}
}

View File

@ -16,27 +16,30 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.common.scopes;
package org.eclipse.jetty.websocket.common.util;
public interface WebSocketScopeListener
import java.io.Closeable;
public class ThreadClassLoaderScope implements Closeable
{
/**
* A WebSocket Container scope was created / activated
*/
void onWebSocketContainerActivated(WebSocketContainerScope scope);
private final ClassLoader old;
private final ClassLoader scopedClassLoader;
/**
* A WebSocket Container scope was stopped / deactivated
*/
void onWebSocketContainerDeactivated(WebSocketContainerScope scope);
public ThreadClassLoaderScope(ClassLoader cl)
{
old = Thread.currentThread().getContextClassLoader();
scopedClassLoader = cl;
Thread.currentThread().setContextClassLoader(scopedClassLoader);
}
/**
* A WebSocket Session scope was created / activated
*/
void onWebSocketSessionActivated(WebSocketSessionScope scope);
@Override
public void close()
{
Thread.currentThread().setContextClassLoader(old);
}
/**
* A WebSocket Session scope was stopped / deactivated
*/
void onWebSocketSessionDeactivated(WebSocketSessionScope scope);
public ClassLoader getScopedClassLoader()
{
return scopedClassLoader;
}
}

View File

@ -0,0 +1,78 @@
//
// ========================================================================
// Copyright (c) 1995-2015 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.common.util;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.Test;
public class ThreadClassLoaderScopeTest
{
private static class ClassLoaderFoo extends URLClassLoader
{
public ClassLoaderFoo()
{
super(new URL[0]);
}
}
private static class ClassLoaderBar extends URLClassLoader
{
public ClassLoaderBar()
{
super(new URL[0]);
}
}
@Test
public void testNormal()
{
try (ThreadClassLoaderScope scope = new ThreadClassLoaderScope(new ClassLoaderFoo()))
{
assertThat("ClassLoader in scope",Thread.currentThread().getContextClassLoader(),instanceOf(ClassLoaderFoo.class));
assertThat("Scoped ClassLoader",scope.getScopedClassLoader(),instanceOf(ClassLoaderFoo.class));
}
assertThat("ClassLoader after scope",Thread.currentThread().getContextClassLoader(),not(instanceOf(ClassLoaderFoo.class)));
}
@Test
public void testWithException()
{
try (ThreadClassLoaderScope scope = new ThreadClassLoaderScope(new ClassLoaderBar()))
{
assertThat("ClassLoader in 'scope'",Thread.currentThread().getContextClassLoader(),instanceOf(ClassLoaderBar.class));
assertThat("Scoped ClassLoader",scope.getScopedClassLoader(),instanceOf(ClassLoaderBar.class));
try (ThreadClassLoaderScope inner = new ThreadClassLoaderScope(new ClassLoaderFoo()))
{
assertThat("ClassLoader in 'inner'",Thread.currentThread().getContextClassLoader(),instanceOf(ClassLoaderFoo.class));
assertThat("Scoped ClassLoader",scope.getScopedClassLoader(),instanceOf(ClassLoaderFoo.class));
throw new RuntimeException("Intention exception");
}
}
catch (Throwable ignore)
{
/* ignore */
}
assertThat("ClassLoader after 'scope'",Thread.currentThread().getContextClassLoader(),not(instanceOf(ClassLoaderBar.class)));
}
}

View File

@ -66,8 +66,6 @@ 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.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketScopeEvents;
import org.eclipse.jetty.websocket.common.scopes.WebSocketScopeListener;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
@ -97,7 +95,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
private WebSocketCreator creator;
private List<Class<?>> registeredSocketClasses;
private DecoratedObjectFactory objectFactory;
private WebSocketScopeEvents scopeEvents = new WebSocketScopeEvents();
public WebSocketServerFactory()
{
@ -209,12 +206,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
}
}
@Override
public void addScopeListener(WebSocketScopeListener listener)
{
this.scopeEvents.addScopeListener(listener);
}
public void addSessionFactory(SessionFactory sessionFactory)
{
if (sessionFactories.contains(sessionFactory))
@ -325,8 +316,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
}
super.doStart();
scopeEvents.fireContainerActivated(this);
}
@Override
@ -334,8 +323,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
{
shutdownAllConnections();
super.doStop();
scopeEvents.fireContainerDeactivated(this);
}
@Override
@ -383,17 +370,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return defaultPolicy;
}
public WebSocketScopeEvents getScopeEvents()
{
return scopeEvents;
}
@Override
public List<WebSocketScopeListener> getScopeListeners()
{
return this.scopeEvents.getScopeListeners();
}
@Override
public SslContextFactory getSslContextFactory()
{
@ -540,12 +516,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
registeredSocketClasses.add(websocketPojo);
}
@Override
public void removeScopeListener(WebSocketScopeListener listener)
{
this.scopeEvents.removeScopeListener(listener);
}
@Override
public void setCreator(WebSocketCreator creator)
{