453834 - CDI Support for WebSocket

+ Adding scopes to websocket to help with CDI integration
This commit is contained in:
Joakim Erdfelt 2014-12-19 13:54:34 -07:00
parent 0c930c8640
commit 1f3097ff16
45 changed files with 717 additions and 311 deletions

View File

@ -40,6 +40,7 @@ import javax.websocket.Extension;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
@ -47,6 +48,7 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.ShutdownThread;
import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
@ -54,6 +56,8 @@ import org.eclipse.jetty.websocket.client.io.UpgradeListener;
import org.eclipse.jetty.websocket.common.SessionFactory;
import org.eclipse.jetty.websocket.common.SessionListener;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
import org.eclipse.jetty.websocket.jsr356.client.AnnotatedClientEndpointMetadata;
import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig;
@ -69,7 +73,7 @@ import org.eclipse.jetty.websocket.jsr356.metadata.EndpointMetadata;
* <p>
* This should be specific to a JVM if run in a standalone mode. or specific to a WebAppContext if running on the Jetty server.
*/
public class ClientContainer extends ContainerLifeCycle implements WebSocketContainer, SessionListener
public class ClientContainer extends ContainerLifeCycle implements WebSocketContainer, WebSocketContainerScope, SessionListener
{
private static final Logger LOG = Log.getLogger(ClientContainer.class);
@ -90,30 +94,28 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
public ClientContainer()
{
// This constructor is used with Standalone JSR Client usage.
this(null,new DecoratedObjectFactory());
this(new SimpleContainerScope(WebSocketPolicy.newClientPolicy()));
client.setDaemon(true);
}
public ClientContainer(Executor executor, DecoratedObjectFactory objectFactory)
public ClientContainer(WebSocketContainerScope scope)
{
this.objectFactory = objectFactory;
boolean trustAll = Boolean.getBoolean("org.eclipse.jetty.websocket.jsr356.ssl-trust-all");
client = new WebSocketClient(scope, new SslContextFactory(trustAll));
client.setEventDriverFactory(new JsrEventDriverFactory(client.getPolicy()));
SessionFactory sessionFactory = new JsrSessionFactory(this,this,client);
client.setSessionFactory(sessionFactory);
addBean(client);
this.endpointClientMetadataCache = new ConcurrentHashMap<>();
this.decoderFactory = new DecoderFactory(PrimitiveDecoderMetadataSet.INSTANCE,null,objectFactory);
this.encoderFactory = new EncoderFactory(PrimitiveEncoderMetadataSet.INSTANCE,null,objectFactory);
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);
boolean trustAll = Boolean.getBoolean("org.eclipse.jetty.websocket.jsr356.ssl-trust-all");
client = new WebSocketClient(new SslContextFactory(trustAll), executor);
client.setEventDriverFactory(new JsrEventDriverFactory(client.getPolicy()));
SessionFactory sessionFactory = new JsrSessionFactory(this,this,client);
sessionFactory.setEnhancedInstantiator(objectFactory);
client.setSessionFactory(sessionFactory);
addBean(client);
ShutdownThread.register(this);
}
@ -203,6 +205,12 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
super.doStop();
}
@Override
public ByteBufferPool getBufferPool()
{
return client.getBufferPool();
}
public WebSocketClient getClient()
{
return client;
@ -286,6 +294,12 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
return encoderFactory;
}
@Override
public Executor getExecutor()
{
return client.getExecutor();
}
@Override
public Set<Extension> getInstalledExtensions()
{
@ -300,6 +314,12 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
return ret;
}
@Override
public DecoratedObjectFactory getObjectFactory()
{
return client.getObjectFactory();
}
/**
* Used in {@link Session#getOpenSessions()}
*/
@ -308,6 +328,18 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
return Collections.unmodifiableSet(this.openSessions);
}
@Override
public WebSocketPolicy getPolicy()
{
return client.getPolicy();
}
@Override
public SslContextFactory getSslContextFactory()
{
return client.getSslContextFactory();
}
private EndpointInstance newClientEndpointInstance(Class<?> endpointClass, ClientEndpointConfig config)
{
try

View File

@ -28,6 +28,8 @@ 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;
import org.eclipse.jetty.websocket.common.scopes.WebSocketSessionScope;
import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadata;
import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadataSet;
@ -78,19 +80,23 @@ public class DecoderFactory implements Configurable
private DecoderFactory parentFactory;
private Map<Class<?>, Wrapper> activeWrappers;
public DecoderFactory(DecoderMetadataSet metadatas)
public DecoderFactory(WebSocketContainerScope containerScope, DecoderMetadataSet metadatas)
{
this(metadatas, null, new DecoratedObjectFactory());
this(containerScope,metadatas,null);
}
public DecoderFactory(DecoderMetadataSet metadatas, DecoderFactory parentFactory, DecoratedObjectFactory objectFactory)
public DecoderFactory(WebSocketSessionScope sessionScope, DecoderMetadataSet metadatas, DecoderFactory parentFactory)
{
this(sessionScope.getContainerScope(),metadatas,parentFactory);
}
protected DecoderFactory(WebSocketContainerScope containerScope, DecoderMetadataSet metadatas, DecoderFactory parentFactory)
{
Objects.requireNonNull(containerScope,"Container Scope cannot be null");
this.objectFactory = containerScope.getObjectFactory();
this.metadatas = metadatas;
this.activeWrappers = new ConcurrentHashMap<>();
this.parentFactory = parentFactory;
Objects.requireNonNull(objectFactory,"EnhancedInitiator cannot be null");
this.objectFactory = objectFactory;
}
public Decoder getDecoderFor(Class<?> type)
@ -109,6 +115,7 @@ public class DecoderFactory implements Configurable
{
LOG.debug("getMetadataFor({})",type);
}
DecoderMetadata metadata = metadatas.getMetadataByType(type);
if (metadata != null)

View File

@ -28,6 +28,8 @@ 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;
import org.eclipse.jetty.websocket.common.scopes.WebSocketSessionScope;
import org.eclipse.jetty.websocket.jsr356.metadata.EncoderMetadata;
import org.eclipse.jetty.websocket.jsr356.metadata.EncoderMetadataSet;
@ -71,19 +73,23 @@ public class EncoderFactory implements Configurable
private EncoderFactory parentFactory;
private Map<Class<?>, Wrapper> activeWrappers;
public EncoderFactory(EncoderMetadataSet metadatas)
public EncoderFactory(WebSocketContainerScope containerScope, EncoderMetadataSet metadatas)
{
this(metadatas,null,new DecoratedObjectFactory());
this(containerScope,metadatas,null);
}
public EncoderFactory(EncoderMetadataSet metadatas, EncoderFactory parentFactory, DecoratedObjectFactory objectFactory)
public EncoderFactory(WebSocketSessionScope sessionScope, EncoderMetadataSet metadatas, EncoderFactory parentFactory)
{
this(sessionScope.getContainerScope(),metadatas,parentFactory);
}
protected EncoderFactory(WebSocketContainerScope containerScope, EncoderMetadataSet metadatas, EncoderFactory parentFactory)
{
Objects.requireNonNull(containerScope,"Container Scope cannot be null");
this.objectFactory = containerScope.getObjectFactory();
this.metadatas = metadatas;
this.activeWrappers = new ConcurrentHashMap<>();
this.parentFactory = parentFactory;
Objects.requireNonNull(objectFactory,"EnhancedInitiator cannot be null");
this.objectFactory = objectFactory;
}
public Encoder getEncoderFor(Class<?> type)

View File

@ -39,7 +39,6 @@ import javax.websocket.RemoteEndpoint.Basic;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
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.api.BatchMode;
@ -75,9 +74,9 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess
private JsrAsyncRemote asyncRemote;
private JsrBasicRemote basicRemote;
public JsrSession(URI requestURI, EventDriver websocket, LogicalConnection connection, ClientContainer container, String id, DecoratedObjectFactory objectFactory, SessionListener... sessionListeners)
public JsrSession(ClientContainer container, String id, URI requestURI, EventDriver websocket, LogicalConnection connection, SessionListener... sessionListeners)
{
super(requestURI, websocket, connection, sessionListeners);
super(container, requestURI, websocket, connection, sessionListeners);
if (!(websocket instanceof AbstractJsrEventDriver))
{
throw new IllegalArgumentException("Cannot use, not a JSR WebSocket: " + websocket);
@ -87,8 +86,8 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess
this.metadata = jsr.getMetadata();
this.container = container;
this.id = id;
this.decoderFactory = new DecoderFactory(metadata.getDecoders(),container.getDecoderFactory(),objectFactory);
this.encoderFactory = new EncoderFactory(metadata.getEncoders(),container.getEncoderFactory(),objectFactory);
this.decoderFactory = new DecoderFactory(this,metadata.getDecoders(),container.getDecoderFactory());
this.encoderFactory = new EncoderFactory(this,metadata.getEncoders(),container.getEncoderFactory());
this.messageHandlerFactory = new MessageHandlerFactory();
this.wrappers = new MessageHandlerWrapper[MessageType.values().length];
this.messageHandlerSet = new HashSet<>();

View File

@ -21,7 +21,6 @@ package org.eclipse.jetty.websocket.jsr356;
import java.net.URI;
import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.common.LogicalConnection;
import org.eclipse.jetty.websocket.common.SessionFactory;
import org.eclipse.jetty.websocket.common.SessionListener;
@ -32,7 +31,6 @@ import org.eclipse.jetty.websocket.jsr356.endpoints.AbstractJsrEventDriver;
public class JsrSessionFactory implements SessionFactory
{
private AtomicLong idgen = new AtomicLong(0);
private DecoratedObjectFactory objectFactory;
private final ClientContainer container;
private final SessionListener[] listeners;
@ -40,13 +38,12 @@ public class JsrSessionFactory implements SessionFactory
{
this.container = container;
this.listeners = sessionListeners;
this.objectFactory = new DecoratedObjectFactory();
}
@Override
public WebSocketSession createSession(URI requestURI, EventDriver websocket, LogicalConnection connection)
{
return new JsrSession(requestURI,websocket,connection,container,getNextId(),objectFactory,listeners);
return new JsrSession(container,getNextId(),requestURI,websocket,connection,listeners);
}
public String getNextId()
@ -59,10 +56,4 @@ public class JsrSessionFactory implements SessionFactory
{
return (websocket instanceof AbstractJsrEventDriver);
}
@Override
public void setEnhancedInstantiator(DecoratedObjectFactory objectFactory)
{
this.objectFactory = objectFactory;
}
}

View File

@ -18,14 +18,16 @@
package org.eclipse.jetty.websocket.jsr356;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.*;
import java.nio.ByteBuffer;
import java.util.Date;
import javax.websocket.Decoder;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.jsr356.decoders.ByteArrayDecoder;
import org.eclipse.jetty.websocket.jsr356.decoders.ByteBufferDecoder;
import org.eclipse.jetty.websocket.jsr356.decoders.DateDecoder;
@ -57,9 +59,11 @@ public class DecoderFactoryTest
@Before
public void initDecoderFactory()
{
DecoderFactory primitivesFactory = new DecoderFactory(PrimitiveDecoderMetadataSet.INSTANCE);
WebSocketContainerScope containerScope = new SimpleContainerScope(WebSocketPolicy.newClientPolicy());
DecoderFactory primitivesFactory = new DecoderFactory(containerScope,PrimitiveDecoderMetadataSet.INSTANCE);
metadatas = new DecoderMetadataSet();
factory = new DecoderFactory(metadatas,primitivesFactory,new DecoratedObjectFactory());
factory = new DecoderFactory(containerScope,metadatas,primitivesFactory);
}
@Test

View File

@ -22,7 +22,9 @@ import static org.hamcrest.Matchers.*;
import javax.websocket.Encoder;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.jsr356.encoders.IntegerEncoder;
import org.eclipse.jetty.websocket.jsr356.encoders.LongEncoder;
import org.eclipse.jetty.websocket.jsr356.encoders.PrimitiveEncoderMetadataSet;
@ -54,9 +56,11 @@ public class EncoderFactoryTest
@Before
public void initEncoderFactory()
{
EncoderFactory primitivesFactory = new EncoderFactory(PrimitiveEncoderMetadataSet.INSTANCE);
WebSocketContainerScope containerScope = new SimpleContainerScope(WebSocketPolicy.newClientPolicy());
EncoderFactory primitivesFactory = new EncoderFactory(containerScope,PrimitiveEncoderMetadataSet.INSTANCE);
metadatas = new EncoderMetadataSet();
factory = new EncoderFactory(metadatas,primitivesFactory,new DecoratedObjectFactory());
factory = new EncoderFactory(containerScope,metadatas,primitivesFactory);
}
@Test

View File

@ -18,6 +18,8 @@
package org.eclipse.jetty.websocket.jsr356;
import static org.hamcrest.Matchers.*;
import java.net.URI;
import java.nio.ByteBuffer;
@ -25,7 +27,6 @@ import javax.websocket.ClientEndpointConfig;
import javax.websocket.DeploymentException;
import javax.websocket.MessageHandler;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig;
@ -42,8 +43,6 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.Matchers.instanceOf;
public class JsrSessionTest
{
private ClientContainer container;
@ -65,7 +64,7 @@ public class JsrSessionTest
EventDriver driver = new JsrEndpointEventDriver(policy,ei);
DummyConnection connection = new DummyConnection();
session = new JsrSession(requestURI,driver,connection,container,id, new DecoratedObjectFactory());
session = new JsrSession(container,id,requestURI,driver,connection);
}
@Test

View File

@ -18,14 +18,16 @@
package org.eclipse.jetty.websocket.jsr356;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.*;
import java.lang.reflect.Type;
import java.util.List;
import javax.websocket.DeploymentException;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.jsr356.decoders.PrimitiveDecoderMetadataSet;
import org.eclipse.jetty.websocket.jsr356.handlers.ByteArrayPartialHandler;
import org.eclipse.jetty.websocket.jsr356.handlers.StringPartialHandler;
@ -45,9 +47,11 @@ public class MessageHandlerFactoryTest
@Before
public void init() throws DeploymentException
{
DecoderFactory primitivesFactory = new DecoderFactory(PrimitiveDecoderMetadataSet.INSTANCE);
WebSocketContainerScope containerScope = new SimpleContainerScope(WebSocketPolicy.newClientPolicy());
DecoderFactory primitivesFactory = new DecoderFactory(containerScope,PrimitiveDecoderMetadataSet.INSTANCE);
metadatas = new DecoderMetadataSet();
decoders = new DecoderFactory(metadatas,primitivesFactory,new DecoratedObjectFactory());
decoders = new DecoderFactory(containerScope,metadatas,primitivesFactory);
factory = new MessageHandlerFactory();
}

View File

@ -32,7 +32,7 @@ import javax.websocket.Extension;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
{
@ -46,12 +46,12 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
private Map<String, Object> userProperties;
private List<Extension> extensions;
public AnnotatedServerEndpointConfig(Class<?> endpointClass, ServerEndpoint anno, DecoratedObjectFactory objectFactory) throws DeploymentException
public AnnotatedServerEndpointConfig(WebSocketContainerScope containerScope, Class<?> endpointClass, ServerEndpoint anno) throws DeploymentException
{
this(endpointClass,anno,objectFactory,null);
this(containerScope,endpointClass,anno,null);
}
public AnnotatedServerEndpointConfig(Class<?> endpointClass, ServerEndpoint anno, DecoratedObjectFactory objectFactory, ServerEndpointConfig baseConfig) throws DeploymentException
public AnnotatedServerEndpointConfig(WebSocketContainerScope containerScope, Class<?> endpointClass, ServerEndpoint anno, ServerEndpointConfig baseConfig) throws DeploymentException
{
ServerEndpointConfig.Configurator configr = null;
@ -112,22 +112,24 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
userProperties.putAll(baseConfig.getUserProperties());
}
ServerEndpointConfig.Configurator cfgr;
if (anno.configurator() == ServerEndpointConfig.Configurator.class)
{
if (configr != null)
{
this.configurator = configr;
cfgr = configr;
}
else
{
this.configurator = new BasicServerEndpointConfigurator(objectFactory);
cfgr = new BasicServerEndpointConfigurator(containerScope);
}
}
else
{
try
{
this.configurator = anno.configurator().newInstance();
cfgr = anno.configurator().newInstance();
}
catch (InstantiationException | IllegalAccessException e)
{
@ -139,6 +141,10 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
throw new DeploymentException(err.toString(),e);
}
}
// Make sure all Configurators obtained are decorated
this.configurator = containerScope.getObjectFactory().decorate(cfgr);
}
@Override

View File

@ -24,8 +24,8 @@ import javax.websocket.DeploymentException;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointMetadata;
import org.eclipse.jetty.websocket.jsr356.annotations.IJsrParamId;
@ -34,7 +34,7 @@ public class AnnotatedServerEndpointMetadata extends AnnotatedEndpointMetadata<S
private final ServerEndpoint endpoint;
private final AnnotatedServerEndpointConfig config;
protected AnnotatedServerEndpointMetadata(Class<?> websocket, ServerEndpointConfig baseConfig, DecoratedObjectFactory objectFactory) throws DeploymentException
protected AnnotatedServerEndpointMetadata(WebSocketContainerScope containerScope, Class<?> websocket, ServerEndpointConfig baseConfig) throws DeploymentException
{
super(websocket);
@ -45,7 +45,7 @@ public class AnnotatedServerEndpointMetadata extends AnnotatedEndpointMetadata<S
}
this.endpoint = anno;
this.config = new AnnotatedServerEndpointConfig(websocket,anno,objectFactory,baseConfig);
this.config = new AnnotatedServerEndpointConfig(containerScope,websocket,anno,baseConfig);
getDecoders().addAll(anno.decoders());
getEncoders().addAll(anno.encoders());

View File

@ -28,7 +28,7 @@ import javax.websocket.Encoder;
import javax.websocket.Extension;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
public class BasicServerEndpointConfig implements ServerEndpointConfig
{
@ -41,7 +41,7 @@ public class BasicServerEndpointConfig implements ServerEndpointConfig
private final String path;
private Map<String, Object> userProperties;
public BasicServerEndpointConfig(Class<?> endpointClass, String path, DecoratedObjectFactory objectFactory)
public BasicServerEndpointConfig(WebSocketContainerScope containerScope, Class<?> endpointClass, String path)
{
this.endpointClass = endpointClass;
this.path = path;
@ -51,10 +51,10 @@ public class BasicServerEndpointConfig implements ServerEndpointConfig
this.subprotocols = new ArrayList<>();
this.extensions = new ArrayList<>();
this.userProperties = new HashMap<>();
this.configurator = new BasicServerEndpointConfigurator(objectFactory);
this.configurator = new BasicServerEndpointConfigurator(containerScope);
}
public BasicServerEndpointConfig(ServerEndpointConfig copy, DecoratedObjectFactory objectFactory)
public BasicServerEndpointConfig(WebSocketContainerScope containerScope, ServerEndpointConfig copy)
{
// immutable concepts
this.endpointClass = copy.getEndpointClass();
@ -64,15 +64,21 @@ public class BasicServerEndpointConfig implements ServerEndpointConfig
this.encoders = copy.getEncoders();
this.subprotocols = copy.getSubprotocols();
this.extensions = copy.getExtensions();
ServerEndpointConfig.Configurator cfgr;
if (copy.getConfigurator() != null)
{
this.configurator = copy.getConfigurator();
cfgr = copy.getConfigurator();
}
else
{
this.configurator = new BasicServerEndpointConfigurator(objectFactory);
cfgr = new BasicServerEndpointConfigurator(containerScope);
}
// Make sure all Configurators obtained are decorated
this.configurator = containerScope.getObjectFactory().decorate(cfgr);
// mutable concepts
this.userProperties = new HashMap<>(copy.getUserProperties());
}

View File

@ -18,45 +18,23 @@
package org.eclipse.jetty.websocket.jsr356.server;
import java.util.List;
import java.util.Objects;
import javax.websocket.Extension;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
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.api.util.QuoteUtil;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
public class BasicServerEndpointConfigurator extends ServerEndpointConfig.Configurator
/**
* The Basic Configurator
*/
public class BasicServerEndpointConfigurator extends ContainerDefaultConfigurator
{
private static final Logger LOG = Log.getLogger(BasicServerEndpointConfigurator.class);
private static final String NO_SUBPROTOCOL = "";
private final DecoratedObjectFactory objectFactory;
/**
* Default Constructor required, as
* javax.websocket.server.ServerEndpointConfig$Configurator.fetchContainerDefaultConfigurator()
* will be the one that instantiates this class in most cases.
*/
public BasicServerEndpointConfigurator()
public BasicServerEndpointConfigurator(WebSocketContainerScope containerScope)
{
this(DecoratedObjectFactory.getCurrentInstantiator());
}
public BasicServerEndpointConfigurator(DecoratedObjectFactory objectFactory)
{
Objects.requireNonNull(objectFactory,"DecoratedObjectFactory cannot be null");
this.objectFactory = objectFactory;
}
@Override
public boolean checkOrigin(String originHeaderValue)
{
return true;
super();
this.objectFactory = containerScope.getObjectFactory();
}
@Override
@ -76,53 +54,4 @@ public class BasicServerEndpointConfigurator extends ServerEndpointConfig.Config
throw new InstantiationException(String.format("%s: %s",e.getClass().getName(),e.getMessage()));
}
}
@Override
public List<Extension> getNegotiatedExtensions(List<Extension> installed, List<Extension> requested)
{
return requested;
}
@Override
public String getNegotiatedSubprotocol(List<String> supported, List<String> requested)
{
if ((requested == null) || (requested.size() == 0))
{
// nothing requested, don't return anything
return NO_SUBPROTOCOL;
}
// Nothing specifically called out as being supported by the endpoint
if ((supported == null) || (supported.isEmpty()))
{
// Just return the first hit in this case
LOG.warn("Client requested Subprotocols on endpoint with none supported: {}",QuoteUtil.join(requested,","));
return NO_SUBPROTOCOL;
}
// Return the first matching hit from the list of supported protocols.
for (String possible : requested)
{
if (possible == null)
{
// skip null
continue;
}
if (supported.contains(possible))
{
return possible;
}
}
LOG.warn("Client requested subprotocols {} do not match any endpoint supported subprotocols {}",QuoteUtil.join(requested,","),
QuoteUtil.join(supported,","));
return NO_SUBPROTOCOL;
}
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response)
{
/* do nothing */
}
}

View File

@ -0,0 +1,127 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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 java.util.List;
import javax.websocket.Extension;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.util.QuoteUtil;
/**
* The "Container Default Configurator" per the JSR-356 spec.
*
* @see ServiceLoader behavior of {@link ServerEndpointConfig.Configurator}
*/
public class ContainerDefaultConfigurator extends Configurator
{
private static final Logger LOG = Log.getLogger(ContainerDefaultConfigurator.class);
private static final String NO_SUBPROTOCOL = "";
/**
* Default Constructor required, as
* javax.websocket.server.ServerEndpointConfig$Configurator.fetchContainerDefaultConfigurator()
* will be the one that instantiates this class in most cases.
*/
public ContainerDefaultConfigurator()
{
super();
}
@Override
public boolean checkOrigin(String originHeaderValue)
{
return true;
}
@Override
public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException
{
if (LOG.isDebugEnabled())
{
LOG.debug(".getEndpointInstance({})",endpointClass);
}
try
{
// Since this is started via a ServiceLoader, this class has no Scope or context
// that can be used to obtain a ObjectFactory from.
return endpointClass.newInstance();
}
catch (IllegalAccessException e)
{
throw new InstantiationException(String.format("%s: %s",e.getClass().getName(),e.getMessage()));
}
}
@Override
public List<Extension> getNegotiatedExtensions(List<Extension> installed, List<Extension> requested)
{
return requested;
}
@Override
public String getNegotiatedSubprotocol(List<String> supported, List<String> requested)
{
if ((requested == null) || (requested.size() == 0))
{
// nothing requested, don't return anything
return NO_SUBPROTOCOL;
}
// Nothing specifically called out as being supported by the endpoint
if ((supported == null) || (supported.isEmpty()))
{
// Just return the first hit in this case
LOG.warn("Client requested Subprotocols on endpoint with none supported: {}",QuoteUtil.join(requested,","));
return NO_SUBPROTOCOL;
}
// Return the first matching hit from the list of supported protocols.
for (String possible : requested)
{
if (possible == null)
{
// skip null
continue;
}
if (supported.contains(possible))
{
return possible;
}
}
LOG.warn("Client requested subprotocols {} do not match any endpoint supported subprotocols {}",QuoteUtil.join(requested,","),
QuoteUtil.join(supported,","));
return NO_SUBPROTOCOL;
}
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response)
{
/* do nothing */
}
}

View File

@ -26,12 +26,12 @@ import javax.websocket.Extension;
import javax.websocket.Extension.Parameter;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.jsr356.JsrExtension;
import org.eclipse.jetty.websocket.jsr356.endpoints.EndpointInstance;
import org.eclipse.jetty.websocket.jsr356.server.pathmap.WebSocketPathSpec;
@ -45,15 +45,15 @@ public class JsrCreator implements WebSocketCreator
public static final String PROP_REMOTE_ADDRESS = "javax.websocket.endpoint.remoteAddress";
public static final String PROP_LOCAL_ADDRESS = "javax.websocket.endpoint.localAddress";
private static final Logger LOG = Log.getLogger(JsrCreator.class);
private final WebSocketContainerScope containerScope;
private final ServerEndpointMetadata metadata;
private final ExtensionFactory extensionFactory;
private final DecoratedObjectFactory objectFactory;
public JsrCreator(ServerEndpointMetadata metadata, ExtensionFactory extensionFactory, DecoratedObjectFactory objectFactory)
public JsrCreator(WebSocketContainerScope containerScope, ServerEndpointMetadata metadata, ExtensionFactory extensionFactory)
{
this.containerScope = containerScope;
this.metadata = metadata;
this.extensionFactory = extensionFactory;
this.objectFactory = objectFactory;
}
@Override
@ -67,7 +67,7 @@ public class JsrCreator implements WebSocketCreator
// Establish a copy of the config, so that the UserProperties are unique
// per upgrade request.
config = new BasicServerEndpointConfig(config, objectFactory);
config = new BasicServerEndpointConfig(containerScope, config);
// Bug 444617 - Expose localAddress and remoteAddress for jsr modify handshake to use
// This is being implemented as an optional set of userProperties so that
@ -145,7 +145,7 @@ public class JsrCreator implements WebSocketCreator
WebSocketPathSpec wspathSpec = (WebSocketPathSpec)pathSpec;
String requestPath = req.getRequestPath();
// Wrap the config with the path spec information
config = new PathParamServerEndpointConfig(config,objectFactory,wspathSpec,requestPath);
config = new PathParamServerEndpointConfig(containerScope,config,wspathSpec,requestPath);
}
return new EndpointInstance(endpoint,config,metadata);
}

View File

@ -23,7 +23,7 @@ import java.util.Map;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.jsr356.server.pathmap.WebSocketPathSpec;
/**
@ -33,9 +33,9 @@ public class PathParamServerEndpointConfig extends BasicServerEndpointConfig imp
{
private final Map<String, String> pathParamMap;
public PathParamServerEndpointConfig(ServerEndpointConfig config, DecoratedObjectFactory objectFactory, WebSocketPathSpec pathSpec, String requestPath)
public PathParamServerEndpointConfig(WebSocketContainerScope containerScope, ServerEndpointConfig config, WebSocketPathSpec pathSpec, String requestPath)
{
super(config, objectFactory);
super(containerScope, config);
Map<String, String> pathMap = pathSpec.getPathParams(requestPath);
pathParamMap = new HashMap<String, String>();

View File

@ -46,7 +46,7 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
public ServerContainer(MappedWebSocketCreator creator, WebSocketServerFactory factory, Executor executor)
{
super(executor, factory.getEnhancedInstantiator());
super();
this.mappedCreator = creator;
this.webSocketServerFactory = factory;
EventDriverFactory eventDriverFactory = this.webSocketServerFactory.getEventDriverFactory();
@ -67,7 +67,7 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
}
else
{
cec = new BasicServerEndpointConfig(endpoint.getClass(),path,objectFactory);
cec = new BasicServerEndpointConfig(this,endpoint.getClass(),path);
}
}
return new EndpointInstance(endpoint,cec,metadata);
@ -82,7 +82,7 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
public void addEndpoint(ServerEndpointMetadata metadata) throws DeploymentException
{
JsrCreator creator = new JsrCreator(metadata,webSocketServerFactory.getExtensionFactory(),objectFactory);
JsrCreator creator = new JsrCreator(this,metadata,webSocketServerFactory.getExtensionFactory());
mappedCreator.addMapping(new WebSocketPathSpec(metadata.getPath()),creator);
}
@ -105,7 +105,7 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
if (anno != null)
{
// Annotated takes precedence here
AnnotatedServerEndpointMetadata ametadata = new AnnotatedServerEndpointMetadata(endpoint,config,objectFactory);
AnnotatedServerEndpointMetadata ametadata = new AnnotatedServerEndpointMetadata(this,endpoint,config);
AnnotatedEndpointScanner<ServerEndpoint, ServerEndpointConfig> scanner = new AnnotatedEndpointScanner<>(ametadata);
metadata = ametadata;
scanner.scan();

View File

@ -177,8 +177,6 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
instantiator = new DecoratedObjectFactory();
}
DecoratedObjectFactory.setCurrentInstantiator(instantiator);
if (LOG.isDebugEnabled())
{
LOG.debug("Found {} classes",c.size());

View File

@ -1 +1 @@
org.eclipse.jetty.websocket.jsr356.server.BasicServerEndpointConfigurator
org.eclipse.jetty.websocket.jsr356.server.ContainerDefaultConfigurator

View File

@ -48,6 +48,6 @@ public class JettyServerEndpointConfiguratorTest
ServerEndpointConfig.Configurator configr = iter.next();
assertThat("Configurator",configr,notNullValue());
assertThat("COnfigurator type",configr,instanceOf(BasicServerEndpointConfigurator.class));
assertThat("Configurator type",configr,instanceOf(ContainerDefaultConfigurator.class));
}
}

View File

@ -18,6 +18,8 @@
package org.eclipse.jetty.websocket.jsr356.server;
import static org.hamcrest.Matchers.*;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
@ -25,7 +27,6 @@ import java.util.List;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.events.EventDriver;
@ -33,6 +34,8 @@ import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
import org.eclipse.jetty.websocket.common.events.EventDriverImpl;
import org.eclipse.jetty.websocket.common.frames.ContinuationFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.jsr356.ClientContainer;
import org.eclipse.jetty.websocket.jsr356.JsrSession;
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
@ -43,9 +46,6 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
public class OnPartialTest
{
@Rule
@ -68,10 +68,10 @@ public class OnPartialTest
ServerEndpoint anno = endpoint.getAnnotation(ServerEndpoint.class);
Assert.assertThat("Endpoint: " + endpoint + " should be annotated with @ServerEndpoint",anno,notNullValue());
DecoratedObjectFactory instantiator = new DecoratedObjectFactory();
WebSocketContainerScope containerScope = new SimpleContainerScope(policy);
ServerEndpointConfig config = new BasicServerEndpointConfig(endpoint,"/",instantiator);
AnnotatedServerEndpointMetadata metadata = new AnnotatedServerEndpointMetadata(endpoint,config,instantiator);
ServerEndpointConfig config = new BasicServerEndpointConfig(containerScope,endpoint,"/");
AnnotatedServerEndpointMetadata metadata = new AnnotatedServerEndpointMetadata(containerScope,endpoint,config);
AnnotatedEndpointScanner<ServerEndpoint, ServerEndpointConfig> scanner = new AnnotatedEndpointScanner<>(metadata);
scanner.scan();
EndpointInstance ei = new EndpointInstance(websocket,config,metadata);
@ -84,7 +84,7 @@ public class OnPartialTest
DummyConnection connection = new DummyConnection();
ClientContainer container = new ClientContainer();
@SuppressWarnings("resource")
JsrSession session = new JsrSession(requestURI,driver,connection,container,id, new DecoratedObjectFactory());
JsrSession session = new JsrSession(container,id,requestURI,driver,connection);
session.setPolicy(policy);
session.open();
return driver;

View File

@ -18,7 +18,7 @@
package org.eclipse.jetty.websocket.jsr356.server;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.*;
import java.io.Reader;
import java.lang.reflect.Field;
@ -34,7 +34,9 @@ import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
import org.eclipse.jetty.websocket.jsr356.annotations.JsrCallable;
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicBinaryMessageByteBufferSocket;
@ -183,7 +185,8 @@ public class ServerAnnotatedEndpointScanner_GoodSignaturesTest
@Test
public void testScan_Basic() throws Exception
{
AnnotatedServerEndpointMetadata metadata = new AnnotatedServerEndpointMetadata(testcase.pojo,null,new DecoratedObjectFactory());
WebSocketContainerScope container = new SimpleContainerScope(WebSocketPolicy.newClientPolicy());
AnnotatedServerEndpointMetadata metadata = new AnnotatedServerEndpointMetadata(container,testcase.pojo,null);
AnnotatedEndpointScanner<ServerEndpoint, ServerEndpointConfig> scanner = new AnnotatedEndpointScanner<>(metadata);
scanner.scan();

View File

@ -18,6 +18,8 @@
package org.eclipse.jetty.websocket.jsr356.server;
import static org.hamcrest.Matchers.*;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
@ -30,10 +32,12 @@ import javax.websocket.OnOpen;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
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.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidCloseIntSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidErrorErrorSocket;
@ -48,8 +52,6 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import static org.hamcrest.Matchers.containsString;
/**
* Test {@link AnnotatedEndpointScanner} against various simple, 1 method {@link ServerEndpoint} annotated classes with invalid signatures.
*/
@ -95,7 +97,8 @@ public class ServerAnnotatedEndpointScanner_InvalidSignaturesTest
@Test
public void testScan_InvalidSignature() throws DeploymentException
{
AnnotatedServerEndpointMetadata metadata = new AnnotatedServerEndpointMetadata(pojo,null,new DecoratedObjectFactory());
WebSocketContainerScope container = new SimpleContainerScope(WebSocketPolicy.newClientPolicy());
AnnotatedServerEndpointMetadata metadata = new AnnotatedServerEndpointMetadata(container,pojo,null);
AnnotatedEndpointScanner<ServerEndpoint,ServerEndpointConfig> scanner = new AnnotatedEndpointScanner<>(metadata);
try

View File

@ -81,9 +81,4 @@ public interface Extension extends IncomingFrames, OutgoingFrames
* the next outgoing extension
*/
public void setNextOutgoingFrames(OutgoingFrames nextOutgoing);
// TODO: Extension should indicate if it requires boundary of fragments to be preserved
// TODO: Extension should indicate if it uses the Extension data field of frame for its own reasons.
}

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.net.CookieStore;
import java.net.SocketAddress;
import java.net.URI;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
@ -31,6 +32,7 @@ import java.util.concurrent.Future;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.io.SelectorManager;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.HttpCookieStore;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
@ -57,15 +59,16 @@ import org.eclipse.jetty.websocket.common.WebSocketSessionFactory;
import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
/**
* WebSocketClient provides a means of establishing connections to remote websocket endpoints.
*/
public class WebSocketClient extends ContainerLifeCycle implements SessionListener
public class WebSocketClient extends ContainerLifeCycle implements SessionListener, WebSocketContainerScope
{
private static final Logger LOG = Log.getLogger(WebSocketClient.class);
private final WebSocketPolicy policy;
private final WebSocketPolicy policy = WebSocketPolicy.newClientPolicy();
private final SslContextFactory sslContextFactory;
private final WebSocketExtensionFactory extensionRegistry;
private boolean daemon = false;
@ -73,6 +76,7 @@ public class WebSocketClient extends ContainerLifeCycle implements SessionListen
private SessionFactory sessionFactory;
private ByteBufferPool bufferPool;
private Executor executor;
private DecoratedObjectFactory objectFactory;
private Scheduler scheduler;
private CookieStore cookieStore;
private ConnectionManager connectionManager;
@ -83,7 +87,7 @@ public class WebSocketClient extends ContainerLifeCycle implements SessionListen
public WebSocketClient()
{
this(null,null);
this((SslContextFactory)null,null);
}
public WebSocketClient(Executor executor)
@ -106,13 +110,28 @@ public class WebSocketClient extends ContainerLifeCycle implements SessionListen
this(sslContextFactory,executor,new MappedByteBufferPool());
}
public WebSocketClient(WebSocketContainerScope scope)
{
this(scope.getSslContextFactory(), scope.getExecutor(), scope.getBufferPool(), scope.getObjectFactory());
}
public WebSocketClient(WebSocketContainerScope scope, SslContextFactory sslContextFactory)
{
this(sslContextFactory, scope.getExecutor(), scope.getBufferPool(), scope.getObjectFactory());
}
public WebSocketClient(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool)
{
this(sslContextFactory, executor, bufferPool, new DecoratedObjectFactory());
}
public WebSocketClient(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool, DecoratedObjectFactory objectFactory)
{
this.executor = executor;
this.sslContextFactory = sslContextFactory;
this.policy = WebSocketPolicy.newClientPolicy();
this.bufferPool = bufferPool;
this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool);
this.objectFactory = objectFactory;
this.extensionRegistry = new WebSocketExtensionFactory(this);
// Bug #431459 - unregistering compression extensions till they are more stable
this.extensionRegistry.unregister("deflate-frame");
@ -121,7 +140,6 @@ public class WebSocketClient extends ContainerLifeCycle implements SessionListen
this.masker = new RandomMasker();
this.eventDriverFactory = new EventDriverFactory(policy);
this.sessionFactory = new WebSocketSessionFactory(this);
addBean(this.executor);
addBean(this.sslContextFactory);
@ -251,6 +269,16 @@ public class WebSocketClient extends ContainerLifeCycle implements SessionListen
cookieStore = new HttpCookieStore.Empty();
}
if(this.sessionFactory == null)
{
this.sessionFactory = new WebSocketSessionFactory(this);
}
if(this.objectFactory == null)
{
this.objectFactory = new DecoratedObjectFactory();
}
super.doStart();
if (LOG.isDebugEnabled())
@ -390,9 +418,15 @@ public class WebSocketClient extends ContainerLifeCycle implements SessionListen
return this.policy.getMaxTextMessageSize();
}
@Override
public DecoratedObjectFactory getObjectFactory()
{
return this.objectFactory;
}
public Set<WebSocketSession> getOpenSessions()
{
return new HashSet<>(getBeans(WebSocketSession.class));
return Collections.unmodifiableSet(new HashSet<>(getBeans(WebSocketSession.class)));
}
public WebSocketPolicy getPolicy()

View File

@ -87,13 +87,15 @@ public class SessionTest
RemoteEndpoint remote = cliSock.getSession().getRemote();
remote.sendStringByFuture("Hello World!");
if (remote.getBatchMode() == BatchMode.ON)
{
remote.flush();
}
srvSock.echoMessage(1,500,TimeUnit.MILLISECONDS);
// wait for response from server
cliSock.waitForMessage(500,TimeUnit.MILLISECONDS);
Set<WebSocketSession> open = client.getOpenSessions();
Assert.assertThat("Open Sessions.size", open.size(), is(1));
Assert.assertThat("(Before Close) Open Sessions.size", open.size(), is(1));
cliSock.assertMessage("Hello World!");
cliSock.close();
@ -101,7 +103,7 @@ public class SessionTest
cliSock.waitForClose(500,TimeUnit.MILLISECONDS);
open = client.getOpenSessions();
Assert.assertThat("Open Sessions.size", open.size(), is(0));
Assert.assertThat("(After Close) Open Sessions.size", open.size(), is(0));
}
finally
{

View File

@ -20,7 +20,6 @@ package org.eclipse.jetty.websocket.common;
import java.net.URI;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.common.events.EventDriver;
/**
@ -31,6 +30,4 @@ public interface SessionFactory
public boolean supports(EventDriver websocket);
public WebSocketSession createSession(URI requestURI, EventDriver websocket, LogicalConnection connection);
public void setEnhancedInstantiator(DecoratedObjectFactory objectFactory);
}

View File

@ -24,6 +24,7 @@ import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor;
import org.eclipse.jetty.io.ByteBufferPool;
@ -51,11 +52,14 @@ import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.io.IOState;
import org.eclipse.jetty.websocket.common.io.IOState.ConnectionStateListener;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketSessionScope;
@ManagedObject("A Jetty WebSocket Session")
public class WebSocketSession extends ContainerLifeCycle implements Session, IncomingFrames, ConnectionStateListener
public class WebSocketSession extends ContainerLifeCycle implements Session, WebSocketSessionScope, IncomingFrames, ConnectionStateListener
{
private static final Logger LOG = Log.getLogger(WebSocketSession.class);
private final WebSocketContainerScope containerScope;
private final URI requestURI;
private final EventDriver websocket;
private final LogicalConnection connection;
@ -72,14 +76,13 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
private UpgradeRequest upgradeRequest;
private UpgradeResponse upgradeResponse;
public WebSocketSession(URI requestURI, EventDriver websocket, LogicalConnection connection, SessionListener... sessionListeners)
public WebSocketSession(WebSocketContainerScope containerScope, URI requestURI, EventDriver websocket, LogicalConnection connection, SessionListener... sessionListeners)
{
if (requestURI == null)
{
throw new RuntimeException("Request URI cannot be null");
}
Objects.requireNonNull(containerScope,"Container Scope cannot be null");
Objects.requireNonNull(requestURI,"Request URI cannot be null");
this.classLoader = Thread.currentThread().getContextClassLoader();
this.containerScope = containerScope;
this.requestURI = requestURI;
this.websocket = websocket;
this.connection = connection;
@ -195,6 +198,12 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
return connection;
}
@Override
public WebSocketContainerScope getContainerScope()
{
return this.containerScope;
}
public ExtensionFactory getExtensionFactory()
{
return extensionFactory;
@ -275,6 +284,13 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
return this.upgradeResponse;
}
@Override
public WebSocketSession getWebSocketSession()
{
return this;
}
@Override
public int hashCode()
{

View File

@ -20,22 +20,38 @@ package org.eclipse.jetty.websocket.common;
import java.net.URI;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.events.JettyAnnotatedEventDriver;
import org.eclipse.jetty.websocket.common.events.JettyListenerEventDriver;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
/**
* Default Session factory, creating WebSocketSession objects.
*/
public class WebSocketSessionFactory implements SessionFactory
{
private final WebSocketContainerScope containerScope;
private final SessionListener[] listeners;
public WebSocketSessionFactory(SessionListener... sessionListeners)
public WebSocketSessionFactory(WebSocketContainerScope containerScope, SessionListener... sessionListeners)
{
listeners = sessionListeners;
}
this.containerScope = containerScope;
if ((sessionListeners != null) && (sessionListeners.length > 0))
{
this.listeners = sessionListeners;
}
else
{
if (this.containerScope instanceof SessionListener)
{
this.listeners = new SessionListener[] { (SessionListener)containerScope };
}
else
{
this.listeners = new SessionListener[0];
}
}
}
@Override
public boolean supports(EventDriver websocket)
@ -46,12 +62,6 @@ public class WebSocketSessionFactory implements SessionFactory
@Override
public WebSocketSession createSession(URI requestURI, EventDriver websocket, LogicalConnection connection)
{
return new WebSocketSession(requestURI,websocket,connection,listeners);
}
@Override
public void setEnhancedInstantiator(DecoratedObjectFactory objectFactory)
{
/* does nothing here */
return new WebSocketSession(containerScope, requestURI,websocket,connection,listeners);
}
}

View File

@ -35,6 +35,7 @@ import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
import org.eclipse.jetty.websocket.common.LogicalConnection;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
@ManagedObject("Abstract Extension")
public abstract class AbstractExtension extends ContainerLifeCycle implements Extension
@ -68,6 +69,12 @@ public abstract class AbstractExtension extends ContainerLifeCycle implements Ex
out.append(bean.toString());
}
public void init(WebSocketContainerScope container)
{
this.policy = container.getPolicy();
this.bufferPool = container.getBufferPool();
}
public ByteBufferPool getBufferPool()
{
return bufferPool;

View File

@ -18,26 +18,21 @@
package org.eclipse.jetty.websocket.common.extensions;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
public class WebSocketExtensionFactory extends ExtensionFactory
{
private WebSocketPolicy policy;
private ByteBufferPool bufferPool;
private DecoratedObjectFactory objectFactory;
private WebSocketContainerScope container;
public WebSocketExtensionFactory(WebSocketPolicy policy, ByteBufferPool bufferPool)
public WebSocketExtensionFactory(WebSocketContainerScope container)
{
super();
this.policy = policy;
this.bufferPool = bufferPool;
this.container = container;
}
@Override
@ -62,12 +57,11 @@ public class WebSocketExtensionFactory extends ExtensionFactory
try
{
Extension ext = objectFactory.createInstance(extClass);
Extension ext = container.getObjectFactory().createInstance(extClass);
if (ext instanceof AbstractExtension)
{
AbstractExtension aext = (AbstractExtension)ext;
aext.setPolicy(policy);
aext.setBufferPool(bufferPool);
aext.init(container);
aext.setConfig(config);
}
return ext;
@ -77,9 +71,4 @@ public class WebSocketExtensionFactory extends ExtensionFactory
throw new WebSocketException("Cannot instantiate extension: " + extClass,e);
}
}
public void setEnhancedInstantiator(DecoratedObjectFactory objectFactory)
{
this.objectFactory = objectFactory;
}
}

View File

@ -0,0 +1,95 @@
//
// ========================================================================
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.common.scopes;
import java.util.concurrent.Executor;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
public class SimpleContainerScope implements WebSocketContainerScope
{
private final ByteBufferPool bufferPool;
private final DecoratedObjectFactory objectFactory;
private final WebSocketPolicy policy;
private Executor executor;
private SslContextFactory sslContextFactory;
public SimpleContainerScope(WebSocketPolicy policy)
{
this(policy,new MappedByteBufferPool(),new DecoratedObjectFactory());
}
public SimpleContainerScope(WebSocketPolicy policy, ByteBufferPool bufferPool)
{
this(policy,bufferPool,new DecoratedObjectFactory());
}
public SimpleContainerScope(WebSocketPolicy policy, ByteBufferPool bufferPool, DecoratedObjectFactory objectFactory)
{
this.policy = policy;
this.bufferPool = bufferPool;
this.objectFactory = objectFactory;
QueuedThreadPool threadPool = new QueuedThreadPool();
String name = "WebSocketSimpleContainer@" + hashCode();
threadPool.setName(name);
threadPool.setDaemon(true);
this.executor = threadPool;
}
@Override
public ByteBufferPool getBufferPool()
{
return this.bufferPool;
}
@Override
public Executor getExecutor()
{
return this.executor;
}
@Override
public DecoratedObjectFactory getObjectFactory()
{
return this.objectFactory;
}
@Override
public WebSocketPolicy getPolicy()
{
return this.policy;
}
@Override
public SslContextFactory getSslContextFactory()
{
return this.sslContextFactory;
}
public void setSslContextFactory(SslContextFactory sslContextFactory)
{
this.sslContextFactory = sslContextFactory;
}
}

View File

@ -0,0 +1,67 @@
//
// ========================================================================
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.common.scopes;
import java.util.concurrent.Executor;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
/**
* Defined Scope for a WebSocketContainer.
*/
public interface WebSocketContainerScope
{
/**
* The configured Container Buffer Pool.
*
* @return the buffer pool (never null)
*/
public ByteBufferPool getBufferPool();
/**
* Executor in use by the container.
*
* @return the Executor in use by the container.
*/
public Executor getExecutor();
/**
* Object Factory used to create objects.
*
* @return Object Factory used to create instances of objects.
*/
public DecoratedObjectFactory getObjectFactory();
/**
* The policy the container is running on.
*
* @return the websocket policy
*/
public WebSocketPolicy getPolicy();
/**
* The SslContextFactory in use by the container.
*
* @return the SslContextFactory in use by the container (can be null if no SSL context is defined)
*/
public SslContextFactory getSslContextFactory();
}

View File

@ -0,0 +1,36 @@
//
// ========================================================================
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.common.scopes;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;
/**
* Defined Scope for a WebSocket Handshake/Upgrade
*/
public interface WebSocketHandshakeScope
{
Class<?> getPotentialEndpointClass();
UpgradeRequest getHandshakeRequest();
UpgradeResponse getHandshakeResponse();
WebSocketContainerScope getContainerScope();
}

View File

@ -0,0 +1,31 @@
//
// ========================================================================
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.common.scopes;
import org.eclipse.jetty.websocket.common.WebSocketSession;
/**
* Defined Scope for a WebSocketSession (active connection)
*/
public interface WebSocketSessionScope
{
WebSocketSession getWebSocketSession();
WebSocketContainerScope getContainerScope();
}

View File

@ -31,6 +31,8 @@ import org.eclipse.jetty.websocket.common.frames.PingFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.common.io.LocalWebSocketSession;
import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
@ -50,6 +52,14 @@ public class EventDriverTest
@Rule
public LeakTrackingBufferPoolRule bufferPool = new LeakTrackingBufferPoolRule("Test");
private WebSocketContainerScope container;
@Before
public void initContainer()
{
this.container = new SimpleContainerScope(WebSocketPolicy.newClientPolicy());
}
private Frame makeBinaryFrame(String content, boolean fin)
{
return new BinaryFrame().setPayload(content).setFin(fin);
@ -61,7 +71,7 @@ public class EventDriverTest
AdapterConnectCloseSocket socket = new AdapterConnectCloseSocket();
EventDriver driver = wrap(socket);
try (LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver,bufferPool))
try (LocalWebSocketSession conn = new LocalWebSocketSession(container,testname,driver))
{
conn.open();
driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame());
@ -78,7 +88,7 @@ public class EventDriverTest
AnnotatedBinaryArraySocket socket = new AnnotatedBinaryArraySocket();
EventDriver driver = wrap(socket);
try (LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver,bufferPool))
try (LocalWebSocketSession conn = new LocalWebSocketSession(container,testname,driver))
{
conn.open();
driver.incomingFrame(makeBinaryFrame("Hello World",true));
@ -97,7 +107,7 @@ public class EventDriverTest
AnnotatedTextSocket socket = new AnnotatedTextSocket();
EventDriver driver = wrap(socket);
try (LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver,bufferPool))
try (LocalWebSocketSession conn = new LocalWebSocketSession(container,testname,driver))
{
conn.open();
driver.incomingError(new WebSocketException("oof"));
@ -116,7 +126,7 @@ public class EventDriverTest
AnnotatedFramesSocket socket = new AnnotatedFramesSocket();
EventDriver driver = wrap(socket);
try (LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver,bufferPool))
try (LocalWebSocketSession conn = new LocalWebSocketSession(container,testname,driver))
{
conn.open();
driver.incomingFrame(new PingFrame().setPayload("PING"));
@ -140,7 +150,7 @@ public class EventDriverTest
AnnotatedBinaryStreamSocket socket = new AnnotatedBinaryStreamSocket();
EventDriver driver = wrap(socket);
try (LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver,bufferPool))
try (LocalWebSocketSession conn = new LocalWebSocketSession(container,testname,driver))
{
conn.open();
driver.incomingFrame(makeBinaryFrame("Hello World",true));
@ -159,7 +169,7 @@ public class EventDriverTest
ListenerBasicSocket socket = new ListenerBasicSocket();
EventDriver driver = wrap(socket);
try (LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver,bufferPool))
try (LocalWebSocketSession conn = new LocalWebSocketSession(container,testname,driver))
{
conn.start();
conn.open();

View File

@ -23,7 +23,6 @@ import static org.hamcrest.Matchers.*;
import java.util.ArrayList;
import java.util.List;
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.api.WebSocketPolicy;
@ -31,6 +30,7 @@ import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.common.extensions.identity.IdentityExtension;
import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
@ -56,8 +56,9 @@ public class ExtensionStackTest
private ExtensionStack createExtensionStack()
{
WebSocketPolicy policy = WebSocketPolicy.newClientPolicy();
WebSocketExtensionFactory factory = new WebSocketExtensionFactory(policy,bufferPool);
factory.setEnhancedInstantiator(new DecoratedObjectFactory());
WebSocketContainerScope container = new SimpleContainerScope(policy,bufferPool);
WebSocketExtensionFactory factory = new WebSocketExtensionFactory(container);
return new ExtensionStack(factory);
}

View File

@ -24,7 +24,6 @@ import java.nio.ByteBuffer;
import java.util.Collections;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Extension;
@ -34,6 +33,8 @@ import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.common.test.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.test.IncomingFramesCapture;
import org.eclipse.jetty.websocket.common.test.UnitParser;
@ -127,8 +128,8 @@ public class ExtensionTool
public ExtensionTool(WebSocketPolicy policy, ByteBufferPool bufferPool)
{
this.policy = policy;
WebSocketExtensionFactory extFactory = new WebSocketExtensionFactory(policy,bufferPool);
extFactory.setEnhancedInstantiator(new DecoratedObjectFactory());
WebSocketContainerScope container = new SimpleContainerScope(policy, bufferPool);
WebSocketExtensionFactory extFactory = new WebSocketExtensionFactory(container);
this.factory = extFactory;
}

View File

@ -20,9 +20,9 @@ package org.eclipse.jetty.websocket.common.io;
import java.net.URI;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.common.test.OutgoingFramesCapture;
import org.junit.rules.TestName;
@ -31,9 +31,10 @@ public class LocalWebSocketSession extends WebSocketSession
private String id;
private OutgoingFramesCapture outgoingCapture;
public LocalWebSocketSession(TestName testname, EventDriver driver, ByteBufferPool bufferPool)
public LocalWebSocketSession(WebSocketContainerScope containerScope, TestName testname, EventDriver driver)
{
super(URI.create("ws://localhost/LocalWebSocketSesssion/" + testname.getMethodName()),driver,new LocalWebSocketConnection(testname,bufferPool));
super(containerScope,URI.create("ws://localhost/LocalWebSocketSesssion/" + testname.getMethodName()),driver,
new LocalWebSocketConnection(testname,containerScope.getBufferPool()));
this.id = testname.getMethodName();
outgoingCapture = new OutgoingFramesCapture();
setOutgoingHandler(outgoingCapture);

View File

@ -34,6 +34,7 @@ import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
import org.eclipse.jetty.websocket.common.io.FramePipes;
import org.eclipse.jetty.websocket.common.io.LocalWebSocketSession;
import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@ -74,6 +75,9 @@ public class MessageOutputStreamTest
// Event Driver factory
EventDriverFactory factory = new EventDriverFactory(policy);
// Container
WebSocketContainerScope containerScope = new SimpleContainerScope(policy,bufferPool);
// local socket
EventDriver driver = factory.wrap(new TrackingSocket("local"));
@ -81,7 +85,7 @@ public class MessageOutputStreamTest
socket = new TrackingSocket("remote");
OutgoingFrames socketPipe = FramePipes.to(factory.wrap(socket));
session = new LocalWebSocketSession(testname,driver,bufferPool);
session = new LocalWebSocketSession(containerScope,testname,driver);
session.setPolicy(policy);
// talk to our remote socket

View File

@ -30,6 +30,7 @@ import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
import org.eclipse.jetty.websocket.common.io.FramePipes;
import org.eclipse.jetty.websocket.common.io.LocalWebSocketSession;
import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@ -72,6 +73,9 @@ public class MessageWriterTest
// Event Driver factory
EventDriverFactory factory = new EventDriverFactory(policy);
// Container
WebSocketContainerScope containerScope = new SimpleContainerScope(policy,bufferPool);
// local socket
EventDriver driver = factory.wrap(new TrackingSocket("local"));
@ -79,7 +83,7 @@ public class MessageWriterTest
socket = new TrackingSocket("remote");
OutgoingFrames socketPipe = FramePipes.to(factory.wrap(socket));
session = new LocalWebSocketSession(testname,driver,bufferPool);
session = new LocalWebSocketSession(containerScope,testname,driver);
session.setPolicy(policy);
// talk to our remote socket

View File

@ -44,7 +44,6 @@ import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.toolchain.test.EventQueue;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
@ -69,6 +68,7 @@ import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
import org.eclipse.jetty.websocket.common.io.IOState;
import org.eclipse.jetty.websocket.common.io.IOState.ConnectionStateListener;
import org.eclipse.jetty.websocket.common.io.http.HttpResponseHeaderParser;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.junit.Assert;
/**
@ -228,8 +228,7 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener,
this.generator = new Generator(policy,bufferPool);
this.parser = new Parser(policy,bufferPool);
this.extensionFactory = new WebSocketExtensionFactory(policy,bufferPool);
this.extensionFactory.setEnhancedInstantiator(new DecoratedObjectFactory());
this.extensionFactory = new WebSocketExtensionFactory(new SimpleContainerScope(policy,bufferPool));
this.ioState = new IOState();
this.ioState.addListener(this);
}

View File

@ -66,6 +66,7 @@ import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.extensions.ExtensionStack;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
import org.eclipse.jetty.websocket.common.frames.CloseFrame;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.junit.Assert;
/**
@ -109,7 +110,7 @@ public class BlockheadServer
this.parser = new Parser(policy,bufferPool);
this.parseCount = new AtomicInteger(0);
this.generator = new Generator(policy,bufferPool,false);
this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool);
this.extensionRegistry = new WebSocketExtensionFactory(new SimpleContainerScope(policy,bufferPool));
}
/**

View File

@ -41,11 +41,13 @@ import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
@ -63,6 +65,7 @@ import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
import org.eclipse.jetty.websocket.common.extensions.ExtensionStack;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
@ -71,7 +74,7 @@ import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
/**
* Factory to create WebSocket connections
*/
public class WebSocketServerFactory extends ContainerLifeCycle implements WebSocketCreator, WebSocketServletFactory, SessionListener
public class WebSocketServerFactory extends ContainerLifeCycle implements WebSocketCreator, WebSocketContainerScope, WebSocketServletFactory, SessionListener
{
private static final Logger LOG = Log.getLogger(WebSocketServerFactory.class);
@ -86,6 +89,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
private final EventDriverFactory eventDriverFactory;
private final ByteBufferPool bufferPool;
private final WebSocketExtensionFactory extensionFactory;
private Executor executor;
private List<SessionFactory> sessionFactories;
private Set<WebSocketSession> openSessions = new CopyOnWriteArraySet<>();
private WebSocketCreator creator;
@ -121,7 +125,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
this.defaultPolicy = policy;
this.eventDriverFactory = new EventDriverFactory(defaultPolicy);
this.bufferPool = bufferPool;
this.extensionFactory = new WebSocketExtensionFactory(defaultPolicy, this.bufferPool);
this.extensionFactory = new WebSocketExtensionFactory(this);
// Bug #431459 - unregistering compression extensions till they are more stable
this.extensionFactory.unregister("deflate-frame");
@ -165,16 +169,12 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
{
Thread.currentThread().setContextClassLoader(contextClassloader);
// Establish the DecoratedObjectFactory thread local
// for various ServiceLoader initiated components to use.
DecoratedObjectFactory.setCurrentInstantiator(getEnhancedInstantiator(request));
// Create Servlet Specific Upgrade Request/Response objects
ServletUpgradeRequest sockreq = new ServletUpgradeRequest(request);
ServletUpgradeResponse sockresp = new ServletUpgradeResponse(response);
Object websocketPojo = creator.createWebSocket(sockreq, sockresp);
websocketPojo = objectFactory.decorate(websocketPojo);
websocketPojo = getObjectFactory().decorate(websocketPojo);
// Handle response forbidden (and similar paths)
if (sockresp.isCommitted())
@ -315,12 +315,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
this.objectFactory = new DecoratedObjectFactory();
}
this.extensionFactory.setEnhancedInstantiator(this.objectFactory);
for(SessionFactory sessionFactory: this.sessionFactories)
{
sessionFactory.setEnhancedInstantiator(this.objectFactory);
}
super.doStart();
}
@ -331,53 +325,26 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
super.doStop();
}
@Override
public ByteBufferPool getBufferPool()
{
return this.bufferPool;
}
@Override
public WebSocketCreator getCreator()
{
return this.creator;
}
public DecoratedObjectFactory getEnhancedInstantiator()
@Override
public Executor getExecutor()
{
return objectFactory;
return this.executor;
}
public DecoratedObjectFactory getEnhancedInstantiator(HttpServletRequest request)
public DecoratedObjectFactory getObjectFactory()
{
if (objectFactory != null)
{
return objectFactory;
}
if (request == null)
{
LOG.debug("Using default DecoratedObjectFactory (HttpServletRequest is null)");
return new DecoratedObjectFactory();
}
return getEnhancedInstantiator(request.getServletContext());
}
public DecoratedObjectFactory getEnhancedInstantiator(ServletContext context)
{
if (objectFactory != null)
{
return objectFactory;
}
if (context == null)
{
LOG.debug("Using default DecoratedObjectFactory (ServletContext is null)");
return new DecoratedObjectFactory();
}
objectFactory = (DecoratedObjectFactory)context.getAttribute(DecoratedObjectFactory.ATTR);
if (objectFactory == null)
{
LOG.debug("Using default DecoratedObjectFactory (ServletContext attribute is null)");
objectFactory = new DecoratedObjectFactory();
}
return objectFactory;
}
@ -403,6 +370,15 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return defaultPolicy;
}
@Override
public SslContextFactory getSslContextFactory()
{
/* Not relevant for a Server, as this is defined in the
* Connector configuration
*/
return null;
}
public void init(ServletContextHandler context) throws ServletException
{
this.objectFactory = (DecoratedObjectFactory)context.getAttribute(DecoratedObjectFactory.ATTR);
@ -410,6 +386,8 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
{
this.objectFactory = new DecoratedObjectFactory();
}
this.executor = context.getServer().getThreadPool();
}
@Override
@ -420,6 +398,17 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
{
this.objectFactory = new DecoratedObjectFactory();
}
ContextHandler handler = ContextHandler.getContextHandler(context);
if (handler == null)
{
throw new ServletException("Not running on Jetty, WebSocket support unavailable");
}
this.executor = handler.getServer().getThreadPool();
try
{
// start lifecycle

View File

@ -260,7 +260,6 @@ public class WebSocketUpgradeFilter extends ContainerLifeCycle implements Filter
factory.init(config.getServletContext());
WebSocketPolicy policy = factory.getPolicy();
String max = config.getInitParameter("maxIdleTime");
if (max != null)
{