diff --git a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WebSocketBoundRequest.java b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/producers/JettyLogFactory.java similarity index 64% rename from jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WebSocketBoundRequest.java rename to jetty-cdi/src/main/java/org/eclipse/jetty/cdi/producers/JettyLogFactory.java index b6e83bf8402..1bc51372430 100644 --- a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WebSocketBoundRequest.java +++ b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/producers/JettyLogFactory.java @@ -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 - public Map getRequestMap() + @Produces + public Logger createLogger(InjectionPoint injectionPoint) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Map getSessionMap(boolean create) - { - // TODO Auto-generated method stub - return null; + return Log.getLogger(injectionPoint.getMember().getDeclaringClass()); } } diff --git a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WeldConversationContext.java b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WeldConversationContext.java deleted file mode 100644 index 2e6331fa1da..00000000000 --- a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WeldConversationContext.java +++ /dev/null @@ -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 - - } -} diff --git a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WeldRequestContext.java b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WeldRequestContext.java deleted file mode 100644 index 0c365990763..00000000000 --- a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WeldRequestContext.java +++ /dev/null @@ -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 - - } -} diff --git a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WeldScopeInitializer.java b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WeldScopeInitializer.java deleted file mode 100644 index 3207a57e47d..00000000000 --- a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WeldScopeInitializer.java +++ /dev/null @@ -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(); - } -} diff --git a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WeldSessionContext.java b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WeldSessionContext.java deleted file mode 100644 index dee4a891eb6..00000000000 --- a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/weld/WeldSessionContext.java +++ /dev/null @@ -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 - - } - -} diff --git a/jetty-cdi/src/test/java/org/eclipse/jetty/cdi/weld/WeldScopeInitializerTest.java b/jetty-cdi/src/test/java/org/eclipse/jetty/cdi/weld/WeldInitializationTest.java similarity index 98% rename from jetty-cdi/src/test/java/org/eclipse/jetty/cdi/weld/WeldScopeInitializerTest.java rename to jetty-cdi/src/test/java/org/eclipse/jetty/cdi/weld/WeldInitializationTest.java index 4917016f760..a538a80ca4c 100644 --- a/jetty-cdi/src/test/java/org/eclipse/jetty/cdi/weld/WeldScopeInitializerTest.java +++ b/jetty-cdi/src/test/java/org/eclipse/jetty/cdi/weld/WeldInitializationTest.java @@ -47,9 +47,9 @@ import org.junit.AfterClass; import org.junit.BeforeClass; 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 URI serverHttpURI; private static URI serverWebsocketURI; diff --git a/jetty-cdi/src/test/java/org/eclipse/jetty/cdi/weld/cdiapp/CdiInfoSocket.java b/jetty-cdi/src/test/java/org/eclipse/jetty/cdi/weld/cdiapp/CdiInfoSocket.java index a61cd481ca3..efb50fbf6e9 100644 --- a/jetty-cdi/src/test/java/org/eclipse/jetty/cdi/weld/cdiapp/CdiInfoSocket.java +++ b/jetty-cdi/src/test/java/org/eclipse/jetty/cdi/weld/cdiapp/CdiInfoSocket.java @@ -47,11 +47,6 @@ public class CdiInfoSocket private Session session; - public CdiInfoSocket() - { - Thread.dumpStack(); - } - @OnOpen public void onOpen(Session session) { @@ -76,8 +71,8 @@ public class CdiInfoSocket { case "info": out.printf("websocketSession is %s%n",asPresent(session)); - out.printf("httpSession: %s%n",asPresent(httpSession)); - out.printf("servletContext: %s%n",asPresent(servletContext)); + out.printf("httpSession is %s%n",asPresent(httpSession)); + out.printf("servletContext is %s%n",asPresent(servletContext)); break; } diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java index 29cbed496c5..42f4e548a97 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java @@ -88,7 +88,7 @@ public class ServletContextHandler extends ContextHandler public interface ServletContainerInitializerCaller extends LifeCycle {}; - protected final DecoratedObjectFactory _instantiator= new DecoratedObjectFactory(); + protected final DecoratedObjectFactory _objFactory = new DecoratedObjectFactory(); protected Class _defaultSecurityHandlerClass=org.eclipse.jetty.security.ConstraintSecurityHandler.class; protected SessionHandler _sessionHandler; protected SecurityHandler _securityHandler; @@ -252,7 +252,7 @@ public class ServletContextHandler extends ContextHandler @Override protected void doStart() throws Exception { - setAttribute(DecoratedObjectFactory.ATTR, _instantiator); + getServletContext().setAttribute(DecoratedObjectFactory.ATTR, _objFactory); super.doStart(); } @@ -264,7 +264,7 @@ public class ServletContextHandler extends ContextHandler protected void doStop() throws Exception { super.doStop(); - _instantiator.clear(); + _objFactory.clear(); } /* ------------------------------------------------------------ */ @@ -331,7 +331,7 @@ public class ServletContextHandler extends ContextHandler { for (ListenerHolder holder:_servletHandler.getListeners()) { - _instantiator.decorate(holder.getListener()); + _objFactory.decorate(holder.getListener()); } } } @@ -647,17 +647,28 @@ public class ServletContextHandler extends ContextHandler h.setHandler(handler); 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 - * @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 public List getDecorators() { List ret = new ArrayList(); - for (org.eclipse.jetty.util.Decorator decorator : _instantiator) + for (org.eclipse.jetty.util.Decorator decorator : _objFactory) { ret.add(new LegacyDecorator(decorator)); } @@ -667,31 +678,35 @@ public class ServletContextHandler extends ContextHandler /* ------------------------------------------------------------ */ /** * @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 decorators) { - _instantiator.setDecorators(decorators); + _objFactory.setDecorators(decorators); } /* ------------------------------------------------------------ */ /** * @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) { - _instantiator.addDecorator(decorator); + _objFactory.addDecorator(decorator); } /* ------------------------------------------------------------ */ void destroyServlet(Servlet servlet) { - _instantiator.destroy(servlet); + _objFactory.destroy(servlet); } /* ------------------------------------------------------------ */ void destroyFilter(Filter filter) { - _instantiator.destroy(filter); + _objFactory.destroy(filter); } /* ------------------------------------------------------------ */ @@ -1244,7 +1259,7 @@ public class ServletContextHandler extends ContextHandler try { T f = createInstance(c); - f = _instantiator.decorate(f); + f = _objFactory.decorate(f); return f; } catch (Exception e) @@ -1260,7 +1275,7 @@ public class ServletContextHandler extends ContextHandler try { T s = createInstance(c); - s = _instantiator.decorate(s); + s = _objFactory.decorate(s); return s; } catch (Exception e) @@ -1403,7 +1418,7 @@ public class ServletContextHandler extends ContextHandler try { T l = createInstance(clazz); - l = _instantiator.decorate(l); + l = _objFactory.decorate(l); return l; } catch (Exception e) diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java index 729e88e30de..3bc61e67f0b 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java @@ -18,15 +18,12 @@ package org.eclipse.jetty.servlet; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.notNullValue; -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 static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; import java.io.IOException; import java.io.PrintWriter; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; 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.gzip.GzipHandler; 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.junit.After; import org.junit.Assert; @@ -361,6 +360,59 @@ public class ServletContextHandlerTest Assert.assertThat(response, Matchers.containsString("404 Fell Through")); } + + /** + * 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) { @@ -391,6 +443,66 @@ public class ServletContextHandlerTest writer.write("Hello World"); } } + + public static class DummyUtilDecorator implements org.eclipse.jetty.util.Decorator + { + @Override + public 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 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 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 { diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/DecoratedObjectFactory.java b/jetty-util/src/main/java/org/eclipse/jetty/util/DecoratedObjectFactory.java index 5feb1c9e2bd..f409d76066a 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/DecoratedObjectFactory.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/DecoratedObjectFactory.java @@ -62,7 +62,7 @@ public class DecoratedObjectFactory implements Iterable { if (LOG.isDebugEnabled()) { - LOG.debug("Creating Instance: " + clazz,new Throwable("Creation Stack")); + LOG.debug("Creating Instance: " + clazz); } T o = clazz.newInstance(); return decorate(o); @@ -106,4 +106,14 @@ public class DecoratedObjectFactory implements Iterable 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(); + } } diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java index eff027094bb..84e668ace24 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java @@ -77,6 +77,8 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont { private static final Logger LOG = Log.getLogger(ClientContainer.class); + /** The delegated Container Scope */ + private final WebSocketContainerScope scopeDelegate; /** Tracking all primitive decoders for the container */ private final DecoderFactory decoderFactory; /** 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 */ private WebSocketClient client; - protected DecoratedObjectFactory objectFactory; - public ClientContainer() { // 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"); + this.scopeDelegate = scope; client = new WebSocketClient(scope, new SslContextFactory(trustAll)); client.setEventDriverFactory(new JsrEventDriverFactory(client.getPolicy())); 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.encoderFactory = new EncoderFactory(this,PrimitiveEncoderMetadataSet.INSTANCE); - EmptyClientEndpointConfig empty = new EmptyClientEndpointConfig(); - this.decoderFactory.init(empty); - this.encoderFactory.init(empty); - ShutdownThread.register(this); } @@ -196,7 +193,18 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont EndpointInstance instance = newClientEndpointInstance(endpoint,null); 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 protected void doStop() throws Exception { @@ -208,7 +216,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont @Override public ByteBufferPool getBufferPool() { - return client.getBufferPool(); + return scopeDelegate.getBufferPool(); } public WebSocketClient getClient() @@ -297,7 +305,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont @Override public Executor getExecutor() { - return client.getExecutor(); + return scopeDelegate.getExecutor(); } @Override @@ -317,7 +325,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont @Override public DecoratedObjectFactory getObjectFactory() { - return client.getObjectFactory(); + return scopeDelegate.getObjectFactory(); } /** @@ -331,13 +339,13 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont @Override public WebSocketPolicy getPolicy() { - return client.getPolicy(); + return scopeDelegate.getPolicy(); } @Override public SslContextFactory getSslContextFactory() { - return client.getSslContextFactory(); + return scopeDelegate.getSslContextFactory(); } private EndpointInstance newClientEndpointInstance(Class endpointClass, ClientEndpointConfig config) diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/DecoderFactory.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/DecoderFactory.java index 1459eda4dcd..71a3af770ed 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/DecoderFactory.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/DecoderFactory.java @@ -25,7 +25,6 @@ import java.util.concurrent.ConcurrentHashMap; import javax.websocket.Decoder; import javax.websocket.EndpointConfig; -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; @@ -76,7 +75,7 @@ public class DecoderFactory implements Configurable private static final Logger LOG = Log.getLogger(DecoderFactory.class); private final DecoderMetadataSet metadatas; - private final DecoratedObjectFactory objectFactory; + private final WebSocketContainerScope containerScope; private DecoderFactory parentFactory; private Map, Wrapper> activeWrappers; @@ -93,7 +92,7 @@ public class DecoderFactory implements Configurable protected DecoderFactory(WebSocketContainerScope containerScope, DecoderMetadataSet metadatas, DecoderFactory parentFactory) { Objects.requireNonNull(containerScope,"Container Scope cannot be null"); - this.objectFactory = containerScope.getObjectFactory(); + this.containerScope = containerScope; this.metadatas = metadatas; this.activeWrappers = new ConcurrentHashMap<>(); this.parentFactory = parentFactory; @@ -186,7 +185,7 @@ public class DecoderFactory implements Configurable Class decoderClass = metadata.getCoderClass(); try { - Decoder decoder = objectFactory.createInstance(decoderClass); + Decoder decoder = containerScope.getObjectFactory().createInstance(decoderClass); return new Wrapper(decoder,metadata); } catch (InstantiationException | IllegalAccessException e) diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/EncoderFactory.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/EncoderFactory.java index 4e18662b2b3..d5165d45a12 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/EncoderFactory.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/EncoderFactory.java @@ -25,7 +25,6 @@ import java.util.concurrent.ConcurrentHashMap; import javax.websocket.Encoder; import javax.websocket.EndpointConfig; -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; @@ -69,7 +68,7 @@ public class EncoderFactory implements Configurable private static final Logger LOG = Log.getLogger(EncoderFactory.class); private final EncoderMetadataSet metadatas; - private final DecoratedObjectFactory objectFactory; + private final WebSocketContainerScope containerScope; private EncoderFactory parentFactory; private Map, Wrapper> activeWrappers; @@ -86,7 +85,7 @@ public class EncoderFactory implements Configurable protected EncoderFactory(WebSocketContainerScope containerScope, EncoderMetadataSet metadatas, EncoderFactory parentFactory) { Objects.requireNonNull(containerScope,"Container Scope cannot be null"); - this.objectFactory = containerScope.getObjectFactory(); + this.containerScope = containerScope; this.metadatas = metadatas; this.activeWrappers = new ConcurrentHashMap<>(); this.parentFactory = parentFactory; @@ -179,7 +178,7 @@ public class EncoderFactory implements Configurable Class encoderClass = metadata.getCoderClass(); try { - Encoder encoder = objectFactory.createInstance(encoderClass); + Encoder encoder = containerScope.getObjectFactory().createInstance(encoderClass); return new Wrapper(encoder,metadata); } catch (InstantiationException | IllegalAccessException e) diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JettyClientContainerProvider.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JettyClientContainerProvider.java index eb043bcc46d..3fafe70a3ca 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JettyClientContainerProvider.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JettyClientContainerProvider.java @@ -22,16 +22,24 @@ import javax.websocket.ContainerProvider; import javax.websocket.WebSocketContainer; /** - * Client {@link ContainerProvider} implementation + * Client {@link ContainerProvider} implementation. + *

+ * Created by a {@link java.util.ServiceLoader} call in the + * {@link javax.websocket.ContainerProvider#getWebSocketContainer()} call. */ public class JettyClientContainerProvider extends ContainerProvider { + /** + * Used by {@link ContainerProvider#getWebSocketContainer()} to get a new instance + * of the Client {@link WebSocketContainer}. + */ @Override protected WebSocketContainer getContainer() { ClientContainer container = new ClientContainer(); try { + // We need to start this container properly. container.start(); return container; } diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/resources/jetty-logging.properties b/jetty-websocket/javax-websocket-client-impl/src/test/resources/jetty-logging.properties index d17e9c443a2..3acadb6cade 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/resources/jetty-logging.properties +++ b/jetty-websocket/javax-websocket-client-impl/src/test/resources/jetty-logging.properties @@ -1,5 +1,6 @@ org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog org.eclipse.jetty.LEVEL=WARN +# org.eclipse.jetty.websocket.LEVEL=INFO # org.eclipse.jetty.websocket.LEVEL=ALL # org.eclipse.jetty.websocket.jsr356.LEVEL=DEBUG diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/AnnotatedServerEndpointConfig.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/AnnotatedServerEndpointConfig.java index f6ae65b3e3f..3dc14762dc6 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/AnnotatedServerEndpointConfig.java +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/AnnotatedServerEndpointConfig.java @@ -122,7 +122,7 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig } else { - cfgr = new BasicServerEndpointConfigurator(containerScope); + cfgr = new ContainerDefaultConfigurator(); } } else @@ -144,7 +144,6 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig // Make sure all Configurators obtained are decorated this.configurator = containerScope.getObjectFactory().decorate(cfgr); - } @Override diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/BasicServerEndpointConfig.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/BasicServerEndpointConfig.java index 28f16ce1073..11569173501 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/BasicServerEndpointConfig.java +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/BasicServerEndpointConfig.java @@ -51,7 +51,7 @@ public class BasicServerEndpointConfig implements ServerEndpointConfig this.subprotocols = new ArrayList<>(); this.extensions = new ArrayList<>(); this.userProperties = new HashMap<>(); - this.configurator = new BasicServerEndpointConfigurator(containerScope); + this.configurator = new ContainerDefaultConfigurator(); } public BasicServerEndpointConfig(WebSocketContainerScope containerScope, ServerEndpointConfig copy) @@ -73,7 +73,7 @@ public class BasicServerEndpointConfig implements ServerEndpointConfig } else { - cfgr = new BasicServerEndpointConfigurator(containerScope); + cfgr = new ContainerDefaultConfigurator(); } // Make sure all Configurators obtained are decorated diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/BasicServerEndpointConfigurator.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/BasicServerEndpointConfigurator.java deleted file mode 100644 index 71000af8fd0..00000000000 --- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/BasicServerEndpointConfigurator.java +++ /dev/null @@ -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 getEndpointInstance(Class 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())); - } - } -} \ No newline at end of file diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ContainerDefaultConfigurator.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ContainerDefaultConfigurator.java index 07d8a26771c..4d0168811f8 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ContainerDefaultConfigurator.java +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ContainerDefaultConfigurator.java @@ -35,7 +35,7 @@ import org.eclipse.jetty.websocket.api.util.QuoteUtil; * * @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 String NO_SUBPROTOCOL = ""; diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java index 93d6659771b..1d32ed3f31b 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java @@ -25,6 +25,7 @@ import java.util.List; import javax.websocket.Extension; import javax.websocket.Extension.Parameter; import javax.websocket.server.ServerEndpointConfig; +import javax.websocket.server.ServerEndpointConfig.Configurator; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; @@ -137,7 +138,13 @@ public class JsrCreator implements WebSocketCreator try { 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(); if (pathSpec instanceof WebSocketPathSpec) { diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java index 6955bef201e..e1932d2a837 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java @@ -18,6 +18,8 @@ package org.eclipse.jetty.websocket.jsr356.server; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.Executor; import javax.websocket.DeploymentException; @@ -43,16 +45,19 @@ public class ServerContainer extends ClientContainer implements javax.websocket. private final MappedWebSocketCreator mappedCreator; private final WebSocketServerFactory webSocketServerFactory; + private List> deferredEndpointClasses; + private List deferredEndpointConfigs; public ServerContainer(MappedWebSocketCreator creator, WebSocketServerFactory factory, Executor executor) { - super(); + super(factory); this.mappedCreator = creator; this.webSocketServerFactory = factory; EventDriverFactory eventDriverFactory = this.webSocketServerFactory.getEventDriverFactory(); eventDriverFactory.addImplementation(new JsrServerEndpointImpl()); eventDriverFactory.addImplementation(new JsrServerExtendsEndpointImpl()); this.webSocketServerFactory.addSessionFactory(new JsrSessionFactory(this,this)); + addBean(webSocketServerFactory); } public EndpointInstance newClientEndpointInstance(Object endpoint, ServerEndpointConfig config, String path) @@ -76,11 +81,22 @@ public class ServerContainer extends ClientContainer implements javax.websocket. @Override public void addEndpoint(Class endpointClass) throws DeploymentException { - ServerEndpointMetadata metadata = getServerEndpointMetadata(endpointClass,null); - addEndpoint(metadata); + if (isStarted() || isStarting()) + { + ServerEndpointMetadata metadata = getServerEndpointMetadata(endpointClass,null); + addEndpoint(metadata); + } + else + { + if (deferredEndpointClasses == null) + { + deferredEndpointClasses = new ArrayList>(); + } + 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()); mappedCreator.addMapping(new WebSocketPathSpec(metadata.getPath()),creator); @@ -89,12 +105,50 @@ public class ServerContainer extends ClientContainer implements javax.websocket. @Override public void addEndpoint(ServerEndpointConfig config) throws DeploymentException { - if (LOG.isDebugEnabled()) + if (isStarted() || isStarting()) { - LOG.debug("addEndpoint({}) path={} endpoint={}",config,config.getPath(),config.getEndpointClass()); + if (LOG.isDebugEnabled()) + { + LOG.debug("addEndpoint({}) path={} endpoint={}",config,config.getPath(),config.getEndpointClass()); + } + ServerEndpointMetadata metadata = getServerEndpointMetadata(config.getEndpointClass(),config); + addEndpoint(metadata); } - ServerEndpointMetadata metadata = getServerEndpointMetadata(config.getEndpointClass(),config); - addEndpoint(metadata); + else + { + if (deferredEndpointConfigs == null) + { + deferredEndpointConfigs = new ArrayList(); + } + 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 diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java index b389ab0f277..76bd63d1bb4 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java @@ -58,7 +58,6 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context); // Create the Jetty ServerContainer implementation - filter.getFactory().init(context); ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),context.getServer().getThreadPool()); context.addBean(jettyContainer); @@ -79,7 +78,6 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context); // Create the Jetty ServerContainer implementation - filter.getFactory().init(context); ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),jettyContext.getServer().getThreadPool()); jettyContext.addBean(jettyContainer); diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java index 85aa4d187c2..1ca38057463 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java @@ -381,7 +381,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc 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) { this.objectFactory = new DecoratedObjectFactory(); diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java index f41e06260e4..9b9b113eba0 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java @@ -257,7 +257,8 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter try { - factory.init(config.getServletContext()); + ServletContext ctx = config.getServletContext(); + factory.init(ctx); WebSocketPolicy policy = factory.getPolicy(); String max = config.getInitParameter("maxIdleTime"); @@ -291,7 +292,7 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter key = WebSocketUpgradeFilter.class.getName(); } - setToAttribute(config.getServletContext(), key); + setToAttribute(ctx, key); factory.start(); } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsLegacyTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsLegacyTest.java new file mode 100644 index 00000000000..baf9388c681 --- /dev/null +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsLegacyTest.java @@ -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 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 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 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(); + } + } +} diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsTest.java new file mode 100644 index 00000000000..b1944c65904 --- /dev/null +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsTest.java @@ -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 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 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 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(); + } + } +} diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SimpleServletServer.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SimpleServletServer.java index 585a6807351..c4dc38dc3ea 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SimpleServletServer.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SimpleServletServer.java @@ -114,6 +114,7 @@ public class SimpleServletServer ServletContextHandler context = new ServletContextHandler(); context.setContextPath("/"); + configureServletContextHandler(context); server.setHandler(context); // Serve capture servlet @@ -138,6 +139,10 @@ public class SimpleServletServer } } + protected void configureServletContextHandler(ServletContextHandler context) + { + } + public void stop() { try diff --git a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServlet.java b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServlet.java index 106ff39cd80..3fc29c6d0f2 100644 --- a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServlet.java +++ b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServlet.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.servlet; import java.io.IOException; +import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -128,10 +129,12 @@ public abstract class WebSocketServlet extends HttpServlet factory = WebSocketServletFactory.Loader.create(policy); configure(factory); - - factory.init(getServletContext()); - getServletContext().setAttribute(WebSocketServletFactory.class.getName(),factory); + ServletContext ctx = getServletContext(); + + factory.init(ctx); + + ctx.setAttribute(WebSocketServletFactory.class.getName(),factory); } catch (Exception x) {