Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoakim Erdfelt2013-04-23 18:06:01 +0000
committerJoakim Erdfelt2013-04-23 18:06:01 +0000
commita4644dc78008dab958895ba87fe2f6a99aea909b (patch)
tree5cbfe85fd6757904db5f887ea4ca3cbc5959a1d9 /jetty-websocket/javax-websocket-server-impl
parent346034b44fe42af7c592c138347c0dabbb124f2a (diff)
downloadorg.eclipse.jetty.project-a4644dc78008dab958895ba87fe2f6a99aea909b.tar.gz
org.eclipse.jetty.project-a4644dc78008dab958895ba87fe2f6a99aea909b.tar.xz
org.eclipse.jetty.project-a4644dc78008dab958895ba87fe2f6a99aea909b.zip
JSR-356 working out server endpoint creation
Diffstat (limited to 'jetty-websocket/javax-websocket-server-impl')
-rw-r--r--jetty-websocket/javax-websocket-server-impl/pom.xml7
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JettyServerEndpointConfigurator.java60
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java93
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrHandshakeRequest.java83
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrHandshakeResponse.java (renamed from jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/WebSocketHandler.java)21
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerMetadata.java5
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java55
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappings.java147
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathSpec.java162
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathSpecGroup.java82
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/RegexPathSpec.java166
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/ServletPathSpec.java291
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpec.java6
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/resources/META-INF/services/javax.websocket.server.ServerEndpointConfig$Configurator1
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicAnnotatedTest.java5
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicEndpointTest.java90
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/JettyServerEndpointConfiguratorTest.java51
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/WSServer.java34
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappingsBenchmarkTest.java224
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappingsTest.java47
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/RegexPathSpecTest.java113
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/ServletPathSpecTest.java186
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpecTest.java21
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpoint.java46
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpointConfigContextListener.java56
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpointContextListener.java55
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoSocket.java (renamed from jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicEchoSocket.java)5
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoSocketConfigContextListener.java56
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoSocketContextListener.java51
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/resources/basic-echo-endpoint-config-web.xml12
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/resources/jetty-logging.properties7
31 files changed, 792 insertions, 1446 deletions
diff --git a/jetty-websocket/javax-websocket-server-impl/pom.xml b/jetty-websocket/javax-websocket-server-impl/pom.xml
index cfd8c918a5..bf4dabe388 100644
--- a/jetty-websocket/javax-websocket-server-impl/pom.xml
+++ b/jetty-websocket/javax-websocket-server-impl/pom.xml
@@ -27,9 +27,14 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.eclipse.jetty.websocket</groupId>
+ <artifactId>websocket-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.eclipse.jetty.drafts</groupId>
<artifactId>javax.websocket-api</artifactId>
- <version>1.0.0.PFD-SNAPSHOT</version>
+ <version>1.0.0.DRAFT-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JettyServerEndpointConfigurator.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JettyServerEndpointConfigurator.java
new file mode 100644
index 0000000000..65de4b5960
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JettyServerEndpointConfigurator.java
@@ -0,0 +1,60 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.websocket.jsr356.server;
+
+import java.util.List;
+
+import javax.websocket.Extension;
+import javax.websocket.HandshakeResponse;
+import javax.websocket.server.HandshakeRequest;
+import javax.websocket.server.ServerEndpointConfig;
+import javax.websocket.server.ServerEndpointConfig.Configurator;
+
+public class JettyServerEndpointConfigurator extends Configurator
+{
+ @Override
+ public boolean checkOrigin(String originHeaderValue)
+ {
+ return super.checkOrigin(originHeaderValue);
+ }
+
+ @Override
+ public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException
+ {
+ return super.getEndpointInstance(endpointClass);
+ }
+
+ @Override
+ public List<Extension> getNegotiatedExtensions(List<Extension> installed, List<Extension> requested)
+ {
+ return super.getNegotiatedExtensions(installed,requested);
+ }
+
+ @Override
+ public String getNegotiatedSubprotocol(List<String> supported, List<String> requested)
+ {
+ return super.getNegotiatedSubprotocol(supported,requested);
+ }
+
+ @Override
+ public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response)
+ {
+ super.modifyHandshake(sec,request,response);
+ }
+}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java
new file mode 100644
index 0000000000..0a1d491a7b
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java
@@ -0,0 +1,93 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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.io.IOException;
+import java.util.List;
+
+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.UpgradeRequest;
+import org.eclipse.jetty.websocket.api.UpgradeResponse;
+import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
+
+public class JsrCreator implements WebSocketCreator
+{
+ private static final Logger LOG = Log.getLogger(JsrCreator.class);
+ private final ServerEndpointConfig config;
+
+ public JsrCreator(ServerEndpointConfig config)
+ {
+ this.config = config;
+ }
+
+ @Override
+ public Object createWebSocket(UpgradeRequest req, UpgradeResponse resp)
+ {
+ JsrHandshakeRequest hsreq = new JsrHandshakeRequest(req);
+ JsrHandshakeResponse hsresp = new JsrHandshakeResponse(resp);
+
+ ServerEndpointConfig.Configurator configurator = config.getConfigurator();
+
+ // modify handshake
+ configurator.modifyHandshake(config,hsreq,hsresp);
+
+ // check origin
+ if (!configurator.checkOrigin(req.getOrigin()))
+ {
+ try
+ {
+ resp.sendForbidden("Origin mismatch");
+ }
+ catch (IOException e)
+ {
+ LOG.debug("Unable to send error response",e);
+ }
+ return null;
+ }
+
+ // deal with sub protocols
+ List<String> supported = config.getSubprotocols();
+ List<String> requested = req.getSubProtocols();
+ String subprotocol = configurator.getNegotiatedSubprotocol(supported,requested);
+ if (subprotocol != null)
+ {
+ resp.setAcceptedSubProtocol(subprotocol);
+ }
+
+ // create endpoint class
+ try
+ {
+ return config.getEndpointClass().newInstance();
+ }
+ catch (InstantiationException | IllegalAccessException e)
+ {
+ LOG.debug("Unable to create websocket: " + config.getEndpointClass().getName(),e);
+ return null;
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("%s[config=%s]",this.getClass().getName(),config);
+ }
+}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrHandshakeRequest.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrHandshakeRequest.java
new file mode 100644
index 0000000000..f1b0a70681
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrHandshakeRequest.java
@@ -0,0 +1,83 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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.net.URI;
+import java.security.Principal;
+import java.util.List;
+import java.util.Map;
+
+import javax.websocket.server.HandshakeRequest;
+
+import org.eclipse.jetty.websocket.api.UpgradeRequest;
+
+public class JsrHandshakeRequest implements HandshakeRequest
+{
+ private final UpgradeRequest request;
+
+ public JsrHandshakeRequest(UpgradeRequest req)
+ {
+ this.request = req;
+ }
+
+ @Override
+ public Map<String, List<String>> getHeaders()
+ {
+ return request.getHeaders();
+ }
+
+ @Override
+ public Object getHttpSession()
+ {
+ return request.getSession();
+ }
+
+ @Override
+ public Map<String, List<String>> getParameterMap()
+ {
+ return request.getParameterMap();
+ }
+
+ @Override
+ public String getQueryString()
+ {
+ return request.getQueryString();
+ }
+
+ @Override
+ public URI getRequestURI()
+ {
+ return request.getRequestURI();
+ }
+
+ @Override
+ public Principal getUserPrincipal()
+ {
+ // TODO: need to return User Principal
+ return null;
+ }
+
+ @Override
+ public boolean isUserInRole(String role)
+ {
+ // TODO: need to return isUserInRole result
+ return false;
+ }
+
+}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/WebSocketHandler.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrHandshakeResponse.java
index 7ba75d1176..0eaf62f3ee 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/WebSocketHandler.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrHandshakeResponse.java
@@ -18,8 +18,25 @@
package org.eclipse.jetty.websocket.jsr356.server;
-import org.eclipse.jetty.server.handler.HandlerWrapper;
+import java.util.List;
+import java.util.Map;
-public class WebSocketHandler extends HandlerWrapper
+import javax.websocket.HandshakeResponse;
+
+import org.eclipse.jetty.websocket.api.UpgradeResponse;
+
+public class JsrHandshakeResponse implements HandshakeResponse
{
+ private final UpgradeResponse response;
+
+ public JsrHandshakeResponse(UpgradeResponse resp)
+ {
+ this.response = resp;
+ }
+
+ @Override
+ public Map<String, List<String>> getHeaders()
+ {
+ return response.getHeaders();
+ }
}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerMetadata.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerMetadata.java
index 71bf546769..13b9f1279d 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerMetadata.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerMetadata.java
@@ -106,4 +106,9 @@ public class JsrServerMetadata extends JsrMetadata<ServerEndpoint>
// Copy constructor
return new JettyServerEndpointConfig(config);
}
+
+ public String getPath()
+ {
+ return config.getPath();
+ }
}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java
index 37ee61dc70..02336accf2 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java
@@ -18,33 +18,78 @@
package org.eclipse.jetty.websocket.jsr356.server;
+import java.util.EnumSet;
import java.util.concurrent.ConcurrentHashMap;
+import javax.servlet.DispatcherType;
+import javax.websocket.ContainerProvider;
import javax.websocket.DeploymentException;
import javax.websocket.server.ServerEndpointConfig;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.jsr356.ClientContainer;
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
+import org.eclipse.jetty.websocket.jsr356.server.pathmap.WebSocketPathSpec;
+import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
+import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
public class ServerContainer extends ClientContainer implements javax.websocket.server.ServerContainer
{
+ private static final Logger LOG = Log.getLogger(ServerContainer.class);
+
+ public static ServerContainer getInstance()
+ {
+ return (ServerContainer)ContainerProvider.getWebSocketContainer();
+ }
private ConcurrentHashMap<Class<?>, JsrServerMetadata> endpointServerMetadataCache = new ConcurrentHashMap<>();
+ private MappedWebSocketCreator mappedCreator;
+
+ public ServerContainer()
+ {
+ super();
+ WebAppContext webapp = WebAppContext.getCurrentWebAppContext();
+ if (webapp != null)
+ {
+ WebSocketUpgradeFilter filter = new WebSocketUpgradeFilter();
+ FilterHolder fholder = new FilterHolder(filter);
+ fholder.setName("Jetty_WebSocketUpgradeFilter");
+ fholder.setDisplayName("WebSocket Upgrade Filter");
+ String pathSpec = "/*";
+ webapp.addFilter(fholder,pathSpec,EnumSet.of(DispatcherType.REQUEST));
+ LOG.debug("Adding {} mapped to {} to {}",filter,pathSpec,webapp);
+ mappedCreator = filter;
+ }
+ else
+ {
+ LOG.debug("No active WebAppContext detected");
+ }
+ }
@Override
public void addEndpoint(Class<?> endpointClass) throws DeploymentException
{
- // TODO Auto-generated method stub
+ JsrServerMetadata metadata = getServerEndpointMetadata(endpointClass);
+ addEndpoint(metadata);
}
- public void addEndpoint(JsrServerMetadata metadata)
+ public void addEndpoint(JsrServerMetadata metadata) throws DeploymentException
{
- // TODO Auto-generated method stub
+ addEndpoint(metadata.getEndpointConfigCopy());
}
@Override
- public void addEndpoint(ServerEndpointConfig serverConfig) throws DeploymentException
+ public void addEndpoint(ServerEndpointConfig config) throws DeploymentException
+ {
+ JsrCreator creator = new JsrCreator(config);
+ mappedCreator.addMapping(new WebSocketPathSpec(config.getPath()),creator);
+ }
+
+ public void addMappedCreator(MappedWebSocketCreator mappedCreator)
{
- // TODO Auto-generated method stub
+ this.mappedCreator = mappedCreator;
}
public JsrServerMetadata getServerEndpointMetadata(Class<?> endpointClass) throws DeploymentException
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappings.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappings.java
deleted file mode 100644
index bb737afb5c..0000000000
--- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappings.java
+++ /dev/null
@@ -1,147 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2013 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.pathmap;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.jetty.websocket.jsr356.server.pathmap.PathMappings.MappedResource;
-
-/**
- * Path Mappings of PathSpec to Resource.
- * <p>
- * Sorted into search order upon entry into the Set
- *
- * @param <E>
- */
-public class PathMappings<E> implements Iterable<MappedResource<E>>
-{
- public static class MappedResource<E> implements Comparable<MappedResource<E>>
- {
- private final PathSpec pathSpec;
- private final E resource;
-
- public MappedResource(PathSpec pathSpec, E resource)
- {
- this.pathSpec = pathSpec;
- this.resource = resource;
- }
-
- /**
- * Comparison is based solely on the pathSpec
- */
- @Override
- public int compareTo(MappedResource<E> other)
- {
- return this.pathSpec.compareTo(other.pathSpec);
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- MappedResource<?> other = (MappedResource<?>)obj;
- if (pathSpec == null)
- {
- if (other.pathSpec != null)
- {
- return false;
- }
- }
- else if (!pathSpec.equals(other.pathSpec))
- {
- return false;
- }
- return true;
- }
-
- public PathSpec getPathSpec()
- {
- return pathSpec;
- }
-
- public E getResource()
- {
- return resource;
- }
-
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = (prime * result) + ((pathSpec == null)?0:pathSpec.hashCode());
- return result;
- }
-
- @Override
- public String toString()
- {
- return String.format("MappedResource[pathSpec=%s,resource=%s]",pathSpec,resource);
- }
- }
-
- private List<MappedResource<E>> mappings = new ArrayList<MappedResource<E>>();
- private MappedResource<E> defaultResource = null;
-
- public MappedResource<E> getMatch(String path)
- {
- int len = mappings.size();
- for (int i = 0; i < len; i++)
- {
- MappedResource<E> mr = mappings.get(i);
- if (mr.getPathSpec().matches(path))
- {
- return mr;
- }
- }
- return defaultResource;
- }
-
- @Override
- public Iterator<MappedResource<E>> iterator()
- {
- return mappings.iterator();
- }
-
- public void put(PathSpec pathSpec, E resource)
- {
- MappedResource<E> entry = new MappedResource<>(pathSpec,resource);
- if (pathSpec.group == PathSpecGroup.DEFAULT)
- {
- defaultResource = entry;
- }
- // TODO: warning on replacement of existing mapping?
- mappings.add(entry);
- Collections.sort(mappings);
- }
-}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathSpec.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathSpec.java
deleted file mode 100644
index 2a8fb67776..0000000000
--- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathSpec.java
+++ /dev/null
@@ -1,162 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2013 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.pathmap;
-
-/**
- * The base PathSpec, what all other path specs are based on
- */
-public abstract class PathSpec implements Comparable<PathSpec>
-{
- protected String pathSpec;
- protected PathSpecGroup group;
- protected int pathDepth;
- protected int specLength;
-
- @Override
- public int compareTo(PathSpec other)
- {
- // Grouping (increasing)
- int diff = this.group.ordinal() - other.group.ordinal();
- if (diff != 0)
- {
- return diff;
- }
-
- // Spec Length (decreasing)
- diff = other.specLength - this.specLength;
- if (diff != 0)
- {
- return diff;
- }
-
- // Path Spec Name (alphabetical)
- return this.pathSpec.compareTo(other.pathSpec);
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- PathSpec other = (PathSpec)obj;
- if (pathSpec == null)
- {
- if (other.pathSpec != null)
- {
- return false;
- }
- }
- else if (!pathSpec.equals(other.pathSpec))
- {
- return false;
- }
- return true;
- }
-
- /**
- * Get the number of path elements that this path spec declares.
- * <p>
- * This is used to determine longest match logic.
- *
- * @return the depth of the path segments that this spec declares
- */
- public int getPathDepth()
- {
- return pathDepth;
- }
-
- /**
- * Return the portion of the path that is after the path spec.
- *
- * @param path
- * the path to match against
- * @return the path info portion of the string
- */
- public abstract String getPathInfo(String path);
-
- /**
- * Return the portion of the path that matches a path spec.
- *
- * @param path
- * the path to match against
- * @return the match, or null if no match at all
- */
- public abstract String getPathMatch(String path);
-
- /**
- * The as-provided path spec.
- *
- * @return the as-provided path spec
- */
- public String getPathSpec()
- {
- return pathSpec;
- }
-
- /**
- * Get the relative path.
- *
- * @param base
- * the base the path is relative to
- * @param path
- * the additional path
- * @return the base plus path with pathSpec portion removed
- */
- public abstract String getRelativePath(String base, String path);
-
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = (prime * result) + ((pathSpec == null)?0:pathSpec.hashCode());
- return result;
- }
-
- /**
- * Test to see if the provided path matches this path spec
- *
- * @param path
- * the path to test
- * @return true if the path matches this path spec, false otherwise
- */
- public abstract boolean matches(String path);
-
- @Override
- public String toString()
- {
- StringBuilder str = new StringBuilder();
- str.append(this.getClass().getSimpleName()).append("[\"");
- str.append(pathSpec);
- str.append("\",pathDepth=").append(pathDepth);
- str.append(",group=").append(group);
- str.append("]");
- return str.toString();
- }
-}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathSpecGroup.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathSpecGroup.java
deleted file mode 100644
index 91eae4eec3..0000000000
--- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathSpecGroup.java
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2013 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.pathmap;
-
-/**
- * Types of path spec groups.
- * <p>
- * This is used to facilitate proper pathspec search order.
- * <p>
- * Search Order: {@link PathSpecGroup#ordinal()} [increasin], {@link PathSpec#specLength} [decreasing], {@link PathSpec#pathSpec} [natural sort order]
- */
-public enum PathSpecGroup
-{
- // NOTE: Order of enums determines order of Groups.
-
- /**
- * For exactly defined path specs, no glob.
- */
- EXACT,
- /**
- * For path specs that have a hardcoded prefix and suffix with wildcard glob in the middle.
- *
- * <pre>
- * "^/downloads/[^/]*.zip$" - regex spec
- * "/a/{var}/c" - websocket spec
- * </pre>
- *
- * Note: there is no known servlet spec variant of this kind of path spec
- */
- MIDDLE_GLOB,
- /**
- * For path specs that have a hardcoded prefix and a trailing wildcard glob.
- * <p>
- *
- * <pre>
- * "/downloads/*" - servlet spec
- * "/api/*" - servlet spec
- * "^/rest/.*$" - regex spec
- * "/bookings/{guest-id}" - websocket spec
- * "/rewards/{vip-level}" - websocket spec
- * </pre>
- */
- PREFIX_GLOB,
- /**
- * For path specs that have a wildcard glob with a hardcoded suffix
- *
- * <pre>
- * "*.do" - servlet spec
- * "*.css" - servlet spec
- * "^.*\.zip$" - regex spec
- * </pre>
- *
- * Note: there is no known websocket spec variant of this kind of path spec
- */
- SUFFIX_GLOB,
- /**
- * The default spec for accessing the Root and/or Default behavior.
- *
- * <pre>
- * "/" - servlet spec (Default Servlet)
- * "/" - websocket spec (Root Context)
- * "^/$" - regex spec (Root Context)
- * </pre>
- */
- DEFAULT;
-}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/RegexPathSpec.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/RegexPathSpec.java
deleted file mode 100644
index 6452958a80..0000000000
--- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/RegexPathSpec.java
+++ /dev/null
@@ -1,166 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2013 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.pathmap;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class RegexPathSpec extends PathSpec
-{
- protected Pattern pattern;
-
- protected RegexPathSpec()
- {
- super();
- }
-
- public RegexPathSpec(String regex)
- {
- super.pathSpec = regex;
- boolean inGrouping = false;
- this.pathDepth = 0;
- this.specLength = pathSpec.length();
- // build up a simple signature we can use to identify the grouping
- StringBuilder signature = new StringBuilder();
- for (char c : pathSpec.toCharArray())
- {
- switch (c)
- {
- case '[':
- inGrouping = true;
- break;
- case ']':
- inGrouping = false;
- signature.append('g'); // glob
- break;
- case '*':
- signature.append('g'); // glob
- break;
- case '/':
- if (!inGrouping)
- {
- this.pathDepth++;
- }
- break;
- default:
- if (!inGrouping)
- {
- if (Character.isLetterOrDigit(c))
- {
- signature.append('l'); // literal (exact)
- }
- }
- break;
- }
- }
- this.pattern = Pattern.compile(pathSpec);
-
- // Figure out the grouping based on the signature
- String sig = signature.toString();
-
- if (Pattern.matches("^l*$",sig))
- {
- this.group = PathSpecGroup.EXACT;
- }
- else if (Pattern.matches("^l*g+",sig))
- {
- this.group = PathSpecGroup.PREFIX_GLOB;
- }
- else if (Pattern.matches("^g+l+$",sig))
- {
- this.group = PathSpecGroup.SUFFIX_GLOB;
- }
- else
- {
- this.group = PathSpecGroup.MIDDLE_GLOB;
- }
- }
-
- public Matcher getMatcher(String path)
- {
- return this.pattern.matcher(path);
- }
-
- @Override
- public String getPathInfo(String path)
- {
- // Path Info only valid for PREFIX_GLOB types
- if (group == PathSpecGroup.PREFIX_GLOB)
- {
- Matcher matcher = getMatcher(path);
- if (matcher.matches())
- {
- if (matcher.groupCount() >= 1)
- {
- String pathInfo = matcher.group(1);
- if ("".equals(pathInfo))
- {
- return "/";
- }
- else
- {
- return pathInfo;
- }
- }
- }
- }
- return null;
- }
-
- @Override
- public String getPathMatch(String path)
- {
- Matcher matcher = getMatcher(path);
- if (matcher.matches())
- {
- if (matcher.groupCount() >= 1)
- {
- int idx = matcher.start(1);
- if (idx > 0)
- {
- if (path.charAt(idx - 1) == '/')
- {
- idx--;
- }
- return path.substring(0,idx);
- }
- }
- return path;
- }
- return null;
- }
-
- public Pattern getPattern()
- {
- return this.pattern;
- }
-
- @Override
- public String getRelativePath(String base, String path)
- {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public boolean matches(String path)
- {
- return getMatcher(path).matches();
- }
-}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/ServletPathSpec.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/ServletPathSpec.java
deleted file mode 100644
index 541c85f5c6..0000000000
--- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/ServletPathSpec.java
+++ /dev/null
@@ -1,291 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2013 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.pathmap;
-
-import org.eclipse.jetty.util.URIUtil;
-
-public class ServletPathSpec extends PathSpec
-{
- public static final String PATH_SPEC_SEPARATORS = ":,";
-
- /**
- * Get multi-path spec splits.
- *
- * @param servletPathSpec
- * the path spec that might contain multiple declared path specs
- * @return the individual path specs found.
- */
- public static ServletPathSpec[] getMultiPathSpecs(String servletPathSpec)
- {
- String pathSpecs[] = servletPathSpec.split(PATH_SPEC_SEPARATORS);
- int len = pathSpecs.length;
- ServletPathSpec sps[] = new ServletPathSpec[len];
- for (int i = 0; i < len; i++)
- {
- sps[i] = new ServletPathSpec(pathSpecs[i]);
- }
- return sps;
- }
-
- public ServletPathSpec(String servletPathSpec)
- {
- super();
- assertValidServletPathSpec(servletPathSpec);
-
- // The Path Spec for Default Servlet
- if ((servletPathSpec == null) || (servletPathSpec.length() == 0) || "/".equals(servletPathSpec))
- {
- super.pathSpec = "/";
- super.pathDepth = -1; // force this to be last in sort order
- this.specLength = 1;
- this.group = PathSpecGroup.DEFAULT;
- return;
- }
-
- this.specLength = servletPathSpec.length();
- super.pathDepth = 0;
- char lastChar = servletPathSpec.charAt(specLength - 1);
- // prefix based
- if ((servletPathSpec.charAt(0) == '/') && (specLength > 1) && (lastChar == '*'))
- {
- this.group = PathSpecGroup.PREFIX_GLOB;
- }
- // suffix based
- else if (servletPathSpec.charAt(0) == '*')
- {
- this.group = PathSpecGroup.SUFFIX_GLOB;
- }
- else
- {
- this.group = PathSpecGroup.EXACT;
- }
-
- for (int i = 0; i < specLength; i++)
- {
- int cp = servletPathSpec.codePointAt(i);
- if (cp < 128)
- {
- char c = (char)cp;
- switch (c)
- {
- case '/':
- super.pathDepth++;
- break;
- }
- }
- }
-
- super.pathSpec = servletPathSpec;
- }
-
- private void assertValidServletPathSpec(String servletPathSpec)
- {
- if ((servletPathSpec == null) || servletPathSpec.equals(""))
- {
- return; // empty path spec
- }
-
- // Ensure we don't have path spec separators here in our single path spec.
- for (char c : PATH_SPEC_SEPARATORS.toCharArray())
- {
- if (servletPathSpec.indexOf(c) >= 0)
- {
- throw new IllegalArgumentException("Servlet Spec 12.2 violation: encountered Path Spec Separator [" + PATH_SPEC_SEPARATORS
- + "] within specified path spec. did you forget to split this path spec up?");
- }
- }
-
- int len = servletPathSpec.length();
- // path spec must either start with '/' or '*.'
- if (servletPathSpec.charAt(0) == '/')
- {
- // Prefix Based
- if (len == 1)
- {
- return; // simple '/' path spec
- }
- int idx = servletPathSpec.indexOf('*');
- if (idx < 0)
- {
- return; // no hit on glob '*'
- }
- // only allowed to have '*' at the end of the path spec
- if (idx != (len - 1))
- {
- throw new IllegalArgumentException("Servlet Spec 12.2 violation: glob '*' can only exist at end of prefix based matches");
- }
- }
- else if (servletPathSpec.startsWith("*."))
- {
- // Suffix Based
- int idx = servletPathSpec.indexOf('/');
- // cannot have path separator
- if (idx >= 0)
- {
- throw new IllegalArgumentException("Servlet Spec 12.2 violation: suffix based path spec cannot have path separators");
- }
-
- idx = servletPathSpec.indexOf('*',2);
- // only allowed to have 1 glob '*', at the start of the path spec
- if (idx >= 1)
- {
- throw new IllegalArgumentException("Servlet Spec 12.2 violation: suffix based path spec cannot have multiple glob '*'");
- }
- }
- else
- {
- throw new IllegalArgumentException("Servlet Spec 12.2 violation: path spec must start with \"/\" or \"*.\"");
- }
- }
-
- @Override
- public String getPathInfo(String path)
- {
- // Path Info only valid for PREFIX_GLOB types
- if (group == PathSpecGroup.PREFIX_GLOB)
- {
- if (path.length() == (specLength - 2))
- {
- return null;
- }
- return path.substring(specLength - 2);
- }
-
- return null;
- }
-
- @Override
- public String getPathMatch(String path)
- {
- switch (group)
- {
- case EXACT:
- if (pathSpec.equals(path))
- {
- return path;
- }
- else
- {
- return null;
- }
- case PREFIX_GLOB:
- if (isWildcardMatch(path))
- {
- return path.substring(0,specLength - 2);
- }
- else
- {
- return null;
- }
- case SUFFIX_GLOB:
- if (path.regionMatches(path.length() - (specLength - 1),pathSpec,1,specLength - 1))
- {
- return path;
- }
- else
- {
- return null;
- }
- case DEFAULT:
- return path;
- default:
- return null;
- }
- }
-
- @Override
- public String getRelativePath(String base, String path)
- {
- String info = getPathInfo(path);
- if (info == null)
- {
- info = path;
- }
-
- if (info.startsWith("./"))
- {
- info = info.substring(2);
- }
- if (base.endsWith(URIUtil.SLASH))
- {
- if (info.startsWith(URIUtil.SLASH))
- {
- path = base + info.substring(1);
- }
- else
- {
- path = base + info;
- }
- }
- else if (info.startsWith(URIUtil.SLASH))
- {
- path = base + info;
- }
- else
- {
- path = base + URIUtil.SLASH + info;
- }
- return path;
- }
-
- private boolean isExactMatch(String path)
- {
- if (group == PathSpecGroup.EXACT)
- {
- if (pathSpec.equals(path))
- {
- return true;
- }
- return (path.charAt(path.length() - 1) == '/') && (path.equals(pathSpec + '/'));
- }
- return false;
- }
-
- private boolean isWildcardMatch(String path)
- {
- // For a spec of "/foo/*" match "/foo" , "/foo/..." but not "/foobar"
- int cpl = specLength - 2;
- if ((group == PathSpecGroup.PREFIX_GLOB) && (path.regionMatches(0,pathSpec,0,cpl)))
- {
- if ((path.length() == cpl) || ('/' == path.charAt(cpl)))
- {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean matches(String path)
- {
- switch (group)
- {
- case EXACT:
- return isExactMatch(path);
- case PREFIX_GLOB:
- return isWildcardMatch(path);
- case SUFFIX_GLOB:
- return path.regionMatches((path.length() - specLength) + 1,pathSpec,1,specLength - 1);
- case DEFAULT:
- return true;
- default:
- return false;
- }
- }
-}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpec.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpec.java
index 3c136b5727..42c76dcfe6 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpec.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpec.java
@@ -29,10 +29,14 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
+import org.eclipse.jetty.websocket.server.pathmap.PathSpecGroup;
+import org.eclipse.jetty.websocket.server.pathmap.RegexPathSpec;
+
/**
- * PathSpec for WebSocket &#064;{@link ServerEndpoint} declarations.
+ * PathSpec for WebSocket &#064;{@link ServerEndpoint} declarations with support for URI templates and &#064;{@link PathParam} annotations
*/
public class WebSocketPathSpec extends RegexPathSpec
{
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/resources/META-INF/services/javax.websocket.server.ServerEndpointConfig$Configurator b/jetty-websocket/javax-websocket-server-impl/src/main/resources/META-INF/services/javax.websocket.server.ServerEndpointConfig$Configurator
new file mode 100644
index 0000000000..34fa1370e8
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/main/resources/META-INF/services/javax.websocket.server.ServerEndpointConfig$Configurator
@@ -0,0 +1 @@
+org.eclipse.jetty.websocket.jsr356.server.JettyServerEndpointConfigurator \ No newline at end of file
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicAnnotatedTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicAnnotatedTest.java
index 197f71a5c7..1017c4640c 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicAnnotatedTest.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicAnnotatedTest.java
@@ -35,11 +35,14 @@ import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.WebSocketClient;
-import org.eclipse.jetty.websocket.jsr356.server.samples.BasicEchoSocket;
+import org.eclipse.jetty.websocket.jsr356.server.samples.echo.BasicEchoSocket;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
+/**
+ * Example of an annotated echo server discovered via annotation scanning.
+ */
public class BasicAnnotatedTest
{
@Rule
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicEndpointTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicEndpointTest.java
new file mode 100644
index 0000000000..411b2b3041
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicEndpointTest.java
@@ -0,0 +1,90 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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.net.URI;
+import java.util.Queue;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import javax.websocket.Endpoint;
+import javax.websocket.server.ServerContainer;
+
+import org.eclipse.jetty.toolchain.test.TestingDir;
+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.server.samples.echo.BasicEchoEndpoint;
+import org.eclipse.jetty.websocket.jsr356.server.samples.echo.BasicEchoEndpointConfigContextListener;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ * Example of an {@link Endpoint} extended echo server added programmatically via the
+ * {@link ServerContainer#addEndpoint(javax.websocket.server.ServerEndpointConfig)}
+ */
+public class BasicEndpointTest
+{
+ @Rule
+ public TestingDir testdir = new TestingDir();
+
+ @Test
+ public void testEcho() throws Exception
+ {
+ WSServer wsb = new WSServer(testdir,"app");
+ wsb.copyWebInf("basic-echo-endpoint-config-web.xml");
+ // the endpoint (extends javax.websocket.Endpoint)
+ wsb.copyClass(BasicEchoEndpoint.class);
+ // the configuration (adds the endpoint)
+ wsb.copyClass(BasicEchoEndpointConfigContextListener.class);
+
+ try
+ {
+ wsb.start();
+ URI uri = wsb.getServerBaseURI();
+
+ WebAppContext webapp = wsb.createWebAppContext();
+ // default webapp configuration used (no annotation scanning)
+ wsb.deployWebapp(webapp);
+ wsb.dump();
+
+ WebSocketClient client = new WebSocketClient();
+ try
+ {
+ client.start();
+ JettyEchoSocket clientEcho = new JettyEchoSocket();
+ Future<Session> future = client.connect(clientEcho,uri.resolve("/echo"));
+ // wait for connect
+ future.get(1,TimeUnit.SECONDS);
+ clientEcho.sendMessage("Hello World");
+ Queue<String> msgs = clientEcho.awaitMessages(1);
+ Assert.assertEquals("Expected message","Hello World",msgs.poll());
+ }
+ finally
+ {
+ client.stop();
+ }
+ }
+ finally
+ {
+ wsb.stop();
+ }
+ }
+}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/JettyServerEndpointConfiguratorTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/JettyServerEndpointConfiguratorTest.java
new file mode 100644
index 0000000000..55e30f3acc
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/JettyServerEndpointConfiguratorTest.java
@@ -0,0 +1,51 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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.*;
+import static org.junit.Assert.*;
+
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+import javax.websocket.server.ServerEndpointConfig;
+
+import org.junit.Test;
+
+/**
+ * Test the JettyServerEndpointConfigurator impl.
+ */
+public class JettyServerEndpointConfiguratorTest
+{
+ @Test
+ public void testServiceLoader()
+ {
+ System.out.printf("Service Name: %s%n",ServerEndpointConfig.Configurator.class.getName());
+
+ ServiceLoader<ServerEndpointConfig.Configurator> loader = ServiceLoader.load(javax.websocket.server.ServerEndpointConfig.Configurator.class);
+ assertThat("loader",loader,notNullValue());
+ Iterator<ServerEndpointConfig.Configurator> iter = loader.iterator();
+ assertThat("loader.iterator",iter,notNullValue());
+ assertThat("loader.iterator.hasNext",iter.hasNext(),is(true));
+
+ ServerEndpointConfig.Configurator configr = iter.next();
+ assertThat("Configurator",configr,notNullValue());
+ assertThat("COnfigurator type",configr,instanceOf(JettyServerEndpointConfigurator.class));
+ }
+}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/WSServer.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/WSServer.java
index 3dc2ed997a..baeeff70ed 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/WSServer.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/WSServer.java
@@ -34,6 +34,8 @@ 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.webapp.WebAppContext;
import org.junit.Assert;
@@ -44,6 +46,7 @@ import org.junit.Assert;
*/
public class WSServer
{
+ private static final Logger LOG = Log.getLogger(WSServer.class);
@SuppressWarnings("unused")
private final TestingDir testdir;
private final File contextDir;
@@ -62,18 +65,34 @@ public class WSServer
FS.ensureEmpty(contextDir);
}
- public void copyEndpoint(Class<?> endpointClass) throws Exception
+ public void copyClass(Class<?> clazz) throws Exception
{
ClassLoader cl = Thread.currentThread().getContextClassLoader();
- String endpointPath = endpointClass.getName().replace('.','/') + ".class";
+ String endpointPath = clazz.getName().replace('.','/') + ".class";
URL classUrl = cl.getResource(endpointPath);
- Assert.assertThat("Class URL for: " + endpointClass,classUrl,notNullValue());
+ Assert.assertThat("Class URL for: " + clazz,classUrl,notNullValue());
File destFile = new File(classesDir,OS.separators(endpointPath));
FS.ensureDirExists(destFile.getParentFile());
File srcFile = new File(classUrl.toURI());
IO.copy(srcFile,destFile);
}
+ public void copyEndpoint(Class<?> endpointClass) throws Exception
+ {
+ copyClass(endpointClass);
+ }
+
+ public void copyWebInf(String testResourceName) throws IOException
+ {
+ webinf = new File(contextDir,"WEB-INF");
+ FS.ensureDirExists(webinf);
+ classesDir = new File(webinf,"classes");
+ FS.ensureDirExists(classesDir);
+ File webxml = new File(webinf,"web.xml");
+ File testWebXml = MavenTestingUtils.getTestResourceFile(testResourceName);
+ IO.copy(testWebXml,webxml);
+ }
+
public WebAppContext createWebAppContext()
{
WebAppContext context = new WebAppContext();
@@ -84,13 +103,7 @@ public class WSServer
public void createWebInf() throws IOException
{
- webinf = new File(contextDir,"WEB-INF");
- FS.ensureDirExists(webinf);
- classesDir = new File(webinf,"classes");
- FS.ensureDirExists(classesDir);
- File webxml = new File(webinf,"web.xml");
- File emptyWebXml = MavenTestingUtils.getTestResourceFile("empty-web.xml");
- IO.copy(emptyWebXml,webxml);
+ copyWebInf("empty-web.xml");
}
public void deployWebapp(WebAppContext webapp) throws Exception
@@ -134,6 +147,7 @@ public class WSServer
}
int port = connector.getLocalPort();
serverUri = new URI(String.format("ws://%s:%d/",host,port));
+ LOG.debug("Server started on {}",serverUri);
}
public void stop()
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappingsBenchmarkTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappingsBenchmarkTest.java
deleted file mode 100644
index 250ec30934..0000000000
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappingsBenchmarkTest.java
+++ /dev/null
@@ -1,224 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2013 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.pathmap;
-
-import java.util.concurrent.CyclicBarrier;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jetty.http.PathMap;
-import org.eclipse.jetty.toolchain.test.AdvancedRunner;
-import org.eclipse.jetty.toolchain.test.annotation.Stress;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AdvancedRunner.class)
-public class PathMappingsBenchmarkTest
-{
- public static abstract class AbstractPathMapThread extends Thread
- {
- private int iterations;
- private CyclicBarrier barrier;
- private long success;
- private long error;
-
- public AbstractPathMapThread(int iterations, CyclicBarrier barrier)
- {
- this.iterations = iterations;
- this.barrier = barrier;
- }
-
- public abstract String getMatchedResource(String path);
-
- @Override
- public void run()
- {
- int llen = LOOKUPS.length;
- String path;
- String expectedResource;
- String matchedResource;
- await(barrier);
- for (int iter = 0; iter < iterations; iter++)
- {
- for (int li = 0; li < llen; li++)
- {
- path = LOOKUPS[li][0];
- expectedResource = LOOKUPS[li][1];
- matchedResource = getMatchedResource(path);
- if (matchedResource.equals(expectedResource))
- {
- success++;
- }
- else
- {
- error++;
- }
- }
- }
- await(barrier);
- }
- }
-
- public static class PathMapMatchThread extends AbstractPathMapThread
- {
- private PathMap<String> pathmap;
-
- public PathMapMatchThread(PathMap<String> pathmap, int iters, CyclicBarrier barrier)
- {
- super(iters,barrier);
- this.pathmap = pathmap;
- }
-
- @Override
- public String getMatchedResource(String path)
- {
- return pathmap.getMatch(path).getValue();
- }
- }
-
- public static class PathMatchThread extends AbstractPathMapThread
- {
- private PathMappings<String> pathmap;
-
- public PathMatchThread(PathMappings<String> pathmap, int iters, CyclicBarrier barrier)
- {
- super(iters,barrier);
- this.pathmap = pathmap;
- }
-
- @Override
- public String getMatchedResource(String path)
- {
- return pathmap.getMatch(path).getResource();
- }
- }
-
- private static final Logger LOG = Log.getLogger(PathMappingsBenchmarkTest.class);
- private static final String[][] LOOKUPS;
- private int runs = 20;
- private int threads = 200;
- private int iters = 10000;
-
- static
- {
- LOOKUPS = new String[][]
- {
- // @formatter:off
- { "/abs/path", "path" },
- { "/abs/path/longer","longpath" },
- { "/abs/path/foo","default" },
- { "/main.css","default" },
- { "/downloads/script.gz","gzipped" },
- { "/downloads/distribution.tar.gz","tarball" },
- { "/downloads/readme.txt","default" },
- { "/downloads/logs.tgz","default" },
- { "/animal/horse/mustang","animals" },
- { "/animal/bird/eagle/bald","birds" },
- { "/animal/fish/shark/hammerhead","fishes" },
- { "/animal/insect/ladybug","animals" },
- // @formatter:on
- };
- }
-
- private static void await(CyclicBarrier barrier)
- {
- try
- {
- barrier.await();
- }
- catch (Exception x)
- {
- throw new RuntimeException(x);
- }
- }
-
- @Stress("High CPU")
- @Test
- public void testServletPathMap()
- {
- // Setup (old) PathMap
-
- PathMap<String> p = new PathMap<>();
-
- p.put("/abs/path","path");
- p.put("/abs/path/longer","longpath");
- p.put("/animal/bird/*","birds");
- p.put("/animal/fish/*","fishes");
- p.put("/animal/*","animals");
- p.put("*.tar.gz","tarball");
- p.put("*.gz","gzipped");
- p.put("/","default");
-
- final CyclicBarrier barrier = new CyclicBarrier(threads + 1);
-
- for (int r = 0; r < runs; r++)
- {
- for (int t = 0; t < threads; t++)
- {
- PathMapMatchThread thread = new PathMapMatchThread(p,iters,barrier);
- thread.start();
- }
- await(barrier);
- long begin = System.nanoTime();
- await(barrier);
- long end = System.nanoTime();
- long elapsed = TimeUnit.NANOSECONDS.toMillis(end - begin);
- int totalMatches = threads * iters * LOOKUPS.length;
- LOG.info("jetty-http/PathMap (Servlet only) threads:{}/iters:{}/total-matches:{} => {} ms",threads,iters,totalMatches,elapsed);
- }
- }
-
- @Stress("High CPU")
- @Test
- public void testServletPathMappings()
- {
- // Setup (new) PathMappings
-
- PathMappings<String> p = new PathMappings<>();
-
- p.put(new ServletPathSpec("/abs/path"),"path");
- p.put(new ServletPathSpec("/abs/path/longer"),"longpath");
- p.put(new ServletPathSpec("/animal/bird/*"),"birds");
- p.put(new ServletPathSpec("/animal/fish/*"),"fishes");
- p.put(new ServletPathSpec("/animal/*"),"animals");
- p.put(new ServletPathSpec("*.tar.gz"),"tarball");
- p.put(new ServletPathSpec("*.gz"),"gzipped");
- p.put(new ServletPathSpec("/"),"default");
-
- final CyclicBarrier barrier = new CyclicBarrier(threads + 1);
-
- for (int r = 0; r < runs; r++)
- {
- for (int t = 0; t < threads; t++)
- {
- PathMatchThread thread = new PathMatchThread(p,iters,barrier);
- thread.start();
- }
- await(barrier);
- long begin = System.nanoTime();
- await(barrier);
- long end = System.nanoTime();
- long elapsed = TimeUnit.NANOSECONDS.toMillis(end - begin);
- int totalMatches = threads * iters * LOOKUPS.length;
- LOG.info("jetty-websocket/PathMappings (Servlet only) threads:{}/iters:{}/total-matches:{} => {} ms",threads,iters,totalMatches,elapsed);
-
- }
- }
-}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappingsTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappingsTest.java
index 1479393f01..2ba15abe9d 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappingsTest.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappingsTest.java
@@ -20,7 +20,9 @@ package org.eclipse.jetty.websocket.jsr356.server.pathmap;
import static org.hamcrest.Matchers.*;
-import org.eclipse.jetty.websocket.jsr356.server.pathmap.PathMappings.MappedResource;
+import org.eclipse.jetty.websocket.server.pathmap.PathMappings;
+import org.eclipse.jetty.websocket.server.pathmap.PathMappings.MappedResource;
+import org.eclipse.jetty.websocket.server.pathmap.ServletPathSpec;
import org.junit.Assert;
import org.junit.Test;
@@ -73,49 +75,6 @@ public class PathMappingsTest
}
/**
- * Test the match order rules imposed by the Servlet API.
- * <p>
- * <ul>
- * <li>Exact match</li>
- * <li>Longest prefix match</li>
- * <li>Longest suffix match</li>
- * <li>default</li>
- * </ul>
- */
- @Test
- public void testServletMatchOrder()
- {
- PathMappings<String> p = new PathMappings<>();
-
- p.put(new ServletPathSpec("/abs/path"),"path");
- p.put(new ServletPathSpec("/abs/path/longer"),"longpath");
- p.put(new ServletPathSpec("/animal/bird/*"),"birds");
- p.put(new ServletPathSpec("/animal/fish/*"),"fishes");
- p.put(new ServletPathSpec("/animal/*"),"animals");
- p.put(new ServletPathSpec("*.tar.gz"),"tarball");
- p.put(new ServletPathSpec("*.gz"),"gzipped");
- p.put(new ServletPathSpec("/"),"default");
-
- for (MappedResource<String> res : p)
- {
- System.out.printf(" %s%n",res);
- }
-
- assertMatch(p,"/abs/path","path");
- assertMatch(p,"/abs/path/longer","longpath");
- assertMatch(p,"/abs/path/foo","default");
- assertMatch(p,"/main.css","default");
- assertMatch(p,"/downloads/script.gz","gzipped");
- assertMatch(p,"/downloads/distribution.tar.gz","tarball");
- assertMatch(p,"/downloads/readme.txt","default");
- assertMatch(p,"/downloads/logs.tgz","default");
- assertMatch(p,"/animal/horse/mustang","animals");
- assertMatch(p,"/animal/bird/eagle/bald","birds");
- assertMatch(p,"/animal/fish/shark/hammerhead","fishes");
- assertMatch(p,"/animal/insect/ladybug","animals");
- }
-
- /**
* Test the match order rules imposed by the WebSocket API (JSR-356)
* <p>
* <ul>
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/RegexPathSpecTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/RegexPathSpecTest.java
deleted file mode 100644
index cdcc150676..0000000000
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/RegexPathSpecTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2013 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.pathmap;
-
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class RegexPathSpecTest
-{
- public static void assertMatches(PathSpec spec, String path)
- {
- String msg = String.format("Spec(\"%s\").matches(\"%s\")",spec.getPathSpec(),path);
- assertThat(msg,spec.matches(path),is(true));
- }
-
- public static void assertNotMatches(PathSpec spec, String path)
- {
- String msg = String.format("!Spec(\"%s\").matches(\"%s\")",spec.getPathSpec(),path);
- assertThat(msg,spec.matches(path),is(false));
- }
-
- @Test
- public void testExactSpec()
- {
- RegexPathSpec spec = new RegexPathSpec("^/a$");
- assertEquals("Spec.pathSpec","^/a$",spec.getPathSpec());
- assertEquals("Spec.pattern","^/a$",spec.getPattern().pattern());
- assertEquals("Spec.pathDepth",1,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.EXACT,spec.group);
-
- assertMatches(spec,"/a");
-
- assertNotMatches(spec,"/aa");
- assertNotMatches(spec,"/a/");
- }
-
- @Test
- public void testMiddleSpec()
- {
- RegexPathSpec spec = new RegexPathSpec("^/rest/([^/]*)/list$");
- assertEquals("Spec.pathSpec","^/rest/([^/]*)/list$",spec.getPathSpec());
- assertEquals("Spec.pattern","^/rest/([^/]*)/list$",spec.getPattern().pattern());
- assertEquals("Spec.pathDepth",3,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.MIDDLE_GLOB,spec.group);
-
- assertMatches(spec,"/rest/api/list");
- assertMatches(spec,"/rest/1.0/list");
- assertMatches(spec,"/rest/2.0/list");
- assertMatches(spec,"/rest/accounts/list");
-
- assertNotMatches(spec,"/a");
- assertNotMatches(spec,"/aa");
- assertNotMatches(spec,"/aa/bb");
- assertNotMatches(spec,"/rest/admin/delete");
- assertNotMatches(spec,"/rest/list");
- }
-
- @Test
- public void testPrefixSpec()
- {
- RegexPathSpec spec = new RegexPathSpec("^/a/(.*)$");
- assertEquals("Spec.pathSpec","^/a/(.*)$",spec.getPathSpec());
- assertEquals("Spec.pattern","^/a/(.*)$",spec.getPattern().pattern());
- assertEquals("Spec.pathDepth",2,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.PREFIX_GLOB,spec.group);
-
- assertMatches(spec,"/a/");
- assertMatches(spec,"/a/b");
- assertMatches(spec,"/a/b/c/d/e");
-
- assertNotMatches(spec,"/a");
- assertNotMatches(spec,"/aa");
- assertNotMatches(spec,"/aa/bb");
- }
-
- @Test
- public void testSuffixSpec()
- {
- RegexPathSpec spec = new RegexPathSpec("^(.*).do$");
- assertEquals("Spec.pathSpec","^(.*).do$",spec.getPathSpec());
- assertEquals("Spec.pattern","^(.*).do$",spec.getPattern().pattern());
- assertEquals("Spec.pathDepth",0,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.SUFFIX_GLOB,spec.group);
-
- assertMatches(spec,"/a.do");
- assertMatches(spec,"/a/b/c.do");
- assertMatches(spec,"/abcde.do");
- assertMatches(spec,"/abc/efg.do");
-
- assertNotMatches(spec,"/a");
- assertNotMatches(spec,"/aa");
- assertNotMatches(spec,"/aa/bb");
- assertNotMatches(spec,"/aa/bb.do/more");
- }
-}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/ServletPathSpecTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/ServletPathSpecTest.java
deleted file mode 100644
index f1bd83a2fa..0000000000
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/ServletPathSpecTest.java
+++ /dev/null
@@ -1,186 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2013 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.pathmap;
-
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class ServletPathSpecTest
-{
- private void assertBadServletPathSpec(String pathSpec)
- {
- try
- {
- new ServletPathSpec(pathSpec);
- fail("Expected IllegalArgumentException for a bad servlet pathspec on: " + pathSpec);
- }
- catch (IllegalArgumentException e)
- {
- // expected path
- System.out.println(e);
- }
- }
-
- private void assertMatches(ServletPathSpec spec, String path)
- {
- String msg = String.format("Spec(\"%s\").matches(\"%s\")",spec.getPathSpec(),path);
- assertThat(msg,spec.matches(path),is(true));
- }
-
- private void assertNotMatches(ServletPathSpec spec, String path)
- {
- String msg = String.format("!Spec(\"%s\").matches(\"%s\")",spec.getPathSpec(),path);
- assertThat(msg,spec.matches(path),is(false));
- }
-
- @Test
- public void testBadServletPathSpecA()
- {
- assertBadServletPathSpec("foo");
- }
-
- @Test
- public void testBadServletPathSpecB()
- {
- assertBadServletPathSpec("/foo/*.do");
- }
-
- @Test
- public void testBadServletPathSpecC()
- {
- assertBadServletPathSpec("foo/*.do");
- }
-
- @Test
- public void testBadServletPathSpecD()
- {
- assertBadServletPathSpec("foo/*.*do");
- }
-
- @Test
- public void testBadServletPathSpecE()
- {
- assertBadServletPathSpec("*do");
- }
-
- @Test
- public void testDefaultPathSpec()
- {
- ServletPathSpec spec = new ServletPathSpec("/");
- assertEquals("Spec.pathSpec","/",spec.getPathSpec());
- assertEquals("Spec.pathDepth",-1,spec.getPathDepth());
- }
-
- @Test
- public void testEmptyPathSpec()
- {
- ServletPathSpec spec = new ServletPathSpec("");
- assertEquals("Spec.pathSpec","/",spec.getPathSpec());
- assertEquals("Spec.pathDepth",-1,spec.getPathDepth());
- }
-
- @Test
- public void testExactPathSpec()
- {
- ServletPathSpec spec = new ServletPathSpec("/abs/path");
- assertEquals("Spec.pathSpec","/abs/path",spec.getPathSpec());
- assertEquals("Spec.pathDepth",2,spec.getPathDepth());
-
- assertMatches(spec,"/abs/path");
- assertMatches(spec,"/abs/path/");
-
- assertNotMatches(spec,"/abs/path/more");
- assertNotMatches(spec,"/foo");
- assertNotMatches(spec,"/foo/abs/path");
- assertNotMatches(spec,"/foo/abs/path/");
- }
-
- @Test
- public void testGetPathInfo()
- {
- assertEquals("pathInfo exact",null,new ServletPathSpec("/Foo/bar").getPathInfo("/Foo/bar"));
- assertEquals("pathInfo prefix","/bar",new ServletPathSpec("/Foo/*").getPathInfo("/Foo/bar"));
- assertEquals("pathInfo prefix","/*",new ServletPathSpec("/Foo/*").getPathInfo("/Foo/*"));
- assertEquals("pathInfo prefix","/",new ServletPathSpec("/Foo/*").getPathInfo("/Foo/"));
- assertEquals("pathInfo prefix",null,new ServletPathSpec("/Foo/*").getPathInfo("/Foo"));
- assertEquals("pathInfo suffix",null,new ServletPathSpec("*.ext").getPathInfo("/Foo/bar.ext"));
- assertEquals("pathInfo default",null,new ServletPathSpec("/").getPathInfo("/Foo/bar.ext"));
-
- assertEquals("pathInfo default","/xxx/zzz",new ServletPathSpec("/*").getPathInfo("/xxx/zzz"));
- }
-
- @Test
- public void testNullPathSpec()
- {
- ServletPathSpec spec = new ServletPathSpec(null);
- assertEquals("Spec.pathSpec","/",spec.getPathSpec());
- assertEquals("Spec.pathDepth",-1,spec.getPathDepth());
- }
-
- @Test
- public void testPathMatch()
- {
- assertEquals("pathMatch exact","/Foo/bar",new ServletPathSpec("/Foo/bar").getPathMatch("/Foo/bar"));
- assertEquals("pathMatch prefix","/Foo",new ServletPathSpec("/Foo/*").getPathMatch("/Foo/bar"));
- assertEquals("pathMatch prefix","/Foo",new ServletPathSpec("/Foo/*").getPathMatch("/Foo/"));
- assertEquals("pathMatch prefix","/Foo",new ServletPathSpec("/Foo/*").getPathMatch("/Foo"));
- assertEquals("pathMatch suffix","/Foo/bar.ext",new ServletPathSpec("*.ext").getPathMatch("/Foo/bar.ext"));
- assertEquals("pathMatch default","/Foo/bar.ext",new ServletPathSpec("/").getPathMatch("/Foo/bar.ext"));
-
- assertEquals("pathMatch default","",new ServletPathSpec("/*").getPathMatch("/xxx/zzz"));
- }
-
- @Test
- public void testPrefixPathSpec()
- {
- ServletPathSpec spec = new ServletPathSpec("/downloads/*");
- assertEquals("Spec.pathSpec","/downloads/*",spec.getPathSpec());
- assertEquals("Spec.pathDepth",2,spec.getPathDepth());
-
- assertMatches(spec,"/downloads/logo.jpg");
- assertMatches(spec,"/downloads/distribution.tar.gz");
- assertMatches(spec,"/downloads/distribution.tgz");
- assertMatches(spec,"/downloads/distribution.zip");
-
- assertMatches(spec,"/downloads");
-
- assertEquals("Spec.pathInfo","/",spec.getPathInfo("/downloads/"));
- assertEquals("Spec.pathInfo","/distribution.zip",spec.getPathInfo("/downloads/distribution.zip"));
- assertEquals("Spec.pathInfo","/dist/9.0/distribution.tar.gz",spec.getPathInfo("/downloads/dist/9.0/distribution.tar.gz"));
- }
-
- @Test
- public void testSuffixPathSpec()
- {
- ServletPathSpec spec = new ServletPathSpec("*.gz");
- assertEquals("Spec.pathSpec","*.gz",spec.getPathSpec());
- assertEquals("Spec.pathDepth",0,spec.getPathDepth());
-
- assertMatches(spec,"/downloads/distribution.tar.gz");
- assertMatches(spec,"/downloads/jetty.log.gz");
-
- assertNotMatches(spec,"/downloads/distribution.zip");
- assertNotMatches(spec,"/downloads/distribution.tgz");
- assertNotMatches(spec,"/abs/path");
-
- assertEquals("Spec.pathInfo",null,spec.getPathInfo("/downloads/distribution.tar.gz"));
- }
-}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpecTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpecTest.java
index ef84852009..d85d0bb7af 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpecTest.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpecTest.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.*;
import java.util.Map;
+import org.eclipse.jetty.websocket.server.pathmap.PathSpecGroup;
import org.junit.Test;
/**
@@ -60,7 +61,7 @@ public class WebSocketPathSpecTest
assertEquals("Spec.pathSpec","/",spec.getPathSpec());
assertEquals("Spec.pattern","^/$",spec.getPattern().pattern());
assertEquals("Spec.pathDepth",1,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.EXACT,spec.group);
+ assertEquals("Spec.group",PathSpecGroup.EXACT,spec.getGroup());
assertEquals("Spec.variableCount",0,spec.getVariableCount());
assertEquals("Spec.variable.length",0,spec.getVariables().length);
@@ -73,7 +74,7 @@ public class WebSocketPathSpecTest
assertEquals("Spec.pathSpec","/a",spec.getPathSpec());
assertEquals("Spec.pattern","^/a$",spec.getPattern().pattern());
assertEquals("Spec.pathDepth",1,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.EXACT,spec.group);
+ assertEquals("Spec.group",PathSpecGroup.EXACT,spec.getGroup());
assertEquals("Spec.variableCount",0,spec.getVariableCount());
assertEquals("Spec.variable.length",0,spec.getVariables().length);
@@ -86,7 +87,7 @@ public class WebSocketPathSpecTest
assertEquals("Spec.pathSpec","/a/b",spec.getPathSpec());
assertEquals("Spec.pattern","^/a/b$",spec.getPattern().pattern());
assertEquals("Spec.pathDepth",2,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.EXACT,spec.group);
+ assertEquals("Spec.group",PathSpecGroup.EXACT,spec.getGroup());
assertEquals("Spec.variableCount",0,spec.getVariableCount());
assertEquals("Spec.variable.length",0,spec.getVariables().length);
@@ -105,7 +106,7 @@ public class WebSocketPathSpecTest
assertEquals("Spec.pathSpec","/a/{var}/c",spec.getPathSpec());
assertEquals("Spec.pattern","^/a/([^/]+)/c$",spec.getPattern().pattern());
assertEquals("Spec.pathDepth",3,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.MIDDLE_GLOB,spec.group);
+ assertEquals("Spec.group",PathSpecGroup.MIDDLE_GLOB,spec.getGroup());
assertDetectedVars(spec,"var");
@@ -129,7 +130,7 @@ public class WebSocketPathSpecTest
assertEquals("Spec.pathSpec","/a/{foo}",spec.getPathSpec());
assertEquals("Spec.pattern","^/a/([^/]+)$",spec.getPattern().pattern());
assertEquals("Spec.pathDepth",2,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.PREFIX_GLOB,spec.group);
+ assertEquals("Spec.group",PathSpecGroup.PREFIX_GLOB,spec.getGroup());
assertDetectedVars(spec,"foo");
@@ -150,7 +151,7 @@ public class WebSocketPathSpecTest
assertEquals("Spec.pathSpec","/{var}/b/c",spec.getPathSpec());
assertEquals("Spec.pattern","^/([^/]+)/b/c$",spec.getPattern().pattern());
assertEquals("Spec.pathDepth",3,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.SUFFIX_GLOB,spec.group);
+ assertEquals("Spec.group",PathSpecGroup.SUFFIX_GLOB,spec.getGroup());
assertDetectedVars(spec,"var");
@@ -174,7 +175,7 @@ public class WebSocketPathSpecTest
assertEquals("Spec.pathSpec","/a/{var1}/c/{var2}/e",spec.getPathSpec());
assertEquals("Spec.pattern","^/a/([^/]+)/c/([^/]+)/e$",spec.getPattern().pattern());
assertEquals("Spec.pathDepth",5,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.MIDDLE_GLOB,spec.group);
+ assertEquals("Spec.group",PathSpecGroup.MIDDLE_GLOB,spec.getGroup());
assertDetectedVars(spec,"var1","var2");
@@ -197,7 +198,7 @@ public class WebSocketPathSpecTest
assertEquals("Spec.pathSpec","/{var1}/b/{var2}/{var3}",spec.getPathSpec());
assertEquals("Spec.pattern","^/([^/]+)/b/([^/]+)/([^/]+)$",spec.getPattern().pattern());
assertEquals("Spec.pathDepth",4,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.MIDDLE_GLOB,spec.group);
+ assertEquals("Spec.group",PathSpecGroup.MIDDLE_GLOB,spec.getGroup());
assertDetectedVars(spec,"var1","var2","var3");
@@ -221,7 +222,7 @@ public class WebSocketPathSpecTest
assertEquals("Spec.pathSpec","/a/{var1}/{var2}",spec.getPathSpec());
assertEquals("Spec.pattern","^/a/([^/]+)/([^/]+)$",spec.getPattern().pattern());
assertEquals("Spec.pathDepth",3,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.PREFIX_GLOB,spec.group);
+ assertEquals("Spec.group",PathSpecGroup.PREFIX_GLOB,spec.getGroup());
assertDetectedVars(spec,"var1","var2");
@@ -244,7 +245,7 @@ public class WebSocketPathSpecTest
assertEquals("Spec.pathSpec","/{var1}",spec.getPathSpec());
assertEquals("Spec.pattern","^/([^/]+)$",spec.getPattern().pattern());
assertEquals("Spec.pathDepth",1,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.PREFIX_GLOB,spec.group);
+ assertEquals("Spec.group",PathSpecGroup.PREFIX_GLOB,spec.getGroup());
assertDetectedVars(spec,"var1");
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpoint.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpoint.java
new file mode 100644
index 0000000000..761fc0cde4
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpoint.java
@@ -0,0 +1,46 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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.samples.echo;
+
+import javax.websocket.Endpoint;
+import javax.websocket.EndpointConfig;
+import javax.websocket.MessageHandler;
+import javax.websocket.Session;
+
+/**
+ * Example of websocket endpoint based on extending {@link Endpoint}
+ */
+public class BasicEchoEndpoint extends Endpoint implements MessageHandler.Whole<String>
+{
+ private Session session;
+
+ @Override
+ public void onMessage(String msg)
+ {
+ // reply with echo
+ session.getAsyncRemote().sendText(msg);
+ }
+
+ @Override
+ public void onOpen(Session session, EndpointConfig config)
+ {
+ this.session = session;
+ this.session.addMessageHandler(this);
+ }
+}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpointConfigContextListener.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpointConfigContextListener.java
new file mode 100644
index 0000000000..d64057aab8
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpointConfigContextListener.java
@@ -0,0 +1,56 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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.samples.echo;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.websocket.ContainerProvider;
+import javax.websocket.DeploymentException;
+import javax.websocket.Endpoint;
+import javax.websocket.server.ServerContainer;
+import javax.websocket.server.ServerEndpointConfig;
+
+/**
+ * Example of adding a server WebSocket (extending {@link Endpoint}) programmatically via config
+ */
+public class BasicEchoEndpointConfigContextListener implements ServletContextListener
+{
+ @Override
+ public void contextDestroyed(ServletContextEvent sce)
+ {
+ /* do nothing */
+ }
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce)
+ {
+ ServerContainer container = (ServerContainer)ContainerProvider.getWebSocketContainer();
+ // Build up a configuration with a specific path
+ String path = "/echo";
+ ServerEndpointConfig.Builder builder = ServerEndpointConfig.Builder.create(BasicEchoEndpoint.class,path);
+ try
+ {
+ container.addEndpoint(builder.build());
+ }
+ catch (DeploymentException e)
+ {
+ throw new RuntimeException("Unable to add endpoint via config file",e);
+ }
+ }
+}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpointContextListener.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpointContextListener.java
new file mode 100644
index 0000000000..035e386be9
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoEndpointContextListener.java
@@ -0,0 +1,55 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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.samples.echo;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.websocket.ContainerProvider;
+import javax.websocket.DeploymentException;
+import javax.websocket.Endpoint;
+import javax.websocket.server.ServerContainer;
+
+/**
+ * Example of adding a server WebSocket (extending {@link Endpoint}) programmatically directly.
+ * <p>
+ * NOTE: this shouldn't work as the endpoint has no path associated with it.
+ */
+public class BasicEchoEndpointContextListener implements ServletContextListener
+{
+ @Override
+ public void contextDestroyed(ServletContextEvent sce)
+ {
+ /* do nothing */
+ }
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce)
+ {
+ ServerContainer container = (ServerContainer)ContainerProvider.getWebSocketContainer();
+ try
+ {
+ // Should fail as there is no path associated with this endpoint
+ container.addEndpoint(BasicEchoEndpoint.class);
+ }
+ catch (DeploymentException e)
+ {
+ throw new RuntimeException("Unable to add endpoint directly",e);
+ }
+ }
+}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicEchoSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoSocket.java
index fa49975cc4..49a7e2e504 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicEchoSocket.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoSocket.java
@@ -16,12 +16,15 @@
// ========================================================================
//
-package org.eclipse.jetty.websocket.jsr356.server.samples;
+package org.eclipse.jetty.websocket.jsr356.server.samples.echo;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
+/**
+ * Annotated echo socket
+ */
@ServerEndpoint("/echo")
public class BasicEchoSocket
{
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoSocketConfigContextListener.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoSocketConfigContextListener.java
new file mode 100644
index 0000000000..401dd12f6e
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoSocketConfigContextListener.java
@@ -0,0 +1,56 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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.samples.echo;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.websocket.ContainerProvider;
+import javax.websocket.DeploymentException;
+import javax.websocket.server.ServerContainer;
+import javax.websocket.server.ServerEndpointConfig;
+
+/**
+ * Example of adding a server socket (annotated) programmatically via config
+ */
+public class BasicEchoSocketConfigContextListener implements ServletContextListener
+{
+ @Override
+ public void contextDestroyed(ServletContextEvent sce)
+ {
+ /* do nothing */
+ }
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce)
+ {
+ ServerContainer container = (ServerContainer)ContainerProvider.getWebSocketContainer();
+ // Build up a configuration with a specific path
+ // Intentionally using alternate path in config (which differs from @ServerEndpoint declaration)
+ String path = "/echo-alt";
+ ServerEndpointConfig.Builder builder = ServerEndpointConfig.Builder.create(BasicEchoSocket.class,path);
+ try
+ {
+ container.addEndpoint(builder.build());
+ }
+ catch (DeploymentException e)
+ {
+ throw new RuntimeException("Unable to add endpoint via config file",e);
+ }
+ }
+}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoSocketContextListener.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoSocketContextListener.java
new file mode 100644
index 0000000000..9e720d016c
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/BasicEchoSocketContextListener.java
@@ -0,0 +1,51 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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.samples.echo;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.websocket.ContainerProvider;
+import javax.websocket.DeploymentException;
+import javax.websocket.server.ServerContainer;
+
+/**
+ * Example of adding a server socket (annotated) programmatically directly with no config
+ */
+public class BasicEchoSocketContextListener implements ServletContextListener
+{
+ @Override
+ public void contextDestroyed(ServletContextEvent sce)
+ {
+ /* do nothing */
+ }
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce)
+ {
+ ServerContainer container = (ServerContainer)ContainerProvider.getWebSocketContainer();
+ try
+ {
+ container.addEndpoint(BasicEchoSocket.class);
+ }
+ catch (DeploymentException e)
+ {
+ throw new RuntimeException("Unable to add endpoint directly",e);
+ }
+ }
+}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/resources/basic-echo-endpoint-config-web.xml b/jetty-websocket/javax-websocket-server-impl/src/test/resources/basic-echo-endpoint-config-web.xml
new file mode 100644
index 0000000000..afd9cef68d
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/resources/basic-echo-endpoint-config-web.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ metadata-complete="false"
+ version="3.0">
+
+ <listener>
+ <listener-class>org.eclipse.jetty.websocket.jsr356.server.samples.echo.BasicEchoEndpointConfigContextListener</listener-class>
+ </listener>
+</web-app> \ No newline at end of file
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/resources/jetty-logging.properties b/jetty-websocket/javax-websocket-server-impl/src/test/resources/jetty-logging.properties
new file mode 100644
index 0000000000..95a7e3fbed
--- /dev/null
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/resources/jetty-logging.properties
@@ -0,0 +1,7 @@
+org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
+org.eclipse.jetty.LEVEL=WARN
+
+org.eclipse.jetty.websocket.LEVEL=DEBUG
+# org.eclipse.jetty.websocket.LEVEL=WARN
+# org.eclipse.jetty.websocket.common.io.LEVEL=DEBUG
+

Back to the top