Issue #207 - Support javax.websocket version 1.1
+ More testcase improvements
This commit is contained in:
parent
43ef087efd
commit
1a8e79c9bb
|
@ -22,6 +22,7 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Predicate;
|
||||
|
@ -64,7 +65,7 @@ public class PathMappings<E> implements Iterable<MappedResource<E>>, Dumpable
|
|||
out.append("PathMappings[size=").append(Integer.toString(_mappings.size())).append("]\n");
|
||||
ContainerLifeCycle.dump(out, indent, _mappings);
|
||||
}
|
||||
|
||||
|
||||
@ManagedAttribute(value = "mappings", readonly = true)
|
||||
public List<MappedResource<E>> getMappings()
|
||||
{
|
||||
|
@ -206,6 +207,18 @@ public class PathMappings<E> implements Iterable<MappedResource<E>>, Dumpable
|
|||
return pathSpecString.charAt(0) == '^' ? new RegexPathSpec(pathSpecString):new ServletPathSpec(pathSpecString);
|
||||
}
|
||||
|
||||
public E get(PathSpec spec)
|
||||
{
|
||||
Optional<E> optionalResource = _mappings.stream()
|
||||
.filter(mappedResource -> mappedResource.getPathSpec().equals(spec))
|
||||
.map(mappedResource -> mappedResource.getResource())
|
||||
.findFirst();
|
||||
if(!optionalResource.isPresent())
|
||||
return null;
|
||||
|
||||
return optionalResource.get();
|
||||
}
|
||||
|
||||
public boolean put(String pathSpecString, E resource)
|
||||
{
|
||||
return put(asPathSpec(pathSpecString),resource);
|
||||
|
|
|
@ -207,6 +207,27 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
|
|||
return userProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AnnotatedServerEndpointConfig that = (AnnotatedServerEndpointConfig) o;
|
||||
|
||||
if (endpointClass != null ? !endpointClass.equals(that.endpointClass) : that.endpointClass != null)
|
||||
return false;
|
||||
return path != null ? path.equals(that.path) : that.path == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = endpointClass != null ? endpointClass.hashCode() : 0;
|
||||
result = 31 * result + (path != null ? path.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
|
|
@ -172,10 +172,28 @@ public class JsrCreator implements WebSocketCreator
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
JsrCreator that = (JsrCreator) o;
|
||||
|
||||
return baseConfig != null ? baseConfig.equals(that.baseConfig) : that.baseConfig == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = (baseConfig != null ? baseConfig.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s[config=%s]",this.getClass().getName(),baseConfig);
|
||||
return String.format("JsrCreator[%s%s]", (baseConfig instanceof AnnotatedServerEndpointConfig ? "@" : ""), baseConfig.getEndpointClass().getName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,33 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Jetty Native approach.
|
||||
* <p>
|
||||
* Note: this will add the Upgrade filter to the existing list, with no regard for order. It will just be tacked onto the end of the list.
|
||||
*
|
||||
* @param context the servlet context handler
|
||||
* @return the created websocket server container
|
||||
* @throws ServletException if unable to create the websocket server container
|
||||
*/
|
||||
@SuppressWarnings("Duplicates")
|
||||
public static ServerContainer configureContext(ServletContextHandler context) throws ServletException
|
||||
{
|
||||
// Create Filter
|
||||
WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context);
|
||||
|
||||
// Create the Jetty ServerContainer implementation
|
||||
ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),context.getServer().getThreadPool());
|
||||
context.addBean(jettyContainer, true);
|
||||
|
||||
// Store a reference to the ServerContainer per javax.websocket spec 1.0 final section 6.4 Programmatic Server Deployment
|
||||
context.setAttribute(javax.websocket.server.ServerContainer.class.getName(),jettyContainer);
|
||||
|
||||
return jettyContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a ServletContext for {@code init-param} or {@code attribute} at {@code keyName} for
|
||||
* true or false setting that determines if the specified feature is enabled (or not).
|
||||
|
@ -91,7 +118,23 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
|
|||
* @param defValue the default value, if the value is not specified in the context
|
||||
* @return the value for the feature key
|
||||
*/
|
||||
public static boolean isEnabledViaContext(ServletContext context, String keyName, boolean defValue)
|
||||
@SuppressWarnings("Duplicates")
|
||||
public static ServerContainer configureContext(ServletContext context, ServletContextHandler jettyContext) throws ServletException
|
||||
{
|
||||
// Create Filter
|
||||
WebSocketUpgradeFilter filter = WebSocketUpgradeFilter.configureContext(context);
|
||||
|
||||
// Create the Jetty ServerContainer implementation
|
||||
ServerContainer jettyContainer = new ServerContainer(filter,filter.getFactory(),jettyContext.getServer().getThreadPool());
|
||||
jettyContext.addBean(jettyContainer, true);
|
||||
|
||||
// Store a reference to the ServerContainer per javax.websocket spec 1.0 final section 6.4 Programmatic Server Deployment
|
||||
context.setAttribute(javax.websocket.server.ServerContainer.class.getName(),jettyContainer);
|
||||
|
||||
return jettyContainer;
|
||||
}
|
||||
|
||||
private boolean isEnabled(Set<Class<?>> c, ServletContext context)
|
||||
{
|
||||
// Try context parameters first
|
||||
String cp = context.getInitParameter(keyName);
|
||||
|
@ -203,19 +246,19 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
|
|||
try(ThreadClassLoaderScope scope = new ThreadClassLoaderScope(context.getClassLoader()))
|
||||
{
|
||||
// Create the Jetty ServerContainer implementation
|
||||
ServerContainer jettyContainer = configureContext(jettyContext);
|
||||
|
||||
context.addListener(new ContextDestroyListener()); // make sure context is cleaned up when the context stops
|
||||
|
||||
if (c.isEmpty())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("No JSR-356 annotations or interfaces discovered");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ServerContainer jettyContainer = configureContext(context,jettyContext);
|
||||
|
||||
context.addListener(new ContextDestroyListener()); //make sure context is cleaned up when the context stops
|
||||
|
||||
// // Establish the DecoratedObjectFactory thread local
|
||||
// // for various ServiceLoader initiated components to use.
|
||||
// DecoratedObjectFactory instantiation = (DecoratedObjectFactory)context.getAttribute(DecoratedObjectFactory.ATTR);
|
||||
// if (instantiation == null)
|
||||
// {
|
||||
// LOG.info("Using WebSocket local DecoratedObjectFactory - none found in ServletContext");
|
||||
// instantiation = new DecoratedObjectFactory();
|
||||
// }
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("Found {} classes",c.size());
|
||||
|
|
|
@ -1 +1 @@
|
|||
org.eclipse.jetty.websocket.common.reflect.NameArgIdentifier
|
||||
org.eclipse.jetty.websocket.jsr356.server.PathParamArgIdentifier
|
||||
|
|
|
@ -295,7 +295,7 @@ public class EchoTest
|
|||
System.err.println(testcase);
|
||||
}
|
||||
|
||||
@Test(timeout=2000)
|
||||
@Test(timeout=10000)
|
||||
public void testEcho() throws Exception
|
||||
{
|
||||
int messageCount = testcase.getMessageCount();
|
||||
|
@ -306,7 +306,7 @@ public class EchoTest
|
|||
{
|
||||
// Connect
|
||||
client.connectToServer(socket,toUri);
|
||||
socket.waitForConnected(2,TimeUnit.SECONDS);
|
||||
socket.waitForConnected(10,TimeUnit.SECONDS);
|
||||
|
||||
// Send Messages
|
||||
for (Object msg : testcase.messages)
|
||||
|
|
|
@ -25,7 +25,7 @@ import javax.websocket.server.ServerEndpoint;
|
|||
|
||||
import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket;
|
||||
|
||||
@ServerEndpoint(value="/basic")
|
||||
@ServerEndpoint(value="/echo/close/reason/session")
|
||||
public class BasicCloseReasonSessionSocket extends TrackingSocket
|
||||
{
|
||||
@OnClose
|
||||
|
|
|
@ -24,7 +24,7 @@ import javax.websocket.server.ServerEndpoint;
|
|||
|
||||
import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket;
|
||||
|
||||
@ServerEndpoint(value="/basic")
|
||||
@ServerEndpoint(value="/echo/close/reason")
|
||||
public class BasicCloseReasonSocket extends TrackingSocket
|
||||
{
|
||||
@OnClose
|
||||
|
|
|
@ -25,7 +25,7 @@ import javax.websocket.server.ServerEndpoint;
|
|||
|
||||
import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket;
|
||||
|
||||
@ServerEndpoint(value="/basic")
|
||||
@ServerEndpoint(value="/echo/close/session/reason")
|
||||
public class BasicCloseSessionReasonSocket extends TrackingSocket
|
||||
{
|
||||
@OnClose
|
||||
|
|
|
@ -23,7 +23,7 @@ import javax.websocket.server.ServerEndpoint;
|
|||
|
||||
import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket;
|
||||
|
||||
@ServerEndpoint(value = "/basic")
|
||||
@ServerEndpoint(value = "/echo/close")
|
||||
public class BasicCloseSocket extends TrackingSocket
|
||||
{
|
||||
@OnClose
|
||||
|
|
|
@ -24,7 +24,7 @@ import javax.websocket.server.ServerEndpoint;
|
|||
|
||||
import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket;
|
||||
|
||||
@ServerEndpoint(value="/basic")
|
||||
@ServerEndpoint(value="/echo/error/session")
|
||||
public class BasicErrorSessionSocket extends TrackingSocket
|
||||
{
|
||||
@OnError
|
||||
|
|
|
@ -24,7 +24,7 @@ import javax.websocket.server.ServerEndpoint;
|
|||
|
||||
import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket;
|
||||
|
||||
@ServerEndpoint(value="/basic")
|
||||
@ServerEndpoint(value="/echo/error/session/throwable")
|
||||
public class BasicErrorSessionThrowableSocket extends TrackingSocket
|
||||
{
|
||||
@OnError
|
||||
|
|
|
@ -23,7 +23,7 @@ import javax.websocket.server.ServerEndpoint;
|
|||
|
||||
import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket;
|
||||
|
||||
@ServerEndpoint(value="/basic")
|
||||
@ServerEndpoint(value="/echo/error")
|
||||
public class BasicErrorSocket extends TrackingSocket
|
||||
{
|
||||
@OnError
|
||||
|
|
|
@ -24,7 +24,7 @@ import javax.websocket.server.ServerEndpoint;
|
|||
|
||||
import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket;
|
||||
|
||||
@ServerEndpoint(value="/basic")
|
||||
@ServerEndpoint(value="/echo/error/throwable/session")
|
||||
public class BasicErrorThrowableSessionSocket extends TrackingSocket
|
||||
{
|
||||
@OnError
|
||||
|
|
|
@ -23,7 +23,7 @@ import javax.websocket.server.ServerEndpoint;
|
|||
|
||||
import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket;
|
||||
|
||||
@ServerEndpoint(value="/basic")
|
||||
@ServerEndpoint(value="/echo/error/throwable")
|
||||
public class BasicErrorThrowableSocket extends TrackingSocket
|
||||
{
|
||||
@OnError
|
||||
|
|
|
@ -24,7 +24,7 @@ import javax.websocket.server.ServerEndpoint;
|
|||
|
||||
import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket;
|
||||
|
||||
@ServerEndpoint(value="/basic")
|
||||
@ServerEndpoint(value="/echo/open/session")
|
||||
public class BasicOpenSessionSocket extends TrackingSocket
|
||||
{
|
||||
@OnOpen
|
||||
|
|
|
@ -23,7 +23,7 @@ import javax.websocket.server.ServerEndpoint;
|
|||
|
||||
import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket;
|
||||
|
||||
@ServerEndpoint(value="/basic")
|
||||
@ServerEndpoint(value="/echo/open")
|
||||
public class BasicOpenSocket extends TrackingSocket
|
||||
{
|
||||
@OnOpen
|
||||
|
|
|
@ -24,7 +24,7 @@ import javax.websocket.server.ServerEndpoint;
|
|||
|
||||
import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket;
|
||||
|
||||
@ServerEndpoint(value="/basic")
|
||||
@ServerEndpoint(value="/echo/pong")
|
||||
public class BasicPongMessageSocket extends TrackingSocket
|
||||
{
|
||||
@OnMessage
|
||||
|
|
|
@ -664,8 +664,10 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
{
|
||||
assertIsStarted();
|
||||
|
||||
// Always set session in endpoint functions
|
||||
this.session = session;
|
||||
|
||||
// Call (optional) on open method
|
||||
if (onOpenFunction != null)
|
||||
onOpenFunction.apply(this.session);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
|||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
|
||||
|
@ -132,7 +134,25 @@ public class WebSocketUpgradeFilter implements Filter, MappedWebSocketCreator, D
|
|||
@Override
|
||||
public void addMapping(PathSpec spec, WebSocketCreator creator)
|
||||
{
|
||||
configuration.addMapping(spec, creator);
|
||||
WebSocketCreator existingCreator = pathmap.get(spec);
|
||||
if (existingCreator != null)
|
||||
{
|
||||
if(existingCreator.equals(creator))
|
||||
{
|
||||
// Entry already exists, don't add it again.
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder err = new StringBuilder();
|
||||
err.append("Duplicate path mapping for \"");
|
||||
err.append(spec.getDeclaration());
|
||||
err.append("\" both ");
|
||||
err.append(existingCreator);
|
||||
err.append(" and ");
|
||||
err.append(creator);
|
||||
throw new InvalidWebSocketException(err.toString());
|
||||
}
|
||||
pathmap.put(spec,creator);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue