Issue #207 - Support javax.websocket version 1.1
# Conflicts: # jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/AnnotatedServerEndpointMetadata.java # jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrPathParamId.java # jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerEndpointImpl.java # jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerExtendsEndpointImpl.java # jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/SimpleServerEndpointMetadata.java # jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/OnPartialTest.java # jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_GoodSignaturesTest.java # jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_InvalidSignaturesTest.java
This commit is contained in:
parent
df584babc0
commit
4c01fd96c8
|
@ -88,12 +88,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
|
|||
client.setDaemon(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the entry point for ServerContainer, via ServletContext.getAttribute(ServerContainer.class.getName())
|
||||
*
|
||||
* @param scope the scope of the ServerContainer
|
||||
*/
|
||||
public ClientContainer(final WebSocketContainerScope scope)
|
||||
public ClientContainer(WebSocketContainerScope scope)
|
||||
{
|
||||
boolean trustAll = Boolean.getBoolean("org.eclipse.jetty.websocket.jsr356.ssl-trust-all");
|
||||
|
||||
|
@ -109,22 +104,6 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
|
|||
|
||||
private Session connect(ConfiguredEndpoint instance, URI path) throws IOException
|
||||
{
|
||||
synchronized (this.client)
|
||||
{
|
||||
if (this.internalClient && !this.client.isStarted())
|
||||
{
|
||||
try
|
||||
{
|
||||
this.client.start();
|
||||
addManaged(this.client);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException("Unable to start Client", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Objects.requireNonNull(instance, "EndpointInstance cannot be null");
|
||||
Objects.requireNonNull(path, "Path cannot be null");
|
||||
|
||||
|
@ -176,28 +155,28 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
|
|||
@Override
|
||||
public Session connectToServer(Class<? extends Endpoint> endpointClass, ClientEndpointConfig config, URI path) throws DeploymentException, IOException
|
||||
{
|
||||
ConfiguredEndpoint instance = newClientEndpointInstance(endpointClass,config);
|
||||
ConfiguredEndpoint instance = newConfiguredEndpoint(endpointClass, config);
|
||||
return connect(instance, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session connectToServer(Class<?> annotatedEndpointClass, URI path) throws DeploymentException, IOException
|
||||
{
|
||||
ConfiguredEndpoint instance = newClientEndpointInstance(annotatedEndpointClass,null);
|
||||
ConfiguredEndpoint instance = newConfiguredEndpoint(annotatedEndpointClass, null);
|
||||
return connect(instance, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session connectToServer(Endpoint endpoint, ClientEndpointConfig config, URI path) throws DeploymentException, IOException
|
||||
{
|
||||
ConfiguredEndpoint instance = newClientEndpointInstance(endpoint,config);
|
||||
ConfiguredEndpoint instance = newConfiguredEndpoint(endpoint, config);
|
||||
return connect(instance, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session connectToServer(Object endpoint, URI path) throws DeploymentException, IOException
|
||||
{
|
||||
ConfiguredEndpoint instance = newClientEndpointInstance(endpoint,null);
|
||||
ConfiguredEndpoint instance = newConfiguredEndpoint(endpoint, null);
|
||||
return connect(instance, path);
|
||||
}
|
||||
|
||||
|
@ -271,6 +250,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
|
|||
|
||||
/**
|
||||
* Used in {@link Session#getOpenSessions()}
|
||||
*
|
||||
* @return the set of open sessions
|
||||
*/
|
||||
public Set<Session> getOpenSessions()
|
||||
|
@ -290,35 +270,47 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
|
|||
return scopeDelegate.getSslContextFactory();
|
||||
}
|
||||
|
||||
private ConfiguredEndpoint newClientEndpointInstance(Class<?> endpointClass, ClientEndpointConfig config)
|
||||
private ConfiguredEndpoint newConfiguredEndpoint(Class<?> endpointClass, EndpointConfig config)
|
||||
{
|
||||
try
|
||||
{
|
||||
return newClientEndpointInstance(endpointClass.newInstance(),config);
|
||||
return newConfiguredEndpoint(endpointClass.newInstance(), config);
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException e)
|
||||
catch (DeploymentException | InstantiationException | IllegalAccessException e)
|
||||
{
|
||||
throw new InvalidWebSocketException("Unable to instantiate websocket: " + endpointClass.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
public ConfiguredEndpoint newClientEndpointInstance(Object endpoint, ClientEndpointConfig config)
|
||||
public ConfiguredEndpoint newConfiguredEndpoint(Object endpoint, EndpointConfig providedConfig) throws DeploymentException
|
||||
{
|
||||
ClientEndpointConfig cec = config;
|
||||
EndpointConfig config = providedConfig;
|
||||
|
||||
if (config == null)
|
||||
{
|
||||
// Get Config from Annotation
|
||||
config = newEmptyConfig(endpoint);
|
||||
}
|
||||
|
||||
config = readAnnotatedConfig(endpoint, config);
|
||||
|
||||
return new ConfiguredEndpoint(endpoint, config);
|
||||
}
|
||||
|
||||
protected EndpointConfig newEmptyConfig(Object endpoint)
|
||||
{
|
||||
return new EmptyClientEndpointConfig();
|
||||
}
|
||||
|
||||
protected EndpointConfig readAnnotatedConfig(Object endpoint, EndpointConfig config) throws DeploymentException
|
||||
{
|
||||
ClientEndpoint anno = endpoint.getClass().getAnnotation(ClientEndpoint.class);
|
||||
if (anno != null)
|
||||
{
|
||||
cec = new AnnotatedClientEndpointConfig(anno);
|
||||
// Overwrite Config from Annotation
|
||||
// TODO: should we merge with provided config?
|
||||
return new AnnotatedClientEndpointConfig(anno);
|
||||
}
|
||||
else
|
||||
{
|
||||
cec = new EmptyClientEndpointConfig();
|
||||
}
|
||||
}
|
||||
return new ConfiguredEndpoint(endpoint,cec);
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -83,6 +83,12 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess
|
|||
this.availableDecoders = new AvailableDecoders(this.config);
|
||||
this.availableEncoders = new AvailableEncoders(this.config);
|
||||
|
||||
if(this.config instanceof PathParamProvider)
|
||||
{
|
||||
PathParamProvider pathParamProvider = (PathParamProvider) this.config;
|
||||
pathParameters.putAll(pathParamProvider.getPathParams());
|
||||
}
|
||||
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Optional interface for custom {@link javax.websocket.EndpointConfig} implementations
|
||||
* in Jetty to expose Path Param values used during the {@link org.eclipse.jetty.websocket.jsr356.function.JsrEndpointFunctions}
|
||||
* resolution of methods.
|
||||
* <p>
|
||||
* Mostly a feature of the JSR356 Server implementation and its <code>@javax.websocket.server.PathParam</code> annotation.
|
||||
* </p>
|
||||
*/
|
||||
public interface PathParamProvider
|
||||
{
|
||||
Map<String,String> getPathParams();
|
||||
}
|
|
@ -28,6 +28,7 @@ import java.util.Map;
|
|||
import javax.websocket.Decoder;
|
||||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.Encoder;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.Extension;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
@ -51,14 +52,13 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
|
|||
this(containerScope, endpointClass, anno, null);
|
||||
}
|
||||
|
||||
public AnnotatedServerEndpointConfig(WebSocketContainerScope containerScope, Class<?> endpointClass, ServerEndpoint anno, ServerEndpointConfig baseConfig) throws DeploymentException
|
||||
public AnnotatedServerEndpointConfig(WebSocketContainerScope containerScope, Class<?> endpointClass, ServerEndpoint anno, EndpointConfig baseConfig) throws DeploymentException
|
||||
{
|
||||
ServerEndpointConfig.Configurator configr = null;
|
||||
ServerEndpointConfig baseServerConfig = null;
|
||||
|
||||
// Copy from base config
|
||||
if (baseConfig != null)
|
||||
if (baseConfig instanceof ServerEndpointConfig)
|
||||
{
|
||||
configr = baseConfig.getConfigurator();
|
||||
baseServerConfig = (ServerEndpointConfig) baseConfig;
|
||||
}
|
||||
|
||||
// Decoders (favor provided config over annotation)
|
||||
|
@ -82,9 +82,9 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
|
|||
}
|
||||
|
||||
// Sub Protocols (favor provided config over annotation)
|
||||
if (baseConfig != null && baseConfig.getSubprotocols() != null && baseConfig.getSubprotocols().size() > 0)
|
||||
if (baseServerConfig != null && baseServerConfig.getSubprotocols() != null && baseServerConfig.getSubprotocols().size() > 0)
|
||||
{
|
||||
this.subprotocols = Collections.unmodifiableList(baseConfig.getSubprotocols());
|
||||
this.subprotocols = Collections.unmodifiableList(baseServerConfig.getSubprotocols());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -92,9 +92,9 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
|
|||
}
|
||||
|
||||
// Path (favor provided config over annotation)
|
||||
if (baseConfig != null && baseConfig.getPath() != null && baseConfig.getPath().length() > 0)
|
||||
if (baseServerConfig != null && baseServerConfig.getPath() != null && baseServerConfig.getPath().length() > 0)
|
||||
{
|
||||
this.path = baseConfig.getPath();
|
||||
this.path = baseServerConfig.getPath();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -112,29 +112,43 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
|
|||
userProperties.putAll(baseConfig.getUserProperties());
|
||||
}
|
||||
|
||||
ServerEndpointConfig.Configurator cfgr;
|
||||
ServerEndpointConfig.Configurator rawConfigurator = getConfigurator(baseServerConfig, anno);
|
||||
|
||||
// Make sure all Configurators obtained are decorated
|
||||
this.configurator = containerScope.getObjectFactory().decorate(rawConfigurator);
|
||||
}
|
||||
|
||||
private Configurator getConfigurator(ServerEndpointConfig baseServerConfig, ServerEndpoint anno) throws DeploymentException
|
||||
{
|
||||
Configurator ret = null;
|
||||
|
||||
// Copy from base config
|
||||
if (baseServerConfig != null)
|
||||
{
|
||||
ret = baseServerConfig.getConfigurator();
|
||||
}
|
||||
|
||||
if (anno != null)
|
||||
{
|
||||
// Is this using the JSR356 spec/api default?
|
||||
if (anno.configurator() == ServerEndpointConfig.Configurator.class)
|
||||
{
|
||||
if (configr != null)
|
||||
{
|
||||
cfgr = configr;
|
||||
}
|
||||
// Return the spec default impl if one wasn't provided as part of the base config
|
||||
if (ret == null)
|
||||
return new ContainerDefaultConfigurator();
|
||||
else
|
||||
{
|
||||
cfgr = new ContainerDefaultConfigurator();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Instantiate the provided configurator
|
||||
try
|
||||
{
|
||||
cfgr = anno.configurator().newInstance();
|
||||
return anno.configurator().newInstance();
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException e)
|
||||
{
|
||||
StringBuilder err = new StringBuilder();
|
||||
err.append("Unable to instantiate ClientEndpoint.configurator() of ");
|
||||
err.append("Unable to instantiate ServerEndpoint.configurator() of ");
|
||||
err.append(anno.configurator().getName());
|
||||
err.append(" defined as annotation in ");
|
||||
err.append(anno.getClass().getName());
|
||||
|
@ -142,8 +156,7 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
|
|||
}
|
||||
}
|
||||
|
||||
// Make sure all Configurators obtained are decorated
|
||||
this.configurator = containerScope.getObjectFactory().decorate(cfgr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 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.LinkedList;
|
||||
|
||||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
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;
|
||||
|
||||
public class AnnotatedServerEndpointMetadata extends AnnotatedEndpointMetadata<ServerEndpoint,ServerEndpointConfig> implements ServerEndpointMetadata
|
||||
{
|
||||
private final ServerEndpoint endpoint;
|
||||
private final AnnotatedServerEndpointConfig config;
|
||||
|
||||
protected AnnotatedServerEndpointMetadata(WebSocketContainerScope containerScope, Class<?> websocket, ServerEndpointConfig baseConfig) throws DeploymentException
|
||||
{
|
||||
super(websocket);
|
||||
|
||||
ServerEndpoint anno = websocket.getAnnotation(ServerEndpoint.class);
|
||||
if (anno == null)
|
||||
{
|
||||
throw new InvalidWebSocketException("Unsupported WebSocket object, missing @" + ServerEndpoint.class + " annotation");
|
||||
}
|
||||
|
||||
this.endpoint = anno;
|
||||
this.config = new AnnotatedServerEndpointConfig(containerScope,websocket,anno,baseConfig);
|
||||
|
||||
getDecoders().addAll(anno.decoders());
|
||||
getEncoders().addAll(anno.encoders());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customizeParamsOnClose(LinkedList<IJsrParamId> params)
|
||||
{
|
||||
super.customizeParamsOnClose(params);
|
||||
params.addFirst(JsrPathParamId.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customizeParamsOnError(LinkedList<IJsrParamId> params)
|
||||
{
|
||||
super.customizeParamsOnError(params);
|
||||
params.addFirst(JsrPathParamId.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customizeParamsOnOpen(LinkedList<IJsrParamId> params)
|
||||
{
|
||||
super.customizeParamsOnOpen(params);
|
||||
params.addFirst(JsrPathParamId.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customizeParamsOnMessage(LinkedList<IJsrParamId> params)
|
||||
{
|
||||
super.customizeParamsOnMessage(params);
|
||||
params.addFirst(JsrPathParamId.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerEndpoint getAnnotation()
|
||||
{
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
public AnnotatedServerEndpointConfig getConfig()
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return config.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("AnnotatedServerEndpointMetadata[endpoint=");
|
||||
builder.append(endpoint);
|
||||
builder.append(",config=");
|
||||
builder.append(config);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.websocket.jsr356.server;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -36,7 +37,6 @@ 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.ConfiguredEndpoint;
|
||||
import org.eclipse.jetty.websocket.jsr356.JsrExtension;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||
|
@ -49,13 +49,13 @@ public class JsrCreator implements WebSocketCreator
|
|||
public static final String PROP_LOCALES = "javax.websocket.upgrade.locales";
|
||||
private static final Logger LOG = Log.getLogger(JsrCreator.class);
|
||||
private final WebSocketContainerScope containerScope;
|
||||
private final ServerEndpointMetadata metadata;
|
||||
private final ServerEndpointConfig baseConfig;
|
||||
private final ExtensionFactory extensionFactory;
|
||||
|
||||
public JsrCreator(WebSocketContainerScope containerScope, ServerEndpointMetadata metadata, ExtensionFactory extensionFactory)
|
||||
public JsrCreator(WebSocketContainerScope containerScope, ServerEndpointConfig config, ExtensionFactory extensionFactory)
|
||||
{
|
||||
this.containerScope = containerScope;
|
||||
this.metadata = metadata;
|
||||
this.baseConfig = config;
|
||||
this.extensionFactory = extensionFactory;
|
||||
}
|
||||
|
||||
|
@ -65,12 +65,18 @@ public class JsrCreator implements WebSocketCreator
|
|||
JsrHandshakeRequest jsrHandshakeRequest = new JsrHandshakeRequest(req);
|
||||
JsrHandshakeResponse jsrHandshakeResponse = new JsrHandshakeResponse(resp);
|
||||
|
||||
// Get raw config, as defined when the endpoint was added to the container
|
||||
ServerEndpointConfig config = metadata.getConfig();
|
||||
|
||||
// Establish a copy of the config, so that the UserProperties are unique
|
||||
// per upgrade request.
|
||||
config = new BasicServerEndpointConfig(containerScope, config);
|
||||
ServerEndpointConfig config = new ServerEndpointConfigWrapper(baseConfig)
|
||||
{
|
||||
Map<String,Object> userProperties = new HashMap<>(baseConfig.getUserProperties());
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getUserProperties()
|
||||
{
|
||||
return userProperties;
|
||||
}
|
||||
};
|
||||
|
||||
// Bug 444617 - Expose localAddress and remoteAddress for jsr modify handshake to use
|
||||
// This is being implemented as an optional set of userProperties so that
|
||||
|
@ -143,7 +149,7 @@ public class JsrCreator implements WebSocketCreator
|
|||
UriTemplatePathSpec wspathSpec = (UriTemplatePathSpec)pathSpec;
|
||||
String requestPath = req.getRequestPath();
|
||||
// Wrap the config with the path spec information
|
||||
config = new PathParamServerEndpointConfig(containerScope,config,wspathSpec,requestPath);
|
||||
config = new PathParamServerEndpointConfig(config,wspathSpec,requestPath);
|
||||
}
|
||||
|
||||
// [JSR] Step 5: Call modifyHandshake
|
||||
|
@ -156,16 +162,7 @@ public class JsrCreator implements WebSocketCreator
|
|||
Object endpoint = config.getConfigurator().getEndpointInstance(endpointClass);
|
||||
// Do not decorate here (let the Connection and Session start first)
|
||||
// This will allow CDI to see Session for injection into Endpoint classes.
|
||||
PathSpec pathSpec = hsreq.getRequestPathSpec();
|
||||
if (pathSpec instanceof UriTemplatePathSpec)
|
||||
{
|
||||
// We have a PathParam path spec
|
||||
UriTemplatePathSpec wspathSpec = (UriTemplatePathSpec)pathSpec;
|
||||
String requestPath = req.getRequestPath();
|
||||
// Wrap the config with the path spec information
|
||||
config = new PathParamServerEndpointConfig(containerScope,config,wspathSpec,requestPath);
|
||||
}
|
||||
return new ConfiguredEndpoint(endpoint,config);
|
||||
return endpoint;
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
|
@ -178,6 +175,6 @@ public class JsrCreator implements WebSocketCreator
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s[metadata=%s]",this.getClass().getName(),metadata);
|
||||
return String.format("%s[config=%s]",this.getClass().getName(),baseConfig);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 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 javax.websocket.server.PathParam;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.InvalidSignatureException;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.IJsrParamId;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.JsrCallable;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.Param;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
|
||||
|
||||
/**
|
||||
* Param handling for static parameters annotated with @{@link PathParam}
|
||||
*/
|
||||
public class JsrPathParamId implements IJsrParamId
|
||||
{
|
||||
public static final IJsrParamId INSTANCE = new JsrPathParamId();
|
||||
|
||||
@Override
|
||||
public boolean process(Param param, JsrCallable callable) throws InvalidSignatureException
|
||||
{
|
||||
PathParam pathparam = param.getAnnotation(PathParam.class);
|
||||
if(pathparam != null)
|
||||
{
|
||||
param.bind(Role.PATH_PARAM);
|
||||
param.setPathParamName(pathparam.value());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 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 javax.websocket.OnMessage;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriver;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriverImpl;
|
||||
import org.eclipse.jetty.websocket.jsr356.ConfiguredEndpoint;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.JsrEvents;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.OnMessageCallable;
|
||||
import org.eclipse.jetty.websocket.jsr356.endpoints.JsrAnnotatedEventDriver;
|
||||
|
||||
/**
|
||||
* Event Driver for classes annotated with @{@link ServerEndpoint}
|
||||
*/
|
||||
public class JsrServerEndpointImpl implements EventDriverImpl
|
||||
{
|
||||
@Override
|
||||
public EventDriver create(Object websocket, WebSocketPolicy policy) throws Throwable
|
||||
{
|
||||
if (!(websocket instanceof ConfiguredEndpoint))
|
||||
{
|
||||
throw new IllegalStateException(String.format("Websocket %s must be an %s",websocket.getClass().getName(),ConfiguredEndpoint.class.getName()));
|
||||
}
|
||||
|
||||
ConfiguredEndpoint ei = (ConfiguredEndpoint)websocket;
|
||||
AnnotatedServerEndpointMetadata metadata = (AnnotatedServerEndpointMetadata)ei.getMetadata();
|
||||
JsrEvents<ServerEndpoint, ServerEndpointConfig> events = new JsrEvents<>(metadata);
|
||||
|
||||
// Handle @OnMessage maxMessageSizes
|
||||
int maxBinaryMessage = getMaxMessageSize(policy.getMaxBinaryMessageSize(),metadata.onBinary,metadata.onBinaryStream);
|
||||
int maxTextMessage = getMaxMessageSize(policy.getMaxTextMessageSize(),metadata.onText,metadata.onTextStream);
|
||||
|
||||
policy.setMaxBinaryMessageSize(maxBinaryMessage);
|
||||
policy.setMaxTextMessageSize(maxTextMessage);
|
||||
|
||||
JsrAnnotatedEventDriver driver = new JsrAnnotatedEventDriver(policy,ei,events);
|
||||
// Handle @PathParam values
|
||||
ServerEndpointConfig config = (ServerEndpointConfig)ei.getConfig();
|
||||
if (config instanceof PathParamServerEndpointConfig)
|
||||
{
|
||||
PathParamServerEndpointConfig ppconfig = (PathParamServerEndpointConfig)config;
|
||||
driver.setPathParameters(ppconfig.getPathParamMap());
|
||||
}
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String describeRule()
|
||||
{
|
||||
return "class is annotated with @" + ServerEndpoint.class.getName();
|
||||
}
|
||||
|
||||
private int getMaxMessageSize(int defaultMaxMessageSize, OnMessageCallable... onMessages)
|
||||
{
|
||||
for (OnMessageCallable callable : onMessages)
|
||||
{
|
||||
if (callable == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
OnMessage onMsg = callable.getMethod().getAnnotation(OnMessage.class);
|
||||
if (onMsg == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (onMsg.maxMessageSize() > 0)
|
||||
{
|
||||
return (int)onMsg.maxMessageSize();
|
||||
}
|
||||
}
|
||||
return defaultMaxMessageSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Object websocket)
|
||||
{
|
||||
if (!(websocket instanceof ConfiguredEndpoint))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ConfiguredEndpoint ei = (ConfiguredEndpoint)websocket;
|
||||
Object endpoint = ei.getEndpoint();
|
||||
|
||||
ServerEndpoint anno = endpoint.getClass().getAnnotation(ServerEndpoint.class);
|
||||
return (anno != null);
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 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 javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriver;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriverImpl;
|
||||
import org.eclipse.jetty.websocket.jsr356.ConfiguredEndpoint;
|
||||
import org.eclipse.jetty.websocket.jsr356.endpoints.JsrEndpointEventDriver;
|
||||
|
||||
public class JsrServerExtendsEndpointImpl implements EventDriverImpl
|
||||
{
|
||||
@Override
|
||||
public EventDriver create(Object websocket, WebSocketPolicy policy)
|
||||
{
|
||||
if (!(websocket instanceof ConfiguredEndpoint))
|
||||
{
|
||||
throw new IllegalStateException(String.format("Websocket %s must be an %s",websocket.getClass().getName(),ConfiguredEndpoint.class.getName()));
|
||||
}
|
||||
|
||||
ConfiguredEndpoint ei = (ConfiguredEndpoint)websocket;
|
||||
JsrEndpointEventDriver driver = new JsrEndpointEventDriver(policy, ei);
|
||||
|
||||
ServerEndpointConfig config = (ServerEndpointConfig)ei.getConfig();
|
||||
if (config instanceof PathParamServerEndpointConfig)
|
||||
{
|
||||
PathParamServerEndpointConfig ppconfig = (PathParamServerEndpointConfig)config;
|
||||
driver.setPathParameters(ppconfig.getPathParamMap());
|
||||
}
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String describeRule()
|
||||
{
|
||||
return "class extends " + javax.websocket.Endpoint.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Object websocket)
|
||||
{
|
||||
if (!(websocket instanceof ConfiguredEndpoint))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ConfiguredEndpoint ei = (ConfiguredEndpoint)websocket;
|
||||
Object endpoint = ei.getEndpoint();
|
||||
|
||||
return (endpoint instanceof javax.websocket.Endpoint);
|
||||
}
|
||||
}
|
|
@ -18,13 +18,23 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.jsr356.server;
|
||||
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
import javax.websocket.server.PathParam;
|
||||
|
||||
import org.eclipse.jetty.websocket.jsr356.metadata.EndpointMetadata;
|
||||
import org.eclipse.jetty.websocket.common.reflect.Arg;
|
||||
import org.eclipse.jetty.websocket.common.reflect.ArgIdentifier;
|
||||
|
||||
public interface ServerEndpointMetadata extends EndpointMetadata
|
||||
/**
|
||||
* Identify method parameters tagged with @{@link javax.websocket.server.PathParam}
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class PathParamArgIdentifier implements ArgIdentifier
|
||||
{
|
||||
ServerEndpointConfig getConfig();
|
||||
|
||||
public String getPath();
|
||||
@Override
|
||||
public Arg apply(Arg arg)
|
||||
{
|
||||
PathParam param = arg.getAnnotation(PathParam.class);
|
||||
if (param != null)
|
||||
arg.setTag(param.value());
|
||||
return arg;
|
||||
}
|
||||
}
|
|
@ -24,19 +24,19 @@ import java.util.Map;
|
|||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
|
||||
import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
|
||||
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
|
||||
import org.eclipse.jetty.websocket.jsr356.PathParamProvider;
|
||||
|
||||
/**
|
||||
* Wrapper for a {@link ServerEndpointConfig} where there is PathParam information from the incoming request.
|
||||
* Make {@link javax.websocket.server.PathParam} information from the incoming request available
|
||||
* on {@link ServerEndpointConfig}
|
||||
*/
|
||||
public class PathParamServerEndpointConfig extends BasicServerEndpointConfig implements ServerEndpointConfig
|
||||
public class PathParamServerEndpointConfig extends ServerEndpointConfigWrapper implements PathParamProvider
|
||||
{
|
||||
private final Map<String, String> pathParamMap;
|
||||
|
||||
public PathParamServerEndpointConfig(WebSocketContainerScope containerScope, ServerEndpointConfig config, UriTemplatePathSpec pathSpec, String requestPath)
|
||||
public PathParamServerEndpointConfig(ServerEndpointConfig config, UriTemplatePathSpec pathSpec, String requestPath)
|
||||
{
|
||||
super(containerScope, config);
|
||||
super(config);
|
||||
|
||||
Map<String, String> pathMap = pathSpec.getPathParams(requestPath);
|
||||
pathParamMap = new HashMap<>();
|
||||
|
@ -46,7 +46,8 @@ public class PathParamServerEndpointConfig extends BasicServerEndpointConfig imp
|
|||
}
|
||||
}
|
||||
|
||||
public Map<String, String> getPathParamMap()
|
||||
@Override
|
||||
public Map<String, String> getPathParams()
|
||||
{
|
||||
return pathParamMap;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import java.util.Set;
|
|||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.Endpoint;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.WebSocketContainer;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
@ -38,13 +38,9 @@ import org.eclipse.jetty.util.annotation.ManagedObject;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
|
||||
import org.eclipse.jetty.websocket.jsr356.ClientContainer;
|
||||
import org.eclipse.jetty.websocket.jsr356.ConfiguredEndpoint;
|
||||
import org.eclipse.jetty.websocket.jsr356.JsrSessionFactory;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
|
||||
import org.eclipse.jetty.websocket.jsr356.metadata.EndpointMetadata;
|
||||
import org.eclipse.jetty.websocket.server.NativeWebSocketConfiguration;
|
||||
import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
|
||||
|
||||
@ManagedObject("JSR356 Server Container")
|
||||
|
@ -52,116 +48,115 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
|
|||
{
|
||||
private static final Logger LOG = Log.getLogger(ServerContainer.class);
|
||||
|
||||
/**
|
||||
* Get the WebSocketContainer out of the current ThreadLocal reference
|
||||
* of the active ContextHandler.
|
||||
*
|
||||
* @return the WebSocketContainer if found, null if not found.
|
||||
*/
|
||||
public static WebSocketContainer getWebSocketContainer()
|
||||
{
|
||||
ContextHandler.Context context = ContextHandler.getCurrentContext();
|
||||
if (context == null)
|
||||
return null;
|
||||
|
||||
ContextHandler handler = ContextHandler.getContextHandler(context);
|
||||
if (handler == null)
|
||||
return null;
|
||||
|
||||
if (!(handler instanceof ServletContextHandler))
|
||||
return null;
|
||||
|
||||
return (javax.websocket.WebSocketContainer) handler.getServletContext().getAttribute("javax.websocket.server.ServerContainer");
|
||||
}
|
||||
|
||||
private final NativeWebSocketConfiguration configuration;
|
||||
private final MappedWebSocketCreator mappedCreator;
|
||||
private final WebSocketServerFactory webSocketServerFactory;
|
||||
private List<Class<?>> deferredEndpointClasses;
|
||||
private List<ServerEndpointConfig> deferredEndpointConfigs;
|
||||
|
||||
/**
|
||||
* @deprecated use {@code ServerContainer(NativeWebSocketConfiguration, HttpClient)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public ServerContainer(NativeWebSocketConfiguration configuration, Executor executor)
|
||||
public ServerContainer(MappedWebSocketCreator creator, WebSocketServerFactory factory, Executor executor)
|
||||
{
|
||||
this(configuration, (HttpClient) null);
|
||||
}
|
||||
|
||||
public ServerContainer(NativeWebSocketConfiguration configuration, HttpClient httpClient)
|
||||
{
|
||||
super(configuration.getFactory(), httpClient);
|
||||
this.configuration = configuration;
|
||||
EventDriverFactory eventDriverFactory = this.configuration.getFactory().getEventDriverFactory();
|
||||
eventDriverFactory.addImplementation(new JsrServerEndpointImpl());
|
||||
eventDriverFactory.addImplementation(new JsrServerExtendsEndpointImpl());
|
||||
this.configuration.getFactory().addSessionFactory(new JsrSessionFactory(this));
|
||||
addBean(this.configuration);
|
||||
}
|
||||
|
||||
public ConfiguredEndpoint newClientEndpointInstance(Object endpoint, ServerEndpointConfig config, String path)
|
||||
{
|
||||
EndpointMetadata metadata = getClientEndpointMetadata(endpoint.getClass(),config);
|
||||
ServerEndpointConfig cec = config;
|
||||
if (config == null)
|
||||
{
|
||||
if (metadata instanceof AnnotatedServerEndpointMetadata)
|
||||
{
|
||||
cec = ((AnnotatedServerEndpointMetadata)metadata).getConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
cec = new BasicServerEndpointConfig(this,endpoint.getClass(),path);
|
||||
}
|
||||
}
|
||||
return new ConfiguredEndpoint(endpoint,cec,metadata);
|
||||
super(factory);
|
||||
this.mappedCreator = creator;
|
||||
this.webSocketServerFactory = factory;
|
||||
this.webSocketServerFactory.addSessionFactory(new JsrSessionFactory(this));
|
||||
addBean(webSocketServerFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EndpointConfig newEmptyConfig(Object endpoint)
|
||||
{
|
||||
return new UndefinedServerEndpointConfig(endpoint.getClass());
|
||||
}
|
||||
|
||||
protected EndpointConfig readAnnotatedConfig(Object endpoint, EndpointConfig config) throws DeploymentException
|
||||
{
|
||||
ServerEndpoint anno = endpoint.getClass().getAnnotation(ServerEndpoint.class);
|
||||
if (anno != null)
|
||||
{
|
||||
// Overwrite Config from Annotation
|
||||
// TODO: should we merge with provided config?
|
||||
return new AnnotatedServerEndpointConfig(this, endpoint.getClass(), anno, config);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a @{@link ServerEndpoint} annotated endpoint class to
|
||||
* the server
|
||||
*
|
||||
* @param endpointClass the annotated endpoint class to add to the server
|
||||
* @throws DeploymentException if unable to deploy that endpoint class
|
||||
* @see javax.websocket.server.ServerContainer#addEndpoint(Class)
|
||||
*/
|
||||
@Override
|
||||
public void addEndpoint(Class<?> endpointClass) throws DeploymentException
|
||||
{
|
||||
if (endpointClass == null)
|
||||
{
|
||||
throw new DeploymentException("EndpointClass is null");
|
||||
}
|
||||
|
||||
if (isStarted() || isStarting())
|
||||
{
|
||||
ServerEndpointMetadata metadata = getServerEndpointMetadata(endpointClass,null);
|
||||
addEndpoint(metadata);
|
||||
ServerEndpoint anno = endpointClass.getAnnotation(ServerEndpoint.class);
|
||||
if (anno == null)
|
||||
{
|
||||
throw new DeploymentException(String.format("Class must be @%s annotated: %s",
|
||||
ServerEndpoint.class.getName(), endpointClass.getName()));
|
||||
}
|
||||
|
||||
ServerEndpointConfig config = new AnnotatedServerEndpointConfig(this, endpointClass, anno);
|
||||
addEndpointMapping(config);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (deferredEndpointClasses == null)
|
||||
{
|
||||
deferredEndpointClasses = new ArrayList<Class<?>>();
|
||||
deferredEndpointClasses = new ArrayList<>();
|
||||
}
|
||||
deferredEndpointClasses.add(endpointClass);
|
||||
}
|
||||
}
|
||||
|
||||
private void addEndpoint(ServerEndpointMetadata metadata) throws DeploymentException
|
||||
{
|
||||
JsrCreator creator = new JsrCreator(this,metadata,this.configuration.getFactory().getExtensionFactory());
|
||||
this.configuration.addMapping("uri-template|" + metadata.getPath(), creator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a ServerEndpointConfig to the server
|
||||
*
|
||||
* @param config the endpoint config to add
|
||||
* @throws DeploymentException if unable to deploy that endpoint class
|
||||
* @see javax.websocket.server.ServerContainer#addEndpoint(ServerEndpointConfig)
|
||||
*/
|
||||
@Override
|
||||
public void addEndpoint(ServerEndpointConfig config) throws DeploymentException
|
||||
{
|
||||
if (config == null)
|
||||
{
|
||||
throw new DeploymentException("ServerEndpointConfig is null");
|
||||
}
|
||||
|
||||
if (isStarted() || isStarting())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("addEndpoint({}) path={} endpoint={}", config, config.getPath(), config.getEndpointClass());
|
||||
}
|
||||
ServerEndpointMetadata metadata = getServerEndpointMetadata(config.getEndpointClass(),config);
|
||||
addEndpoint(metadata);
|
||||
addEndpointMapping(config);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (deferredEndpointConfigs == null)
|
||||
{
|
||||
deferredEndpointConfigs = new ArrayList<ServerEndpointConfig>();
|
||||
deferredEndpointConfigs = new ArrayList<>();
|
||||
}
|
||||
deferredEndpointConfigs.add(config);
|
||||
}
|
||||
}
|
||||
|
||||
private void addEndpointMapping(ServerEndpointConfig config) throws DeploymentException
|
||||
{
|
||||
JsrCreator creator = new JsrCreator(this, config, webSocketServerFactory.getExtensionFactory());
|
||||
mappedCreator.addMapping(new UriTemplatePathSpec(config.getPath()), creator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
|
@ -188,39 +183,6 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
|
|||
}
|
||||
}
|
||||
|
||||
public ServerEndpointMetadata getServerEndpointMetadata(final Class<?> endpoint, final ServerEndpointConfig config) throws DeploymentException
|
||||
{
|
||||
ServerEndpointMetadata metadata = null;
|
||||
|
||||
ServerEndpoint anno = endpoint.getAnnotation(ServerEndpoint.class);
|
||||
if (anno != null)
|
||||
{
|
||||
// Annotated takes precedence here
|
||||
AnnotatedServerEndpointMetadata ametadata = new AnnotatedServerEndpointMetadata(this,endpoint,config);
|
||||
AnnotatedEndpointScanner<ServerEndpoint, ServerEndpointConfig> scanner = new AnnotatedEndpointScanner<>(ametadata);
|
||||
metadata = ametadata;
|
||||
scanner.scan();
|
||||
}
|
||||
else if (Endpoint.class.isAssignableFrom(endpoint))
|
||||
{
|
||||
// extends Endpoint
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends Endpoint> eendpoint = (Class<? extends Endpoint>)endpoint;
|
||||
metadata = new SimpleServerEndpointMetadata(eendpoint,config);
|
||||
}
|
||||
else
|
||||
{
|
||||
StringBuilder err = new StringBuilder();
|
||||
err.append("Not a recognized websocket [");
|
||||
err.append(endpoint.getName());
|
||||
err.append("] does not extend @").append(ServerEndpoint.class.getName());
|
||||
err.append(" or extend from ").append(Endpoint.class.getName());
|
||||
throw new DeploymentException("Unable to identify as valid Endpoint: " + endpoint);
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDefaultAsyncSendTimeout()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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 java.util.Map;
|
||||
|
||||
import javax.websocket.Decoder;
|
||||
import javax.websocket.Encoder;
|
||||
import javax.websocket.Extension;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
public abstract class ServerEndpointConfigWrapper implements ServerEndpointConfig
|
||||
{
|
||||
private final ServerEndpointConfig delegate;
|
||||
|
||||
public ServerEndpointConfigWrapper(ServerEndpointConfig delegate)
|
||||
{
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<? extends Encoder>> getEncoders()
|
||||
{
|
||||
return delegate.getEncoders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<? extends Decoder>> getDecoders()
|
||||
{
|
||||
return delegate.getDecoders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getUserProperties()
|
||||
{
|
||||
return delegate.getUserProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEndpointClass()
|
||||
{
|
||||
return delegate.getEndpointClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath()
|
||||
{
|
||||
return delegate.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSubprotocols()
|
||||
{
|
||||
return delegate.getSubprotocols();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Extension> getExtensions()
|
||||
{
|
||||
return delegate.getExtensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configurator getConfigurator()
|
||||
{
|
||||
return delegate.getConfigurator();
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 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 javax.websocket.Endpoint;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
import org.eclipse.jetty.websocket.jsr356.client.SimpleEndpointMetadata;
|
||||
|
||||
public class SimpleServerEndpointMetadata extends SimpleEndpointMetadata implements ServerEndpointMetadata
|
||||
{
|
||||
private final ServerEndpointConfig config;
|
||||
|
||||
public SimpleServerEndpointMetadata(Class<? extends Endpoint> endpointClass, ServerEndpointConfig config)
|
||||
{
|
||||
super(endpointClass,config);
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerEndpointConfig getConfig()
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath()
|
||||
{
|
||||
return config.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("SimpleServerEndpointMetadata [");
|
||||
builder.append("config=").append(config.getClass().getName());
|
||||
builder.append(",path=").append(config.getPath());
|
||||
builder.append(",endpoint=").append(config.getEndpointClass());
|
||||
builder.append(",decoders=").append(config.getDecoders());
|
||||
builder.append(",encoders=").append(config.getEncoders());
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.websocket.Decoder;
|
||||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.Encoder;
|
||||
import javax.websocket.Extension;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
public class UndefinedServerEndpointConfig implements ServerEndpointConfig
|
||||
{
|
||||
private final List<Class<? extends Decoder>> decoders;
|
||||
private final List<Class<? extends Encoder>> encoders;
|
||||
private final List<Extension> extensions;
|
||||
private final List<String> subprotocols;
|
||||
private final ServerEndpointConfig.Configurator configurator;
|
||||
private final Class<?> endpointClass;
|
||||
private Map<String, Object> userProperties;
|
||||
|
||||
public UndefinedServerEndpointConfig(Class<?> endpointClass)
|
||||
{
|
||||
this.endpointClass = endpointClass;
|
||||
this.decoders = new ArrayList<>();
|
||||
this.encoders = new ArrayList<>();
|
||||
this.subprotocols = new ArrayList<>();
|
||||
this.extensions = new ArrayList<>();
|
||||
this.userProperties = new HashMap<>();
|
||||
this.configurator = new ContainerDefaultConfigurator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<? extends Encoder>> getEncoders()
|
||||
{
|
||||
return encoders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<? extends Decoder>> getDecoders()
|
||||
{
|
||||
return decoders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getUserProperties()
|
||||
{
|
||||
return userProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEndpointClass()
|
||||
{
|
||||
return endpointClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath()
|
||||
{
|
||||
throw new RuntimeException("Using an UndefinedServerEndpointConfig");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSubprotocols()
|
||||
{
|
||||
return subprotocols;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Extension> getExtensions()
|
||||
{
|
||||
return extensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerEndpointConfig.Configurator getConfigurator()
|
||||
{
|
||||
return configurator;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.eclipse.jetty.websocket.common.reflect.NameArgIdentifier
|
|
@ -20,8 +20,8 @@ package org.eclipse.jetty.websocket.jsr356.server;
|
|||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -55,7 +55,7 @@ public class AnnotatedServerEndpointTest
|
|||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
File testdir = MavenTestingUtils.getTargetTestingDir(AnnotatedServerEndpointTest.class.getName());
|
||||
Path testdir = MavenTestingUtils.getTargetTestingPath(AnnotatedServerEndpointTest.class.getName());
|
||||
server = new WSServer(testdir,"app");
|
||||
server.createWebInf();
|
||||
server.copyEndpoint(ConfiguredEchoSocket.class);
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidCloseIntSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidErrorErrorSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidErrorExceptionSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidErrorIntSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidOpenCloseReasonSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidOpenIntSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidOpenSessionIntSocket;
|
||||
import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
/**
|
||||
* Deploy various {@link ServerEndpoint} annotated classes with invalid signatures,
|
||||
* check for {@link DeploymentException}
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class DeploymentExceptionTest
|
||||
{
|
||||
@Parameters(name = "{0}")
|
||||
public static Collection<Class<?>[]> data()
|
||||
{
|
||||
List<Class<?>[]> data = new ArrayList<>();
|
||||
|
||||
data.add(new Class<?>[]{InvalidCloseIntSocket.class});
|
||||
data.add(new Class<?>[]{InvalidErrorErrorSocket.class});
|
||||
data.add(new Class<?>[]{InvalidErrorExceptionSocket.class});
|
||||
data.add(new Class<?>[]{InvalidErrorIntSocket.class});
|
||||
data.add(new Class<?>[]{InvalidOpenCloseReasonSocket.class});
|
||||
data.add(new Class<?>[]{InvalidOpenIntSocket.class});
|
||||
data.add(new Class<?>[]{InvalidOpenSessionIntSocket.class});
|
||||
|
||||
// TODO: invalid return types
|
||||
// TODO: static methods
|
||||
// TODO: private or protected methods
|
||||
// TODO: abstract methods
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
/** The pojo to test */
|
||||
@Parameterized.Parameter(0)
|
||||
public Class<?> pojo;
|
||||
|
||||
@Test
|
||||
public void testDeploy_InvalidSignature() throws Exception
|
||||
{
|
||||
MappedWebSocketCreator creator = new DummyCreator();
|
||||
WebSocketServerFactory serverFactory = new WebSocketServerFactory();
|
||||
Executor executor = new QueuedThreadPool();
|
||||
ServerContainer container = new ServerContainer(creator, serverFactory, executor);
|
||||
|
||||
try
|
||||
{
|
||||
container.start();
|
||||
expectedException.expect(DeploymentException.class);
|
||||
container.addEndpoint(pojo);
|
||||
}
|
||||
finally
|
||||
{
|
||||
container.stop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -96,6 +96,16 @@ public class EchoClientSocket extends TrackingSocket
|
|||
return eventCountLatch.await(timeout,unit);
|
||||
}
|
||||
|
||||
public void sendText(String msg) throws IOException, EncodeException
|
||||
{
|
||||
remote.sendText(msg);
|
||||
}
|
||||
|
||||
public void sendBinary(ByteBuffer msg) throws IOException, EncodeException
|
||||
{
|
||||
remote.sendBinary(msg);
|
||||
}
|
||||
|
||||
public void sendObject(Object obj) throws IOException, EncodeException
|
||||
{
|
||||
remote.sendObject(obj);
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.jsr356.server;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.eclipse.jetty.toolchain.test.ExtraMatchers.ordered;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
@ -36,6 +38,21 @@ import org.eclipse.jetty.util.BufferUtil;
|
|||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.EchoCase.PartialBinary;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.EchoCase.PartialText;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicCloseReasonSessionSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicCloseReasonSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicCloseSessionReasonSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicCloseSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorSessionSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorSessionThrowableSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorThrowableSessionSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorThrowableSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicOpenSessionSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicOpenSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicPongMessageSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicTextMessageStringSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.StatelessTextMessageStringSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.beans.DateTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.binary.ByteBufferSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.partial.PartialTextSessionSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.partial.PartialTextSocket;
|
||||
|
@ -61,7 +78,6 @@ import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderParamSo
|
|||
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.StringReturnReaderParamSocket;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
@ -182,6 +198,10 @@ public class EchoTest
|
|||
// PathParam based
|
||||
EchoCase.add(TESTCASES,IntParamTextSocket.class).requestPath("/echo/primitives/integer/params/5678").addMessage(1234).expect("1234|5678");
|
||||
|
||||
// Text based
|
||||
EchoCase.add(TESTCASES,BasicTextMessageStringSocket.class).addMessage("Hello").expect("Hello");
|
||||
EchoCase.add(TESTCASES,StatelessTextMessageStringSocket.class).addMessage("Hello").expect("Hello");
|
||||
|
||||
// ByteBuffer based
|
||||
EchoCase.add(TESTCASES,ByteBufferSocket.class).addMessage(BufferUtil.toBuffer("Hello World")).expect("Hello World");
|
||||
|
||||
|
@ -201,12 +221,35 @@ public class EchoTest
|
|||
EchoCase.add(TESTCASES,PartialTextSessionSocket.class)
|
||||
.addSplitMessage("Built"," for"," the"," future")
|
||||
.expect("('Built',false)(' for',false)(' the',false)(' future',true)");
|
||||
|
||||
// Beans
|
||||
EchoCase.add(TESTCASES, DateTextSocket.class).addMessage("Ooops").expect("");
|
||||
|
||||
// Pong
|
||||
EchoCase.add(TESTCASES, BasicPongMessageSocket.class).addMessage("send-ping").expect("Pong[]");
|
||||
|
||||
// Open Events
|
||||
EchoCase.add(TESTCASES, BasicOpenSocket.class).expect("Open[]");
|
||||
EchoCase.add(TESTCASES, BasicOpenSessionSocket.class).expect("Open[Session]");
|
||||
|
||||
// Close Events
|
||||
EchoCase.add(TESTCASES, BasicCloseSocket.class).expect("Close[]");
|
||||
EchoCase.add(TESTCASES, BasicCloseReasonSocket.class).expect("Close[Reason]");
|
||||
EchoCase.add(TESTCASES, BasicCloseReasonSessionSocket.class).expect("Close[Reason,Session]");
|
||||
EchoCase.add(TESTCASES, BasicCloseSessionReasonSocket.class).expect("Close[Session,Reason]");
|
||||
|
||||
// Error Events
|
||||
EchoCase.add(TESTCASES, BasicErrorSocket.class).expect("Error[]");
|
||||
EchoCase.add(TESTCASES, BasicErrorSessionSocket.class).expect("Error[Session]");
|
||||
EchoCase.add(TESTCASES, BasicErrorSessionThrowableSocket.class).expect("Error[Session,Throwable]");
|
||||
EchoCase.add(TESTCASES, BasicErrorThrowableSocket.class).expect("Error[Throwable]");
|
||||
EchoCase.add(TESTCASES, BasicErrorThrowableSessionSocket.class).expect("Error[Throwable,Session]");
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
File testdir = MavenTestingUtils.getTargetTestingDir(EchoTest.class.getName());
|
||||
Path testdir = MavenTestingUtils.getTargetTestingPath(EchoTest.class.getName());
|
||||
server = new WSServer(testdir,"app");
|
||||
server.copyWebInf("empty-web.xml");
|
||||
|
||||
|
@ -277,6 +320,14 @@ public class EchoTest
|
|||
PartialBinary pb = (PartialBinary)msg;
|
||||
socket.sendPartialBinary(pb.part,pb.fin);
|
||||
}
|
||||
else if (msg instanceof ByteBuffer)
|
||||
{
|
||||
socket.sendBinary((ByteBuffer) msg);
|
||||
}
|
||||
else if (msg instanceof String)
|
||||
{
|
||||
socket.sendText((String) msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
socket.sendObject(msg);
|
||||
|
@ -288,10 +339,7 @@ public class EchoTest
|
|||
EventQueue<String> received = socket.eventQueue;
|
||||
|
||||
// Validate Responses
|
||||
for (String expected : testcase.expectedStrings)
|
||||
{
|
||||
Assert.assertThat("Received Echo Responses",received,contains(expected));
|
||||
}
|
||||
assertThat("Received Events", received, ordered(testcase.expectedStrings));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -31,11 +31,10 @@ import java.util.concurrent.TimeoutException;
|
|||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.log.StacklessLogging;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.JsrEvents;
|
||||
import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.idletimeout.IdleTimeoutContextListener;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.idletimeout.OnOpenIdleTimeoutEndpoint;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.idletimeout.OnOpenIdleTimeoutSocket;
|
||||
|
@ -52,7 +51,7 @@ public class IdleTimeoutTest
|
|||
@BeforeClass
|
||||
public static void setupServer() throws Exception
|
||||
{
|
||||
server = new WSServer(MavenTestingUtils.getTargetTestingDir(IdleTimeoutTest.class.getName()),"app");
|
||||
server = new WSServer(MavenTestingUtils.getTargetTestingPath(IdleTimeoutTest.class.getName()),"app");
|
||||
server.copyWebInf("idle-timeout-config-web.xml");
|
||||
// the endpoint (extends javax.websocket.Endpoint)
|
||||
server.copyClass(OnOpenIdleTimeoutEndpoint.class);
|
||||
|
@ -117,13 +116,10 @@ public class IdleTimeoutTest
|
|||
|
||||
@Test
|
||||
public void testAnnotated() throws Exception
|
||||
{
|
||||
try(StacklessLogging ignored = new StacklessLogging(JsrEvents.class))
|
||||
{
|
||||
URI uri = server.getServerBaseURI();
|
||||
assertConnectionTimeout(uri.resolve("idle-onopen-socket"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndpoint() throws Exception
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 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 static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriver;
|
||||
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.common.test.DummyConnection;
|
||||
import org.eclipse.jetty.websocket.jsr356.ClientContainer;
|
||||
import org.eclipse.jetty.websocket.jsr356.ConfiguredEndpoint;
|
||||
import org.eclipse.jetty.websocket.jsr356.JsrSession;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.partial.PartialTrackingSocket;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
public class OnPartialTest
|
||||
{
|
||||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
public EventDriver toEventDriver(Object websocket) throws Throwable
|
||||
{
|
||||
WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
|
||||
policy.setInputBufferSize(1024);
|
||||
policy.setMaxBinaryMessageBufferSize(1024);
|
||||
policy.setMaxTextMessageBufferSize(1024);
|
||||
|
||||
|
||||
// Create EventDriver
|
||||
EventDriverImpl driverImpl = new JsrServerEndpointImpl();
|
||||
Class<?> endpoint = websocket.getClass();
|
||||
ServerEndpoint anno = endpoint.getAnnotation(ServerEndpoint.class);
|
||||
Assert.assertThat("Endpoint: " + endpoint + " should be annotated with @ServerEndpoint",anno,notNullValue());
|
||||
|
||||
WebSocketContainerScope containerScope = new SimpleContainerScope(policy);
|
||||
// Event Driver Factory
|
||||
EventDriverFactory factory = new EventDriverFactory(containerScope);
|
||||
factory.addImplementation(new JsrServerEndpointImpl());
|
||||
|
||||
ServerEndpointConfig config = new BasicServerEndpointConfig(containerScope,endpoint,"/");
|
||||
AnnotatedServerEndpointMetadata metadata = new AnnotatedServerEndpointMetadata(containerScope,endpoint,config);
|
||||
AnnotatedEndpointScanner<ServerEndpoint, ServerEndpointConfig> scanner = new AnnotatedEndpointScanner<>(metadata);
|
||||
scanner.scan();
|
||||
ConfiguredEndpoint ei = new ConfiguredEndpoint(websocket,config,metadata);
|
||||
EventDriver driver = driverImpl.create(ei,policy);
|
||||
Assert.assertThat("EventDriver",driver,notNullValue());
|
||||
|
||||
// Create Local JsrSession
|
||||
String id = testname.getMethodName();
|
||||
URI requestURI = URI.create("ws://localhost/" + id);
|
||||
DummyConnection connection = new DummyConnection();
|
||||
ClientContainer container = new ClientContainer();
|
||||
container.start();
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
JsrSession session = new JsrSession(container,id,requestURI,driver,connection);
|
||||
session.start();
|
||||
session.open();
|
||||
return driver;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnTextPartial() throws Throwable
|
||||
{
|
||||
List<WebSocketFrame> frames = new ArrayList<>();
|
||||
frames.add(new TextFrame().setPayload("Saved").setFin(false));
|
||||
frames.add(new ContinuationFrame().setPayload(" by ").setFin(false));
|
||||
frames.add(new ContinuationFrame().setPayload("zero").setFin(true));
|
||||
|
||||
PartialTrackingSocket socket = new PartialTrackingSocket();
|
||||
|
||||
EventDriver driver = toEventDriver(socket);
|
||||
driver.onConnect();
|
||||
|
||||
for (WebSocketFrame frame : frames)
|
||||
{
|
||||
driver.incomingFrame(frame);
|
||||
}
|
||||
|
||||
Assert.assertThat("Captured Event Queue size",socket.eventQueue.size(),is(3));
|
||||
Assert.assertThat("Event[0]",socket.eventQueue.poll(),is("onPartial(\"Saved\",false)"));
|
||||
Assert.assertThat("Event[1]",socket.eventQueue.poll(),is("onPartial(\" by \",false)"));
|
||||
Assert.assertThat("Event[2]",socket.eventQueue.poll(),is("onPartial(\"zero\",true)"));
|
||||
}
|
||||
}
|
|
@ -21,8 +21,8 @@ package org.eclipse.jetty.websocket.jsr356.server;
|
|||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.websocket.ContainerProvider;
|
||||
|
@ -48,7 +48,7 @@ public class PingPongTest
|
|||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
File testdir = MavenTestingUtils.getTargetTestingDir(PingPongTest.class.getName());
|
||||
Path testdir = MavenTestingUtils.getTargetTestingPath(PingPongTest.class.getName());
|
||||
server = new WSServer(testdir,"app");
|
||||
server.copyWebInf("pong-config-web.xml");
|
||||
|
||||
|
|
|
@ -1,206 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 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 static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.PongMessage;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
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;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicCloseReasonSessionSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicCloseReasonSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicCloseSessionReasonSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicCloseSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorSessionSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorSessionThrowableSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorThrowableSessionSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorThrowableSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicOpenSessionSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicOpenSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicPongMessageSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicTextMessageStringSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.StatelessTextMessageStringSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.beans.DateTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.BooleanObjectTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.BooleanTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ByteObjectTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ByteTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.CharTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.CharacterObjectTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.DoubleObjectTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.DoubleTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.FloatObjectTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.FloatTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.IntTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.IntegerObjectTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ShortObjectTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ShortTextSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderParamSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.StringReturnReaderParamSocket;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
/**
|
||||
* Test {@link AnnotatedEndpointScanner} against various simple, 1 method {@link ServerEndpoint} annotated classes with valid signatures.
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class ServerAnnotatedEndpointScanner_GoodSignaturesTest
|
||||
{
|
||||
public static class Case
|
||||
{
|
||||
public static void add(List<Case[]> data, Class<?> pojo, Field metadataField, Class<?>... expectedParams)
|
||||
{
|
||||
data.add(new Case[]
|
||||
{ new Case(pojo,metadataField,expectedParams) });
|
||||
}
|
||||
|
||||
// The websocket pojo to test against
|
||||
Class<?> pojo;
|
||||
// The JsrAnnotatedMetadata field that should be populated
|
||||
Field metadataField;
|
||||
// The expected parameters for the Callable found by the scanner
|
||||
Class<?> expectedParameters[];
|
||||
|
||||
public Case(Class<?> pojo, Field metadataField, Class<?>... expectedParams)
|
||||
{
|
||||
this.pojo = pojo;
|
||||
this.metadataField = metadataField;
|
||||
this.expectedParameters = expectedParams;
|
||||
}
|
||||
}
|
||||
|
||||
@Parameters
|
||||
public static Collection<Case[]> data() throws Exception
|
||||
{
|
||||
List<Case[]> data = new ArrayList<>();
|
||||
Field fOpen = findFieldRef(AnnotatedServerEndpointMetadata.class,"onOpen");
|
||||
Field fClose = findFieldRef(AnnotatedServerEndpointMetadata.class,"onClose");
|
||||
Field fError = findFieldRef(AnnotatedServerEndpointMetadata.class,"onError");
|
||||
Field fText = findFieldRef(AnnotatedServerEndpointMetadata.class,"onText");
|
||||
Field fTextStream = findFieldRef(AnnotatedServerEndpointMetadata.class,"onTextStream");
|
||||
Field fBinary = findFieldRef(AnnotatedServerEndpointMetadata.class,"onBinary");
|
||||
@SuppressWarnings("unused")
|
||||
Field fBinaryStream = findFieldRef(AnnotatedServerEndpointMetadata.class,"onBinaryStream");
|
||||
Field fPong = findFieldRef(AnnotatedServerEndpointMetadata.class,"onPong");
|
||||
|
||||
// @formatter:off
|
||||
// -- Open Events
|
||||
Case.add(data, BasicOpenSocket.class, fOpen);
|
||||
Case.add(data, BasicOpenSessionSocket.class, fOpen, Session.class);
|
||||
// -- Close Events
|
||||
Case.add(data, BasicCloseSocket.class, fClose);
|
||||
Case.add(data, BasicCloseReasonSocket.class, fClose, CloseReason.class);
|
||||
Case.add(data, BasicCloseReasonSessionSocket.class, fClose, CloseReason.class, Session.class);
|
||||
Case.add(data, BasicCloseSessionReasonSocket.class, fClose, Session.class, CloseReason.class);
|
||||
// -- Error Events
|
||||
Case.add(data, BasicErrorSocket.class, fError);
|
||||
Case.add(data, BasicErrorSessionSocket.class, fError, Session.class);
|
||||
Case.add(data, BasicErrorSessionThrowableSocket.class, fError, Session.class, Throwable.class);
|
||||
Case.add(data, BasicErrorThrowableSocket.class, fError, Throwable.class);
|
||||
Case.add(data, BasicErrorThrowableSessionSocket.class, fError, Throwable.class, Session.class);
|
||||
// -- Text Events
|
||||
Case.add(data, BasicTextMessageStringSocket.class, fText, String.class);
|
||||
Case.add(data, StatelessTextMessageStringSocket.class, fText, Session.class, String.class);
|
||||
// -- Primitives
|
||||
Case.add(data, BooleanTextSocket.class, fText, Boolean.TYPE);
|
||||
Case.add(data, BooleanObjectTextSocket.class, fText, Boolean.class);
|
||||
Case.add(data, ByteTextSocket.class, fText, Byte.TYPE);
|
||||
Case.add(data, ByteObjectTextSocket.class, fText, Byte.class);
|
||||
Case.add(data, CharTextSocket.class, fText, Character.TYPE);
|
||||
Case.add(data, CharacterObjectTextSocket.class, fText, Character.class);
|
||||
Case.add(data, DoubleTextSocket.class, fText, Double.TYPE);
|
||||
Case.add(data, DoubleObjectTextSocket.class, fText, Double.class);
|
||||
Case.add(data, FloatTextSocket.class, fText, Float.TYPE);
|
||||
Case.add(data, FloatObjectTextSocket.class, fText, Float.class);
|
||||
Case.add(data, IntTextSocket.class, fText, Integer.TYPE);
|
||||
Case.add(data, IntegerObjectTextSocket.class, fText, Integer.class);
|
||||
Case.add(data, ShortTextSocket.class, fText, Short.TYPE);
|
||||
Case.add(data, ShortObjectTextSocket.class, fText, Short.class);
|
||||
// -- Beans
|
||||
Case.add(data, DateTextSocket.class, fText, Date.class);
|
||||
// -- Reader Events
|
||||
Case.add(data, ReaderParamSocket.class, fTextStream, Reader.class, String.class);
|
||||
Case.add(data, StringReturnReaderParamSocket.class, fTextStream, Reader.class, String.class);
|
||||
// -- Binary Events
|
||||
Case.add(data, BasicBinaryMessageByteBufferSocket.class, fBinary, ByteBuffer.class);
|
||||
// -- Pong Events
|
||||
Case.add(data, BasicPongMessageSocket.class, fPong, PongMessage.class);
|
||||
// @formatter:on
|
||||
|
||||
// TODO: validate return types
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private static Field findFieldRef(Class<?> clazz, String fldName) throws Exception
|
||||
{
|
||||
return clazz.getField(fldName);
|
||||
}
|
||||
|
||||
private Case testcase;
|
||||
|
||||
public ServerAnnotatedEndpointScanner_GoodSignaturesTest(Case testcase)
|
||||
{
|
||||
this.testcase = testcase;
|
||||
System.err.printf("Testing signature of %s%n",testcase.pojo.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScan_Basic() throws Exception
|
||||
{
|
||||
WebSocketContainerScope container = new SimpleContainerScope(WebSocketPolicy.newClientPolicy());
|
||||
AnnotatedServerEndpointMetadata metadata = new AnnotatedServerEndpointMetadata(container,testcase.pojo,null);
|
||||
AnnotatedEndpointScanner<ServerEndpoint, ServerEndpointConfig> scanner = new AnnotatedEndpointScanner<>(metadata);
|
||||
scanner.scan();
|
||||
|
||||
Assert.assertThat("Metadata",metadata,notNullValue());
|
||||
|
||||
JsrCallable method = (JsrCallable)testcase.metadataField.get(metadata);
|
||||
Assert.assertThat(testcase.metadataField.toString(),method,notNullValue());
|
||||
int len = testcase.expectedParameters.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Class<?> expectedParam = testcase.expectedParameters[i];
|
||||
Class<?> actualParam = method.getParamTypes()[i];
|
||||
|
||||
Assert.assertTrue("Parameter[" + i + "] - expected:[" + expectedParam + "], actual:[" + actualParam + "]",actualParam.equals(expectedParam));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 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 static org.hamcrest.Matchers.containsString;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.websocket.DeploymentException;
|
||||
import javax.websocket.OnClose;
|
||||
import javax.websocket.OnError;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
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.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;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidErrorExceptionSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidErrorIntSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidOpenCloseReasonSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidOpenIntSocket;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.samples.InvalidOpenSessionIntSocket;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
/**
|
||||
* Test {@link AnnotatedEndpointScanner} against various simple, 1 method {@link ServerEndpoint} annotated classes with invalid signatures.
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class ServerAnnotatedEndpointScanner_InvalidSignaturesTest
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ServerAnnotatedEndpointScanner_InvalidSignaturesTest.class);
|
||||
|
||||
@Parameters
|
||||
public static Collection<Class<?>[]> data()
|
||||
{
|
||||
List<Class<?>[]> data = new ArrayList<>();
|
||||
|
||||
// @formatter:off
|
||||
data.add(new Class<?>[]{ InvalidCloseIntSocket.class, OnClose.class });
|
||||
data.add(new Class<?>[]{ InvalidErrorErrorSocket.class, OnError.class });
|
||||
data.add(new Class<?>[]{ InvalidErrorExceptionSocket.class, OnError.class });
|
||||
data.add(new Class<?>[]{ InvalidErrorIntSocket.class, OnError.class });
|
||||
data.add(new Class<?>[]{ InvalidOpenCloseReasonSocket.class, OnOpen.class });
|
||||
data.add(new Class<?>[]{ InvalidOpenIntSocket.class, OnOpen.class });
|
||||
data.add(new Class<?>[]{ InvalidOpenSessionIntSocket.class, OnOpen.class });
|
||||
// @formatter:on
|
||||
|
||||
// TODO: invalid return types
|
||||
// TODO: static methods
|
||||
// TODO: private or protected methods
|
||||
// TODO: abstract methods
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// The pojo to test
|
||||
private Class<?> pojo;
|
||||
// The annotation class expected to be mentioned in the error message
|
||||
private Class<? extends Annotation> expectedAnnoClass;
|
||||
|
||||
public ServerAnnotatedEndpointScanner_InvalidSignaturesTest(Class<?> pojo, Class<? extends Annotation> expectedAnnotation)
|
||||
{
|
||||
this.pojo = pojo;
|
||||
this.expectedAnnoClass = expectedAnnotation;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScan_InvalidSignature() throws DeploymentException
|
||||
{
|
||||
WebSocketContainerScope container = new SimpleContainerScope(WebSocketPolicy.newClientPolicy());
|
||||
AnnotatedServerEndpointMetadata metadata = new AnnotatedServerEndpointMetadata(container,pojo,null);
|
||||
AnnotatedEndpointScanner<ServerEndpoint,ServerEndpointConfig> scanner = new AnnotatedEndpointScanner<>(metadata);
|
||||
|
||||
try
|
||||
{
|
||||
scanner.scan();
|
||||
Assert.fail("Expected " + InvalidSignatureException.class + " with message that references " + expectedAnnoClass + " annotation");
|
||||
}
|
||||
catch (InvalidSignatureException e)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{}:{}",e.getClass(),e.getMessage());
|
||||
Assert.assertThat("Message",e.getMessage(),containsString(expectedAnnoClass.getSimpleName()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -114,7 +114,7 @@ public class SessionTest
|
|||
@Before
|
||||
public void startServer() throws Exception
|
||||
{
|
||||
server = new WSServer(MavenTestingUtils.getTargetTestingDir(SessionTest.class.getSimpleName() + "-" + ID.incrementAndGet()),"app");
|
||||
server = new WSServer(MavenTestingUtils.getTargetTestingPath(SessionTest.class.getSimpleName() + "-" + ID.incrementAndGet()),"app");
|
||||
server.copyWebInf("empty-web.xml");
|
||||
server.copyClass(SessionInfoSocket.class);
|
||||
server.copyClass(SessionAltConfig.class);
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.io.IOException;
|
|||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationConfiguration;
|
||||
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
|
||||
|
@ -36,11 +37,10 @@ import org.eclipse.jetty.server.handler.HandlerCollection;
|
|||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.toolchain.test.IO;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.OS;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.util.resource.PathResource;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.FragmentConfiguration;
|
||||
import org.eclipse.jetty.webapp.MetaInfConfiguration;
|
||||
|
@ -57,22 +57,22 @@ import org.junit.Assert;
|
|||
public class WSServer
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WSServer.class);
|
||||
private final File contextDir;
|
||||
private final Path contextDir;
|
||||
private final String contextPath;
|
||||
private Server server;
|
||||
private URI serverUri;
|
||||
private ContextHandlerCollection contexts;
|
||||
private File webinf;
|
||||
private File classesDir;
|
||||
private Path webinf;
|
||||
private Path classesDir;
|
||||
|
||||
public WSServer(TestingDir testdir, String contextName)
|
||||
{
|
||||
this(testdir.getPath().toFile(),contextName);
|
||||
this(testdir.getPath(),contextName);
|
||||
}
|
||||
|
||||
public WSServer(File testdir, String contextName)
|
||||
public WSServer(Path testdir, String contextName)
|
||||
{
|
||||
this.contextDir = new File(testdir,contextName);
|
||||
this.contextDir = testdir.resolve(contextName);
|
||||
this.contextPath = "/" + contextName;
|
||||
FS.ensureEmpty(contextDir);
|
||||
}
|
||||
|
@ -83,10 +83,10 @@ public class WSServer
|
|||
String endpointPath = clazz.getName().replace('.','/') + ".class";
|
||||
URL classUrl = cl.getResource(endpointPath);
|
||||
Assert.assertThat("Class URL for: " + clazz,classUrl,notNullValue());
|
||||
File destFile = new File(classesDir,OS.separators(endpointPath));
|
||||
FS.ensureDirExists(destFile.getParentFile());
|
||||
Path destFile = classesDir.resolve(endpointPath);
|
||||
FS.ensureDirExists(destFile.getParent());
|
||||
File srcFile = new File(classUrl.toURI());
|
||||
IO.copy(srcFile,destFile);
|
||||
IO.copy(srcFile,destFile.toFile());
|
||||
}
|
||||
|
||||
public void copyEndpoint(Class<?> endpointClass) throws Exception
|
||||
|
@ -96,20 +96,20 @@ public class WSServer
|
|||
|
||||
public void copyWebInf(String testResourceName) throws IOException
|
||||
{
|
||||
webinf = new File(contextDir,"WEB-INF");
|
||||
webinf = contextDir.resolve("WEB-INF");
|
||||
FS.ensureDirExists(webinf);
|
||||
classesDir = new File(webinf,"classes");
|
||||
classesDir = webinf.resolve("classes");
|
||||
FS.ensureDirExists(classesDir);
|
||||
File webxml = new File(webinf,"web.xml");
|
||||
Path webxml = webinf.resolve("web.xml");
|
||||
File testWebXml = MavenTestingUtils.getTestResourceFile(testResourceName);
|
||||
IO.copy(testWebXml,webxml);
|
||||
IO.copy(testWebXml,webxml.toFile());
|
||||
}
|
||||
|
||||
public WebAppContext createWebAppContext() throws MalformedURLException, IOException
|
||||
{
|
||||
WebAppContext context = new WebAppContext();
|
||||
context.setContextPath(this.contextPath);
|
||||
context.setBaseResource(Resource.newResource(this.contextDir));
|
||||
context.setBaseResource(new PathResource(this.contextDir));
|
||||
context.setAttribute("org.eclipse.jetty.websocket.jsr356",Boolean.TRUE);
|
||||
|
||||
// @formatter:off
|
||||
|
@ -157,7 +157,7 @@ public class WSServer
|
|||
return server;
|
||||
}
|
||||
|
||||
public File getWebAppDir()
|
||||
public Path getWebAppDir()
|
||||
{
|
||||
return this.contextDir;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue