453834 - CDI Support for WebSocket

+ Verifying ServletContextHandler behavior of Decorators
+ Marking old ServletContextHandler methods as deprecated
+ Updates to DecoratedObjectFactory
+ Removing customized weld scopes/context (for now)
+ Deferring JSR356 ServerContainer endpoint init
  till Container.doStart() to allow weld to init properly first
+ Removing JSR356 BasicServerEndpointConfigurator in favor
  of ContainerDefaultEndpointConfigurator
+ Only decorating server endpoints if they were created by
  ContainerDefaultEndpointConfigurator, all others are trusted
  to be complete and injected already.
This commit is contained in:
Joakim Erdfelt 2015-01-30 15:13:35 -07:00
parent e213c4488e
commit 87246263b8
28 changed files with 655 additions and 347 deletions

View File

@ -16,25 +16,22 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.cdi.weld; package org.eclipse.jetty.cdi.producers;
import java.util.Map; import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import org.jboss.weld.context.bound.BoundRequest; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class WebSocketBoundRequest implements BoundRequest /**
* CDI Producer of Jetty Logging instances.
*/
public class JettyLogFactory
{ {
@Override @Produces
public Map<String, Object> getRequestMap() public Logger createLogger(InjectionPoint injectionPoint)
{ {
// TODO Auto-generated method stub return Log.getLogger(injectionPoint.getMember().getDeclaringClass());
return null;
}
@Override
public Map<String, Object> getSessionMap(boolean create)
{
// TODO Auto-generated method stub
return null;
} }
} }

View File

@ -1,41 +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.cdi.weld;
import org.jboss.weld.context.bound.BoundConversationContext;
public class WeldConversationContext
{
public static void activate(BoundConversationContext boundConversationContext)
{
// TODO Auto-generated method stub
}
public static void deactivate()
{
// TODO Auto-generated method stub
}
public static void invalidate()
{
// TODO Auto-generated method stub
}
}

View File

@ -1,41 +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.cdi.weld;
import org.jboss.weld.context.bound.BoundRequestContext;
public class WeldRequestContext
{
public static void activate(BoundRequestContext boundRequestContext)
{
// TODO Auto-generated method stub
}
public static void deactivate()
{
// TODO Auto-generated method stub
}
public static void invalidate()
{
// TODO Auto-generated method stub
}
}

View File

@ -1,77 +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.cdi.weld;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.jboss.weld.context.bound.BoundConversationContext;
import org.jboss.weld.context.bound.BoundRequestContext;
import org.jboss.weld.manager.BeanManagerImpl;
/**
* CDI/Weld scopes initialization of WebSocket specific Weld Contexts.
*/
public class WeldScopeInitializer
{
private static final Logger LOG = Log.getLogger(WeldScopeInitializer.class);
@Inject
private ServletContext servletContext;
@Inject
private BoundRequestContext boundRequestContext;
@Inject
private BoundConversationContext boundConversationContext;
@Inject
private BeanManagerImpl beanManager;
private WeldConversationContext conversationContext;
private WeldRequestContext requestContext;
private WeldSessionContext sessionCOntext;
public void activate(WebSocketContainerScope scope)
{
LOG.info("activate(WebSocketContainerScope:{})",scope);
WeldConversationContext.activate(boundConversationContext);
WeldSessionContext.activate(beanManager);
WeldRequestContext.activate(boundRequestContext);
}
public void deactivate(WebSocketContainerScope scope)
{
LOG.info("deactivate(WebSocketContainerScope:{})",scope);
WeldConversationContext.deactivate();
WeldSessionContext.deactivate();
WeldRequestContext.deactivate();
}
public void invalidate(WebSocketContainerScope scope)
{
LOG.info("invalidate(WebSocketContainerScope:{})",scope);
WeldConversationContext.invalidate();
WeldSessionContext.invalidate();
WeldRequestContext.invalidate();
}
}

View File

@ -1,44 +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.cdi.weld;
import org.jboss.weld.manager.BeanManagerImpl;
public class WeldSessionContext
{
public static void activate(BeanManagerImpl beanManager)
{
// TODO Auto-generated method stub
}
public static void deactivate()
{
// TODO Auto-generated method stub
}
public static void invalidate()
{
// TODO Auto-generated method stub
}
}

View File

@ -47,9 +47,9 @@ import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
public class WeldScopeInitializerTest public class WeldInitializationTest
{ {
private static final Logger LOG = Log.getLogger(WeldScopeInitializerTest.class); private static final Logger LOG = Log.getLogger(WeldInitializationTest.class);
private static Server server; private static Server server;
private static URI serverHttpURI; private static URI serverHttpURI;
private static URI serverWebsocketURI; private static URI serverWebsocketURI;

View File

@ -47,11 +47,6 @@ public class CdiInfoSocket
private Session session; private Session session;
public CdiInfoSocket()
{
Thread.dumpStack();
}
@OnOpen @OnOpen
public void onOpen(Session session) public void onOpen(Session session)
{ {
@ -76,8 +71,8 @@ public class CdiInfoSocket
{ {
case "info": case "info":
out.printf("websocketSession is %s%n",asPresent(session)); out.printf("websocketSession is %s%n",asPresent(session));
out.printf("httpSession: %s%n",asPresent(httpSession)); out.printf("httpSession is %s%n",asPresent(httpSession));
out.printf("servletContext: %s%n",asPresent(servletContext)); out.printf("servletContext is %s%n",asPresent(servletContext));
break; break;
} }

View File

@ -88,7 +88,7 @@ public class ServletContextHandler extends ContextHandler
public interface ServletContainerInitializerCaller extends LifeCycle {}; public interface ServletContainerInitializerCaller extends LifeCycle {};
protected final DecoratedObjectFactory _instantiator= new DecoratedObjectFactory(); protected final DecoratedObjectFactory _objFactory = new DecoratedObjectFactory();
protected Class<? extends SecurityHandler> _defaultSecurityHandlerClass=org.eclipse.jetty.security.ConstraintSecurityHandler.class; protected Class<? extends SecurityHandler> _defaultSecurityHandlerClass=org.eclipse.jetty.security.ConstraintSecurityHandler.class;
protected SessionHandler _sessionHandler; protected SessionHandler _sessionHandler;
protected SecurityHandler _securityHandler; protected SecurityHandler _securityHandler;
@ -252,7 +252,7 @@ public class ServletContextHandler extends ContextHandler
@Override @Override
protected void doStart() throws Exception protected void doStart() throws Exception
{ {
setAttribute(DecoratedObjectFactory.ATTR, _instantiator); getServletContext().setAttribute(DecoratedObjectFactory.ATTR, _objFactory);
super.doStart(); super.doStart();
} }
@ -264,7 +264,7 @@ public class ServletContextHandler extends ContextHandler
protected void doStop() throws Exception protected void doStop() throws Exception
{ {
super.doStop(); super.doStop();
_instantiator.clear(); _objFactory.clear();
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -331,7 +331,7 @@ public class ServletContextHandler extends ContextHandler
{ {
for (ListenerHolder holder:_servletHandler.getListeners()) for (ListenerHolder holder:_servletHandler.getListeners())
{ {
_instantiator.decorate(holder.getListener()); _objFactory.decorate(holder.getListener());
} }
} }
} }
@ -648,16 +648,27 @@ public class ServletContextHandler extends ContextHandler
relinkHandlers(); relinkHandlers();
} }
/* ------------------------------------------------------------ */
/**
* The DecoratedObjectFactory for use by IoC containers (weld / spring / etc)
*
* @return The DecoratedObjectFactory
*/
public DecoratedObjectFactory getObjectFactory()
{
return _objFactory;
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return The decorator list used to resource inject new Filters, Servlets and EventListeners * @return The decorator list used to resource inject new Filters, Servlets and EventListeners
* @deprecated use getAttribute("org.eclipse.jetty.util.DecoratedObjectFactory") instead * @deprecated use the {@link DecoratedObjectFactory} from getAttribute("org.eclipse.jetty.util.DecoratedObjectFactory") or {@link #getObjectFactory()} instead
*/ */
@Deprecated @Deprecated
public List<Decorator> getDecorators() public List<Decorator> getDecorators()
{ {
List<Decorator> ret = new ArrayList<ServletContextHandler.Decorator>(); List<Decorator> ret = new ArrayList<ServletContextHandler.Decorator>();
for (org.eclipse.jetty.util.Decorator decorator : _instantiator) for (org.eclipse.jetty.util.Decorator decorator : _objFactory)
{ {
ret.add(new LegacyDecorator(decorator)); ret.add(new LegacyDecorator(decorator));
} }
@ -667,31 +678,35 @@ public class ServletContextHandler extends ContextHandler
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param decorators The list of {@link Decorator}s * @param decorators The list of {@link Decorator}s
* @deprecated use the {@link DecoratedObjectFactory} from getAttribute("org.eclipse.jetty.util.DecoratedObjectFactory") or {@link #getObjectFactory()} instead
*/ */
@Deprecated
public void setDecorators(List<Decorator> decorators) public void setDecorators(List<Decorator> decorators)
{ {
_instantiator.setDecorators(decorators); _objFactory.setDecorators(decorators);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param decorator The decorator to add * @param decorator The decorator to add
* @deprecated use the {@link DecoratedObjectFactory} from getAttribute("org.eclipse.jetty.util.DecoratedObjectFactory") or {@link #getObjectFactory()} instead
*/ */
@Deprecated
public void addDecorator(Decorator decorator) public void addDecorator(Decorator decorator)
{ {
_instantiator.addDecorator(decorator); _objFactory.addDecorator(decorator);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
void destroyServlet(Servlet servlet) void destroyServlet(Servlet servlet)
{ {
_instantiator.destroy(servlet); _objFactory.destroy(servlet);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
void destroyFilter(Filter filter) void destroyFilter(Filter filter)
{ {
_instantiator.destroy(filter); _objFactory.destroy(filter);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -1244,7 +1259,7 @@ public class ServletContextHandler extends ContextHandler
try try
{ {
T f = createInstance(c); T f = createInstance(c);
f = _instantiator.decorate(f); f = _objFactory.decorate(f);
return f; return f;
} }
catch (Exception e) catch (Exception e)
@ -1260,7 +1275,7 @@ public class ServletContextHandler extends ContextHandler
try try
{ {
T s = createInstance(c); T s = createInstance(c);
s = _instantiator.decorate(s); s = _objFactory.decorate(s);
return s; return s;
} }
catch (Exception e) catch (Exception e)
@ -1403,7 +1418,7 @@ public class ServletContextHandler extends ContextHandler
try try
{ {
T l = createInstance(clazz); T l = createInstance(clazz);
l = _instantiator.decorate(l); l = _objFactory.decorate(l);
return l; return l;
} }
catch (Exception e) catch (Exception e)

View File

@ -18,15 +18,12 @@
package org.eclipse.jetty.servlet; package org.eclipse.jetty.servlet;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.*;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -52,6 +49,8 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.handler.ResourceHandler; import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.server.handler.gzip.GzipHandler; import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.Decorator;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
@ -362,6 +361,59 @@ public class ServletContextHandlerTest
} }
/**
* Test behavior of legacy {@link ServletContextHandler.Decorator}, with
* new DecoratedObjectFactory class
*/
@SuppressWarnings("deprecation")
@Test
public void testLegacyDecorator() throws Exception
{
ServletContextHandler context = new ServletContextHandler();
context.addDecorator(new DummyLegacyDecorator());
_server.setHandler(context);
context.addServlet(DecoratedObjectFactoryServlet.class, "/objfactory/*");
_server.start();
String response= _connector.getResponses("GET /objfactory/ HTTP/1.0\r\n\r\n");
assertThat("Response status code", response, containsString("200 OK"));
String expected = String.format("Attribute[%s] = %s", DecoratedObjectFactory.ATTR, DecoratedObjectFactory.class.getName());
assertThat("Has context attribute", response, containsString(expected));
assertThat("Decorators size", response, containsString("Decorators.size = [1]"));
expected = String.format("decorator[] = %s", DummyLegacyDecorator.class.getName());
assertThat("Specific Legacy Decorator", response, containsString(expected));
}
/**
* Test behavior of new {@link org.eclipse.jetty.util.Decorator}, with
* new DecoratedObjectFactory class
*/
@Test
public void testUtilDecorator() throws Exception
{
ServletContextHandler context = new ServletContextHandler();
context.getObjectFactory().addDecorator(new DummyUtilDecorator());
_server.setHandler(context);
context.addServlet(DecoratedObjectFactoryServlet.class, "/objfactory/*");
_server.start();
String response= _connector.getResponses("GET /objfactory/ HTTP/1.0\r\n\r\n");
assertThat("Response status code", response, containsString("200 OK"));
String expected = String.format("Attribute[%s] = %s", DecoratedObjectFactory.ATTR, DecoratedObjectFactory.class.getName());
assertThat("Has context attribute", response, containsString(expected));
assertThat("Decorators size", response, containsString("Decorators.size = [1]"));
expected = String.format("decorator[] = %s", DummyUtilDecorator.class.getName());
assertThat("Specific Legacy Decorator", response, containsString(expected));
}
private int assertResponseContains(String expected, String response) private int assertResponseContains(String expected, String response)
{ {
int idx = response.indexOf(expected); int idx = response.indexOf(expected);
@ -392,6 +444,66 @@ public class ServletContextHandlerTest
} }
} }
public static class DummyUtilDecorator implements org.eclipse.jetty.util.Decorator
{
@Override
public <T> T decorate(T o)
{
return o;
}
@Override
public void destroy(Object o)
{
}
}
public static class DummyLegacyDecorator implements org.eclipse.jetty.servlet.ServletContextHandler.Decorator
{
@Override
public <T> T decorate(T o)
{
return o;
}
@Override
public void destroy(Object o)
{
}
}
public static class DecoratedObjectFactoryServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
resp.setContentType("text/plain");
resp.setStatus(HttpServletResponse.SC_OK);
PrintWriter out = resp.getWriter();
Object obj = req.getServletContext().getAttribute(DecoratedObjectFactory.ATTR);
out.printf("Attribute[%s] = %s%n",DecoratedObjectFactory.ATTR,obj.getClass().getName());
if (obj instanceof DecoratedObjectFactory)
{
out.printf("Object is a DecoratedObjectFactory%n");
DecoratedObjectFactory objFactory = (DecoratedObjectFactory)obj;
List<Decorator> decorators = objFactory.getDecorators();
out.printf("Decorators.size = [%d]%n",decorators.size());
for (Decorator decorator : decorators)
{
out.printf(" decorator[] = %s%n",decorator.getClass().getName());
}
}
else
{
out.printf("Object is NOT a DecoratedObjectFactory%n");
}
}
}
public static class TestServlet extends HttpServlet public static class TestServlet extends HttpServlet
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -62,7 +62,7 @@ public class DecoratedObjectFactory implements Iterable<Decorator>
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
{ {
LOG.debug("Creating Instance: " + clazz,new Throwable("Creation Stack")); LOG.debug("Creating Instance: " + clazz);
} }
T o = clazz.newInstance(); T o = clazz.newInstance();
return decorate(o); return decorate(o);
@ -106,4 +106,14 @@ public class DecoratedObjectFactory implements Iterable<Decorator>
this.decorators.addAll(decorators); this.decorators.addAll(decorators);
} }
} }
@Override
public String toString()
{
StringBuilder str = new StringBuilder();
str.append(this.getClass().getName()).append("[decorators=");
str.append(Integer.toString(decorators.size()));
str.append("]");
return str.toString();
}
} }

View File

@ -77,6 +77,8 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
{ {
private static final Logger LOG = Log.getLogger(ClientContainer.class); private static final Logger LOG = Log.getLogger(ClientContainer.class);
/** The delegated Container Scope */
private final WebSocketContainerScope scopeDelegate;
/** Tracking all primitive decoders for the container */ /** Tracking all primitive decoders for the container */
private final DecoderFactory decoderFactory; private final DecoderFactory decoderFactory;
/** Tracking all primitive encoders for the container */ /** Tracking all primitive encoders for the container */
@ -89,8 +91,6 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
/** The jetty websocket client in use for this container */ /** The jetty websocket client in use for this container */
private WebSocketClient client; private WebSocketClient client;
protected DecoratedObjectFactory objectFactory;
public ClientContainer() public ClientContainer()
{ {
// This constructor is used with Standalone JSR Client usage. // This constructor is used with Standalone JSR Client usage.
@ -102,6 +102,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
{ {
boolean trustAll = Boolean.getBoolean("org.eclipse.jetty.websocket.jsr356.ssl-trust-all"); boolean trustAll = Boolean.getBoolean("org.eclipse.jetty.websocket.jsr356.ssl-trust-all");
this.scopeDelegate = scope;
client = new WebSocketClient(scope, new SslContextFactory(trustAll)); client = new WebSocketClient(scope, new SslContextFactory(trustAll));
client.setEventDriverFactory(new JsrEventDriverFactory(client.getPolicy())); client.setEventDriverFactory(new JsrEventDriverFactory(client.getPolicy()));
SessionFactory sessionFactory = new JsrSessionFactory(this,this,client); SessionFactory sessionFactory = new JsrSessionFactory(this,this,client);
@ -112,10 +113,6 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
this.decoderFactory = new DecoderFactory(this,PrimitiveDecoderMetadataSet.INSTANCE); this.decoderFactory = new DecoderFactory(this,PrimitiveDecoderMetadataSet.INSTANCE);
this.encoderFactory = new EncoderFactory(this,PrimitiveEncoderMetadataSet.INSTANCE); this.encoderFactory = new EncoderFactory(this,PrimitiveEncoderMetadataSet.INSTANCE);
EmptyClientEndpointConfig empty = new EmptyClientEndpointConfig();
this.decoderFactory.init(empty);
this.encoderFactory.init(empty);
ShutdownThread.register(this); ShutdownThread.register(this);
} }
@ -197,6 +194,17 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
return connect(instance,path); return connect(instance,path);
} }
@Override
protected void doStart() throws Exception
{
super.doStart();
// Initialize the default decoder / encoder factories
EmptyClientEndpointConfig empty = new EmptyClientEndpointConfig();
this.decoderFactory.init(empty);
this.encoderFactory.init(empty);
}
@Override @Override
protected void doStop() throws Exception protected void doStop() throws Exception
{ {
@ -208,7 +216,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
@Override @Override
public ByteBufferPool getBufferPool() public ByteBufferPool getBufferPool()
{ {
return client.getBufferPool(); return scopeDelegate.getBufferPool();
} }
public WebSocketClient getClient() public WebSocketClient getClient()
@ -297,7 +305,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
@Override @Override
public Executor getExecutor() public Executor getExecutor()
{ {
return client.getExecutor(); return scopeDelegate.getExecutor();
} }
@Override @Override
@ -317,7 +325,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
@Override @Override
public DecoratedObjectFactory getObjectFactory() public DecoratedObjectFactory getObjectFactory()
{ {
return client.getObjectFactory(); return scopeDelegate.getObjectFactory();
} }
/** /**
@ -331,13 +339,13 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
@Override @Override
public WebSocketPolicy getPolicy() public WebSocketPolicy getPolicy()
{ {
return client.getPolicy(); return scopeDelegate.getPolicy();
} }
@Override @Override
public SslContextFactory getSslContextFactory() public SslContextFactory getSslContextFactory()
{ {
return client.getSslContextFactory(); return scopeDelegate.getSslContextFactory();
} }
private EndpointInstance newClientEndpointInstance(Class<?> endpointClass, ClientEndpointConfig config) private EndpointInstance newClientEndpointInstance(Class<?> endpointClass, ClientEndpointConfig config)

View File

@ -25,7 +25,6 @@ import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.Decoder; import javax.websocket.Decoder;
import javax.websocket.EndpointConfig; import javax.websocket.EndpointConfig;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
@ -76,7 +75,7 @@ public class DecoderFactory implements Configurable
private static final Logger LOG = Log.getLogger(DecoderFactory.class); private static final Logger LOG = Log.getLogger(DecoderFactory.class);
private final DecoderMetadataSet metadatas; private final DecoderMetadataSet metadatas;
private final DecoratedObjectFactory objectFactory; private final WebSocketContainerScope containerScope;
private DecoderFactory parentFactory; private DecoderFactory parentFactory;
private Map<Class<?>, Wrapper> activeWrappers; private Map<Class<?>, Wrapper> activeWrappers;
@ -93,7 +92,7 @@ public class DecoderFactory implements Configurable
protected DecoderFactory(WebSocketContainerScope containerScope, DecoderMetadataSet metadatas, DecoderFactory parentFactory) protected DecoderFactory(WebSocketContainerScope containerScope, DecoderMetadataSet metadatas, DecoderFactory parentFactory)
{ {
Objects.requireNonNull(containerScope,"Container Scope cannot be null"); Objects.requireNonNull(containerScope,"Container Scope cannot be null");
this.objectFactory = containerScope.getObjectFactory(); this.containerScope = containerScope;
this.metadatas = metadatas; this.metadatas = metadatas;
this.activeWrappers = new ConcurrentHashMap<>(); this.activeWrappers = new ConcurrentHashMap<>();
this.parentFactory = parentFactory; this.parentFactory = parentFactory;
@ -186,7 +185,7 @@ public class DecoderFactory implements Configurable
Class<? extends Decoder> decoderClass = metadata.getCoderClass(); Class<? extends Decoder> decoderClass = metadata.getCoderClass();
try try
{ {
Decoder decoder = objectFactory.createInstance(decoderClass); Decoder decoder = containerScope.getObjectFactory().createInstance(decoderClass);
return new Wrapper(decoder,metadata); return new Wrapper(decoder,metadata);
} }
catch (InstantiationException | IllegalAccessException e) catch (InstantiationException | IllegalAccessException e)

View File

@ -25,7 +25,6 @@ import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.Encoder; import javax.websocket.Encoder;
import javax.websocket.EndpointConfig; import javax.websocket.EndpointConfig;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
@ -69,7 +68,7 @@ public class EncoderFactory implements Configurable
private static final Logger LOG = Log.getLogger(EncoderFactory.class); private static final Logger LOG = Log.getLogger(EncoderFactory.class);
private final EncoderMetadataSet metadatas; private final EncoderMetadataSet metadatas;
private final DecoratedObjectFactory objectFactory; private final WebSocketContainerScope containerScope;
private EncoderFactory parentFactory; private EncoderFactory parentFactory;
private Map<Class<?>, Wrapper> activeWrappers; private Map<Class<?>, Wrapper> activeWrappers;
@ -86,7 +85,7 @@ public class EncoderFactory implements Configurable
protected EncoderFactory(WebSocketContainerScope containerScope, EncoderMetadataSet metadatas, EncoderFactory parentFactory) protected EncoderFactory(WebSocketContainerScope containerScope, EncoderMetadataSet metadatas, EncoderFactory parentFactory)
{ {
Objects.requireNonNull(containerScope,"Container Scope cannot be null"); Objects.requireNonNull(containerScope,"Container Scope cannot be null");
this.objectFactory = containerScope.getObjectFactory(); this.containerScope = containerScope;
this.metadatas = metadatas; this.metadatas = metadatas;
this.activeWrappers = new ConcurrentHashMap<>(); this.activeWrappers = new ConcurrentHashMap<>();
this.parentFactory = parentFactory; this.parentFactory = parentFactory;
@ -179,7 +178,7 @@ public class EncoderFactory implements Configurable
Class<? extends Encoder> encoderClass = metadata.getCoderClass(); Class<? extends Encoder> encoderClass = metadata.getCoderClass();
try try
{ {
Encoder encoder = objectFactory.createInstance(encoderClass); Encoder encoder = containerScope.getObjectFactory().createInstance(encoderClass);
return new Wrapper(encoder,metadata); return new Wrapper(encoder,metadata);
} }
catch (InstantiationException | IllegalAccessException e) catch (InstantiationException | IllegalAccessException e)

View File

@ -22,16 +22,24 @@ import javax.websocket.ContainerProvider;
import javax.websocket.WebSocketContainer; import javax.websocket.WebSocketContainer;
/** /**
* Client {@link ContainerProvider} implementation * Client {@link ContainerProvider} implementation.
* <p>
* Created by a {@link java.util.ServiceLoader} call in the
* {@link javax.websocket.ContainerProvider#getWebSocketContainer()} call.
*/ */
public class JettyClientContainerProvider extends ContainerProvider public class JettyClientContainerProvider extends ContainerProvider
{ {
/**
* Used by {@link ContainerProvider#getWebSocketContainer()} to get a new instance
* of the Client {@link WebSocketContainer}.
*/
@Override @Override
protected WebSocketContainer getContainer() protected WebSocketContainer getContainer()
{ {
ClientContainer container = new ClientContainer(); ClientContainer container = new ClientContainer();
try try
{ {
// We need to start this container properly.
container.start(); container.start();
return container; return container;
} }

View File

@ -1,5 +1,6 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.LEVEL=WARN org.eclipse.jetty.LEVEL=WARN
# org.eclipse.jetty.websocket.LEVEL=INFO
# org.eclipse.jetty.websocket.LEVEL=ALL # org.eclipse.jetty.websocket.LEVEL=ALL
# org.eclipse.jetty.websocket.jsr356.LEVEL=DEBUG # org.eclipse.jetty.websocket.jsr356.LEVEL=DEBUG

View File

@ -122,7 +122,7 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
} }
else else
{ {
cfgr = new BasicServerEndpointConfigurator(containerScope); cfgr = new ContainerDefaultConfigurator();
} }
} }
else else
@ -144,7 +144,6 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
// Make sure all Configurators obtained are decorated // Make sure all Configurators obtained are decorated
this.configurator = containerScope.getObjectFactory().decorate(cfgr); this.configurator = containerScope.getObjectFactory().decorate(cfgr);
} }
@Override @Override

View File

@ -51,7 +51,7 @@ public class BasicServerEndpointConfig implements ServerEndpointConfig
this.subprotocols = new ArrayList<>(); this.subprotocols = new ArrayList<>();
this.extensions = new ArrayList<>(); this.extensions = new ArrayList<>();
this.userProperties = new HashMap<>(); this.userProperties = new HashMap<>();
this.configurator = new BasicServerEndpointConfigurator(containerScope); this.configurator = new ContainerDefaultConfigurator();
} }
public BasicServerEndpointConfig(WebSocketContainerScope containerScope, ServerEndpointConfig copy) public BasicServerEndpointConfig(WebSocketContainerScope containerScope, ServerEndpointConfig copy)
@ -73,7 +73,7 @@ public class BasicServerEndpointConfig implements ServerEndpointConfig
} }
else else
{ {
cfgr = new BasicServerEndpointConfigurator(containerScope); cfgr = new ContainerDefaultConfigurator();
} }
// Make sure all Configurators obtained are decorated // Make sure all Configurators obtained are decorated

View File

@ -1,57 +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.jsr356.server;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
/**
* The Basic Configurator
*/
public class BasicServerEndpointConfigurator extends ContainerDefaultConfigurator
{
private static final Logger LOG = Log.getLogger(BasicServerEndpointConfigurator.class);
private final DecoratedObjectFactory objectFactory;
public BasicServerEndpointConfigurator(WebSocketContainerScope containerScope)
{
super();
this.objectFactory = containerScope.getObjectFactory();
}
@Override
public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException
{
if (LOG.isDebugEnabled())
{
LOG.debug(".getEndpointInstance({})",endpointClass);
}
try
{
return objectFactory.createInstance(endpointClass);
}
catch (IllegalAccessException e)
{
throw new InstantiationException(String.format("%s: %s",e.getClass().getName(),e.getMessage()));
}
}
}

View File

@ -35,7 +35,7 @@ import org.eclipse.jetty.websocket.api.util.QuoteUtil;
* *
* @see ServiceLoader behavior of {@link ServerEndpointConfig.Configurator} * @see ServiceLoader behavior of {@link ServerEndpointConfig.Configurator}
*/ */
public class ContainerDefaultConfigurator extends Configurator public final class ContainerDefaultConfigurator extends Configurator
{ {
private static final Logger LOG = Log.getLogger(ContainerDefaultConfigurator.class); private static final Logger LOG = Log.getLogger(ContainerDefaultConfigurator.class);
private static final String NO_SUBPROTOCOL = ""; private static final String NO_SUBPROTOCOL = "";

View File

@ -25,6 +25,7 @@ import java.util.List;
import javax.websocket.Extension; import javax.websocket.Extension;
import javax.websocket.Extension.Parameter; import javax.websocket.Extension.Parameter;
import javax.websocket.server.ServerEndpointConfig; import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
@ -137,7 +138,13 @@ public class JsrCreator implements WebSocketCreator
try try
{ {
Class<?> endpointClass = config.getEndpointClass(); Class<?> endpointClass = config.getEndpointClass();
Object endpoint = config.getConfigurator().getEndpointInstance(endpointClass); Configurator configr = config.getConfigurator();
Object endpoint = configr.getEndpointInstance(endpointClass);
if (configr instanceof ContainerDefaultConfigurator)
{
// default impl always decorates (custom ones do not)
endpoint = containerScope.getObjectFactory().decorate(endpoint);
}
PathSpec pathSpec = hsreq.getRequestPathSpec(); PathSpec pathSpec = hsreq.getRequestPathSpec();
if (pathSpec instanceof WebSocketPathSpec) if (pathSpec instanceof WebSocketPathSpec)
{ {

View File

@ -18,6 +18,8 @@
package org.eclipse.jetty.websocket.jsr356.server; package org.eclipse.jetty.websocket.jsr356.server;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import javax.websocket.DeploymentException; import javax.websocket.DeploymentException;
@ -43,16 +45,19 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
private final MappedWebSocketCreator mappedCreator; private final MappedWebSocketCreator mappedCreator;
private final WebSocketServerFactory webSocketServerFactory; private final WebSocketServerFactory webSocketServerFactory;
private List<Class<?>> deferredEndpointClasses;
private List<ServerEndpointConfig> deferredEndpointConfigs;
public ServerContainer(MappedWebSocketCreator creator, WebSocketServerFactory factory, Executor executor) public ServerContainer(MappedWebSocketCreator creator, WebSocketServerFactory factory, Executor executor)
{ {
super(); super(factory);
this.mappedCreator = creator; this.mappedCreator = creator;
this.webSocketServerFactory = factory; this.webSocketServerFactory = factory;
EventDriverFactory eventDriverFactory = this.webSocketServerFactory.getEventDriverFactory(); EventDriverFactory eventDriverFactory = this.webSocketServerFactory.getEventDriverFactory();
eventDriverFactory.addImplementation(new JsrServerEndpointImpl()); eventDriverFactory.addImplementation(new JsrServerEndpointImpl());
eventDriverFactory.addImplementation(new JsrServerExtendsEndpointImpl()); eventDriverFactory.addImplementation(new JsrServerExtendsEndpointImpl());
this.webSocketServerFactory.addSessionFactory(new JsrSessionFactory(this,this)); this.webSocketServerFactory.addSessionFactory(new JsrSessionFactory(this,this));
addBean(webSocketServerFactory);
} }
public EndpointInstance newClientEndpointInstance(Object endpoint, ServerEndpointConfig config, String path) public EndpointInstance newClientEndpointInstance(Object endpoint, ServerEndpointConfig config, String path)
@ -75,12 +80,23 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
@Override @Override
public void addEndpoint(Class<?> endpointClass) throws DeploymentException public void addEndpoint(Class<?> endpointClass) throws DeploymentException
{
if (isStarted() || isStarting())
{ {
ServerEndpointMetadata metadata = getServerEndpointMetadata(endpointClass,null); ServerEndpointMetadata metadata = getServerEndpointMetadata(endpointClass,null);
addEndpoint(metadata); addEndpoint(metadata);
} }
else
{
if (deferredEndpointClasses == null)
{
deferredEndpointClasses = new ArrayList<Class<?>>();
}
deferredEndpointClasses.add(endpointClass);
}
}
public void addEndpoint(ServerEndpointMetadata metadata) throws DeploymentException private void addEndpoint(ServerEndpointMetadata metadata) throws DeploymentException
{ {
JsrCreator creator = new JsrCreator(this,metadata,webSocketServerFactory.getExtensionFactory()); JsrCreator creator = new JsrCreator(this,metadata,webSocketServerFactory.getExtensionFactory());
mappedCreator.addMapping(new WebSocketPathSpec(metadata.getPath()),creator); mappedCreator.addMapping(new WebSocketPathSpec(metadata.getPath()),creator);
@ -88,6 +104,8 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
@Override @Override
public void addEndpoint(ServerEndpointConfig config) throws DeploymentException public void addEndpoint(ServerEndpointConfig config) throws DeploymentException
{
if (isStarted() || isStarting())
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
{ {
@ -96,6 +114,42 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
ServerEndpointMetadata metadata = getServerEndpointMetadata(config.getEndpointClass(),config); ServerEndpointMetadata metadata = getServerEndpointMetadata(config.getEndpointClass(),config);
addEndpoint(metadata); addEndpoint(metadata);
} }
else
{
if (deferredEndpointConfigs == null)
{
deferredEndpointConfigs = new ArrayList<ServerEndpointConfig>();
}
deferredEndpointConfigs.add(config);
}
}
@Override
protected void doStart() throws Exception
{
// Proceed with Normal Startup
super.doStart();
// Process Deferred Endpoints
if (deferredEndpointClasses != null)
{
for (Class<?> endpointClass : deferredEndpointClasses)
{
addEndpoint(endpointClass);
}
}
if (deferredEndpointConfigs != null)
{
for (ServerEndpointConfig config : deferredEndpointConfigs)
{
addEndpoint(config);
}
}
deferredEndpointClasses.clear();
deferredEndpointConfigs.clear();
}
public ServerEndpointMetadata getServerEndpointMetadata(final Class<?> endpoint, final ServerEndpointConfig config) throws DeploymentException public ServerEndpointMetadata getServerEndpointMetadata(final Class<?> endpoint, final ServerEndpointConfig config) throws DeploymentException
{ {

View File

@ -58,7 +58,6 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context); WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context);
// Create the Jetty ServerContainer implementation // Create the Jetty ServerContainer implementation
filter.getFactory().init(context);
ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),context.getServer().getThreadPool()); ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),context.getServer().getThreadPool());
context.addBean(jettyContainer); context.addBean(jettyContainer);
@ -79,7 +78,6 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context); WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context);
// Create the Jetty ServerContainer implementation // Create the Jetty ServerContainer implementation
filter.getFactory().init(context);
ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),jettyContext.getServer().getThreadPool()); ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),jettyContext.getServer().getThreadPool());
jettyContext.addBean(jettyContainer); jettyContext.addBean(jettyContainer);

View File

@ -381,7 +381,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
public void init(ServletContextHandler context) throws ServletException public void init(ServletContextHandler context) throws ServletException
{ {
this.objectFactory = (DecoratedObjectFactory)context.getAttribute(DecoratedObjectFactory.ATTR); this.objectFactory = (DecoratedObjectFactory)context.getServletContext().getAttribute(DecoratedObjectFactory.ATTR);
if (this.objectFactory == null) if (this.objectFactory == null)
{ {
this.objectFactory = new DecoratedObjectFactory(); this.objectFactory = new DecoratedObjectFactory();

View File

@ -257,7 +257,8 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
try try
{ {
factory.init(config.getServletContext()); ServletContext ctx = config.getServletContext();
factory.init(ctx);
WebSocketPolicy policy = factory.getPolicy(); WebSocketPolicy policy = factory.getPolicy();
String max = config.getInitParameter("maxIdleTime"); String max = config.getInitParameter("maxIdleTime");
@ -291,7 +292,7 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
key = WebSocketUpgradeFilter.class.getName(); key = WebSocketUpgradeFilter.class.getName();
} }
setToAttribute(config.getServletContext(), key); setToAttribute(ctx, key);
factory.start(); factory.start();
} }

View File

@ -0,0 +1,179 @@
//
// ========================================================================
// 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.server;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContext;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.toolchain.test.EventQueue;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.Decorator;
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.common.test.BlockheadClient;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
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.Test;
public class DecoratorsLegacyTest
{
private static class DecoratorsSocket extends WebSocketAdapter
{
private final DecoratedObjectFactory objFactory;
public DecoratorsSocket(DecoratedObjectFactory objFactory)
{
this.objFactory = objFactory;
}
@Override
public void onWebSocketText(String message)
{
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
if (objFactory != null)
{
out.printf("Object is a DecoratedObjectFactory%n");
List<Decorator> decorators = objFactory.getDecorators();
out.printf("Decorators.size = [%d]%n",decorators.size());
for (Decorator decorator : decorators)
{
out.printf(" decorator[] = %s%n",decorator.getClass().getName());
}
}
else
{
out.printf("DecoratedObjectFactory is NULL%n");
}
getRemote().sendStringByFuture(str.toString());
}
}
private static class DecoratorsCreator implements WebSocketCreator
{
@Override
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
{
ServletContext servletContext = req.getHttpServletRequest().getServletContext();
DecoratedObjectFactory objFactory = (DecoratedObjectFactory)servletContext.getAttribute(DecoratedObjectFactory.ATTR);
return new DecoratorsSocket(objFactory);
}
}
public static class DecoratorsRequestServlet extends WebSocketServlet
{
private static final long serialVersionUID = 1L;
private final WebSocketCreator creator;
public DecoratorsRequestServlet(WebSocketCreator creator)
{
this.creator = creator;
}
@Override
public void configure(WebSocketServletFactory factory)
{
factory.setCreator(this.creator);
}
}
private static class DummyLegacyDecorator implements org.eclipse.jetty.servlet.ServletContextHandler.Decorator
{
@Override
public <T> T decorate(T o)
{
return o;
}
@Override
public void destroy(Object o)
{
}
}
private static SimpleServletServer server;
private static DecoratorsCreator decoratorsCreator;
@BeforeClass
public static void startServer() throws Exception
{
decoratorsCreator = new DecoratorsCreator();
server = new SimpleServletServer(new DecoratorsRequestServlet(decoratorsCreator))
{
@SuppressWarnings("deprecation")
@Override
protected void configureServletContextHandler(ServletContextHandler context)
{
// Add decorator in the legacy way
context.addDecorator(new DummyLegacyDecorator());
}
};
server.start();
}
@AfterClass
public static void stopServer()
{
server.stop();
}
@Test
public void testAccessRequestCookies() throws Exception
{
BlockheadClient client = new BlockheadClient(server.getServerUri());
client.setTimeout(1,TimeUnit.SECONDS);
try
{
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
client.write(new TextFrame().setPayload("info"));
EventQueue<WebSocketFrame> frames = client.readFrames(1,1,TimeUnit.SECONDS);
WebSocketFrame resp = frames.poll();
String textMsg = resp.getPayloadAsUTF8();
assertThat("DecoratedObjectFactory", textMsg, containsString("Object is a DecoratedObjectFactory"));
assertThat("decorators.size", textMsg, containsString("Decorators.size = [1]"));
assertThat("decorator type", textMsg, containsString("decorator[] = " + DummyLegacyDecorator.class.getName()));
}
finally
{
client.close();
}
}
}

View File

@ -0,0 +1,178 @@
//
// ========================================================================
// 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.server;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContext;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.toolchain.test.EventQueue;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.Decorator;
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.common.test.BlockheadClient;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
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.Test;
public class DecoratorsTest
{
private static class DecoratorsSocket extends WebSocketAdapter
{
private final DecoratedObjectFactory objFactory;
public DecoratorsSocket(DecoratedObjectFactory objFactory)
{
this.objFactory = objFactory;
}
@Override
public void onWebSocketText(String message)
{
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
if (objFactory != null)
{
out.printf("Object is a DecoratedObjectFactory%n");
List<Decorator> decorators = objFactory.getDecorators();
out.printf("Decorators.size = [%d]%n",decorators.size());
for (Decorator decorator : decorators)
{
out.printf(" decorator[] = %s%n",decorator.getClass().getName());
}
}
else
{
out.printf("DecoratedObjectFactory is NULL%n");
}
getRemote().sendStringByFuture(str.toString());
}
}
private static class DecoratorsCreator implements WebSocketCreator
{
@Override
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
{
ServletContext servletContext = req.getHttpServletRequest().getServletContext();
DecoratedObjectFactory objFactory = (DecoratedObjectFactory)servletContext.getAttribute(DecoratedObjectFactory.ATTR);
return new DecoratorsSocket(objFactory);
}
}
public static class DecoratorsRequestServlet extends WebSocketServlet
{
private static final long serialVersionUID = 1L;
private final WebSocketCreator creator;
public DecoratorsRequestServlet(WebSocketCreator creator)
{
this.creator = creator;
}
@Override
public void configure(WebSocketServletFactory factory)
{
factory.setCreator(this.creator);
}
}
private static class DummyUtilDecorator implements org.eclipse.jetty.util.Decorator
{
@Override
public <T> T decorate(T o)
{
return o;
}
@Override
public void destroy(Object o)
{
}
}
private static SimpleServletServer server;
private static DecoratorsCreator decoratorsCreator;
@BeforeClass
public static void startServer() throws Exception
{
decoratorsCreator = new DecoratorsCreator();
server = new SimpleServletServer(new DecoratorsRequestServlet(decoratorsCreator))
{
@Override
protected void configureServletContextHandler(ServletContextHandler context)
{
// Add decorator in the new util way
context.getObjectFactory().addDecorator(new DummyUtilDecorator());
}
};
server.start();
}
@AfterClass
public static void stopServer()
{
server.stop();
}
@Test
public void testAccessRequestCookies() throws Exception
{
BlockheadClient client = new BlockheadClient(server.getServerUri());
client.setTimeout(1,TimeUnit.SECONDS);
try
{
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
client.write(new TextFrame().setPayload("info"));
EventQueue<WebSocketFrame> frames = client.readFrames(1,1,TimeUnit.SECONDS);
WebSocketFrame resp = frames.poll();
String textMsg = resp.getPayloadAsUTF8();
assertThat("DecoratedObjectFactory", textMsg, containsString("Object is a DecoratedObjectFactory"));
assertThat("decorators.size", textMsg, containsString("Decorators.size = [1]"));
assertThat("decorator type", textMsg, containsString("decorator[] = " + DummyUtilDecorator.class.getName()));
}
finally
{
client.close();
}
}
}

View File

@ -114,6 +114,7 @@ public class SimpleServletServer
ServletContextHandler context = new ServletContextHandler(); ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/"); context.setContextPath("/");
configureServletContextHandler(context);
server.setHandler(context); server.setHandler(context);
// Serve capture servlet // Serve capture servlet
@ -138,6 +139,10 @@ public class SimpleServletServer
} }
} }
protected void configureServletContextHandler(ServletContextHandler context)
{
}
public void stop() public void stop()
{ {
try try

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.servlet;
import java.io.IOException; import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -129,9 +130,11 @@ public abstract class WebSocketServlet extends HttpServlet
configure(factory); configure(factory);
factory.init(getServletContext()); ServletContext ctx = getServletContext();
getServletContext().setAttribute(WebSocketServletFactory.class.getName(),factory); factory.init(ctx);
ctx.setAttribute(WebSocketServletFactory.class.getName(),factory);
} }
catch (Exception x) catch (Exception x)
{ {