Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Bartel2015-12-17 22:26:14 -0500
committerJan Bartel2015-12-17 22:26:14 -0500
commit163a59a18c8c8406a9f0f0f7b701c81335e4624f (patch)
treef6db108f2ec381d261b163464c0c628b445afe89
parent4ce2104a70b8add0767fc2fad4fbd1c3dd40e6e2 (diff)
parent133e9e054d1a6a3a16eb602cbdfd3f86f3c87572 (diff)
downloadorg.eclipse.jetty.project-163a59a18c8c8406a9f0f0f7b701c81335e4624f.tar.gz
org.eclipse.jetty.project-163a59a18c8c8406a9f0f0f7b701c81335e4624f.tar.xz
org.eclipse.jetty.project-163a59a18c8c8406a9f0f0f7b701c81335e4624f.zip
Merge branch 'master' into session-refactor
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpContent.java9
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java2
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java7
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/ResourceHttpContent.java4
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java3
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java58
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ResourceContentFactory.java36
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java2
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ResourceCacheTest.java73
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java13
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java2
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java18
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/listener/ELContextCleaner.java3
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java43
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java16
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHolderTest.java55
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java16
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java45
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/IncludeExclude.java10
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/RegexSet.java2
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java42
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java5
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrPongMessage.java6
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java8
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrHandshakeRequest.java2
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/PathParamServerEndpointConfig.java4
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerContainer.java4
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpec.java347
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/DummyCreator.java4
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappingsTest.java110
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpecBadSpecsTest.java87
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpecTest.java286
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java3
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/MappedWebSocketCreator.java4
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java6
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeHandlerWrapper.java6
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathMappings.java190
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathSpec.java167
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathSpecGroup.java82
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/RegexPathSpec.java157
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/ServletPathSpec.java272
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/PathMappingsBenchmarkTest.java226
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/PathMappingsTest.java119
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/RegexPathSpecTest.java135
-rw-r--r--jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/ServletPathSpecTest.java188
46 files changed, 414 insertions, 2464 deletions
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpContent.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpContent.java
index 7ae190aab2..ec8ab2dc63 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpContent.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpContent.java
@@ -68,6 +68,13 @@ public interface HttpContent
public interface Factory
{
- HttpContent getContent(String path) throws IOException;
+ /**
+ * @param path The path within the context to the resource
+ * @param maxBuffer The maximum buffer to allocated for this request. For cached content, a larger buffer may have
+ * previously been allocated and returned by the {@link HttpContent#getDirectBuffer()} or {@link HttpContent#getIndirectBuffer()} calls.
+ * @return A {@link HttpContent}
+ * @throws IOException
+ */
+ HttpContent getContent(String path,int maxBuffer) throws IOException;
}
}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
index 0c1787b9f5..e265e0146b 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
@@ -638,7 +638,7 @@ public class HttpGenerator
if (values[0]==null)
{
- split = StringUtil.csvSplit(field.getValue());
+ split = StringUtil.csvSplit(field.getValue());
if (split.length>0)
{
values=new HttpHeaderValue[split.length];
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java b/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java
index 448be2e26d..c438b1cd6d 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java
@@ -26,11 +26,10 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
-import java.util.function.BiFunction;
+import java.util.function.Predicate;
import java.util.function.Predicate;
import org.eclipse.jetty.util.ArrayTernaryTrie;
-import org.eclipse.jetty.util.RegexSet;
import org.eclipse.jetty.util.Trie;
import org.eclipse.jetty.util.URIUtil;
@@ -73,8 +72,10 @@ import org.eclipse.jetty.util.URIUtil;
* This class is not synchronized. If concurrent modifications are
* possible then it should be synchronized at a higher level.
*
- * @param <O> the Map.Entry value type
+ * @param <O> the Map.Entry value type
+ * @deprecated replaced with {@link org.eclipse.jetty.http.pathmap.PathMappings} (this class will be removed in Jetty 10)
*/
+@Deprecated
public class PathMap<O> extends HashMap<String,O>
{
/* ------------------------------------------------------------ */
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/ResourceHttpContent.java b/jetty-http/src/main/java/org/eclipse/jetty/http/ResourceHttpContent.java
index 30d7ba5c26..c583ce2e50 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/ResourceHttpContent.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/ResourceHttpContent.java
@@ -125,7 +125,7 @@ public class ResourceHttpContent implements HttpContent
@Override
public ByteBuffer getDirectBuffer()
{
- if (_resource.length()<=0 || _maxBuffer<_resource.length())
+ if (_resource.length()<=0 || _maxBuffer>0 && _maxBuffer<_resource.length())
return null;
try
{
@@ -155,7 +155,7 @@ public class ResourceHttpContent implements HttpContent
@Override
public ByteBuffer getIndirectBuffer()
{
- if (_resource.length()<=0 || _maxBuffer<_resource.length())
+ if (_resource.length()<=0 || _maxBuffer>0 && _maxBuffer<_resource.length())
return null;
try
{
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java
index 108ca0ad6f..ae5efe4ee0 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java
@@ -199,5 +199,8 @@ public class HashLoginService extends AbstractLoginService
protected void doStop() throws Exception
{
super.doStop();
+ if (_propertyUserStore != null)
+ _propertyUserStore.stop();
+ _propertyUserStore = null;
}
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
index df6f65f597..1330a1f80b 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
@@ -787,6 +787,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
}
break;
}
+
ByteBuffer buffer = _channel.useDirectBuffers() ? httpContent.getDirectBuffer() : null;
if (buffer == null)
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java
index a209bf109f..6141c693a1 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java
@@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.util.Comparator;
import java.util.SortedSet;
@@ -172,7 +173,7 @@ public class ResourceCache implements HttpContent.Factory
public HttpContent lookup(String pathInContext)
throws IOException
{
- return getContent(pathInContext);
+ return getContent(pathInContext,_maxCachedFileSize);
}
/* ------------------------------------------------------------ */
@@ -180,6 +181,8 @@ public class ResourceCache implements HttpContent.Factory
* Get either a valid entry object or create a new one if possible.
*
* @param pathInContext The key into the cache
+ * @param maxBuffer The maximum buffer to allocated for this request. For cached content, a larger buffer may have
+ * previously been allocated and returned by the {@link HttpContent#getDirectBuffer()} or {@link HttpContent#getIndirectBuffer()} calls.
* @return The entry matching <code>pathInContext</code>, or a new entry
* if no matching entry was found. If the content exists but is not cachable,
* then a {@link ResourceHttpContent} instance is return. If
@@ -187,7 +190,7 @@ public class ResourceCache implements HttpContent.Factory
* @throws IOException Problem loading the resource
*/
@Override
- public HttpContent getContent(String pathInContext)
+ public HttpContent getContent(String pathInContext,int maxBufferSize)
throws IOException
{
// Is the content in this cache?
@@ -197,14 +200,14 @@ public class ResourceCache implements HttpContent.Factory
// try loading the content from our factory.
Resource resource=_factory.getResource(pathInContext);
- HttpContent loaded = load(pathInContext,resource);
+ HttpContent loaded = load(pathInContext,resource,maxBufferSize);
if (loaded!=null)
return loaded;
// Is the content in the parent cache?
if (_parent!=null)
{
- HttpContent httpContent=_parent.lookup(pathInContext);
+ HttpContent httpContent=_parent.getContent(pathInContext,maxBufferSize);
if (httpContent!=null)
return httpContent;
}
@@ -225,14 +228,13 @@ public class ResourceCache implements HttpContent.Factory
long len = resource.length();
// Will it fit in the cache?
- return (len>0 && len<_maxCachedFileSize && len<_maxCacheSize);
+ return (len>0 && (_useFileMappedBuffer || (len<_maxCachedFileSize && len<_maxCacheSize)));
}
/* ------------------------------------------------------------ */
- private HttpContent load(String pathInContext, Resource resource)
+ private HttpContent load(String pathInContext, Resource resource, int maxBufferSize)
throws IOException
{
-
if (resource==null || !resource.exists())
return null;
@@ -256,7 +258,6 @@ public class ResourceCache implements HttpContent.Factory
if (resourceGz.exists() && resourceGz.lastModified()>=resource.lastModified() && resourceGz.length()<resource.length())
{
contentGz = new CachedHttpContent(pathInContextGz,resourceGz,null);
- shrinkCache();
CachedHttpContent added = _cache.putIfAbsent(pathInContextGz,contentGz);
if (added!=null)
{
@@ -270,9 +271,6 @@ public class ResourceCache implements HttpContent.Factory
else
content = new CachedHttpContent(pathInContext,resource,null);
- // reduce the cache to an acceptable size.
- shrinkCache();
-
// Add it to the cache.
CachedHttpContent added = _cache.putIfAbsent(pathInContext,content);
if (added!=null)
@@ -284,7 +282,7 @@ public class ResourceCache implements HttpContent.Factory
return content;
}
- // Look for a gzip resource or content
+ // Look for non Cacheable gzip resource or content
String mt = _mimeTypes.getMimeByExtension(pathInContext);
if (_gzip)
{
@@ -292,16 +290,16 @@ public class ResourceCache implements HttpContent.Factory
String pathInContextGz=pathInContext+".gz";
CachedHttpContent contentGz = _cache.get(pathInContextGz);
if (contentGz!=null && contentGz.isValid() && contentGz.getResource().lastModified()>=resource.lastModified())
- return new ResourceHttpContent(resource,mt,getMaxCachedFileSize(),contentGz);
+ return new ResourceHttpContent(resource,mt,maxBufferSize,contentGz);
// Is there a gzip resource?
Resource resourceGz=_factory.getResource(pathInContextGz);
if (resourceGz.exists() && resourceGz.lastModified()>=resource.lastModified() && resourceGz.length()<resource.length())
- return new ResourceHttpContent(resource,mt,getMaxCachedFileSize(),
- new ResourceHttpContent(resourceGz,_mimeTypes.getMimeByExtension(pathInContextGz),getMaxCachedFileSize()));
+ return new ResourceHttpContent(resource,mt,maxBufferSize,
+ new ResourceHttpContent(resourceGz,_mimeTypes.getMimeByExtension(pathInContextGz),maxBufferSize));
}
- return new ResourceHttpContent(resource,mt,getMaxCachedFileSize());
+ return new ResourceHttpContent(resource,mt,maxBufferSize);
}
/* ------------------------------------------------------------ */
@@ -359,6 +357,8 @@ public class ResourceCache implements HttpContent.Factory
/* ------------------------------------------------------------ */
protected ByteBuffer getDirectBuffer(Resource resource)
{
+ // Only use file mapped buffers for cached resources, otherwise too much virtual memory commitment for
+ // a non shared resource. Also ignore max buffer size
try
{
if (_useFileMappedBuffer && resource.getFile()!=null && resource.length()<Integer.MAX_VALUE)
@@ -421,8 +421,9 @@ public class ResourceCache implements HttpContent.Factory
_contentLengthValue=exists?(int)resource.length():0;
_contentLength=new PreEncodedHttpField(HttpHeader.CONTENT_LENGTH,Long.toString(_contentLengthValue));
- _cachedSize.addAndGet(_contentLengthValue);
- _cachedFiles.incrementAndGet();
+ if (_cachedFiles.incrementAndGet()>_maxCachedFiles)
+ shrinkCache();
+
_lastAccessed=System.currentTimeMillis();
_etag=ResourceCache.this._etags?new PreEncodedHttpField(HttpHeader.ETAG,resource.getWeakETag()):null;
@@ -487,8 +488,14 @@ public class ResourceCache implements HttpContent.Factory
/* ------------------------------------------------------------ */
protected void invalidate()
{
- // Invalidate it
- _cachedSize.addAndGet(-_contentLengthValue);
+ ByteBuffer indirect=_indirectBuffer.get();
+ if (indirect!=null && _indirectBuffer.compareAndSet(indirect,null))
+ _cachedSize.addAndGet(-BufferUtil.length(indirect));
+
+ ByteBuffer direct=_directBuffer.get();
+ if (direct!=null && !BufferUtil.isMappedBuffer(direct) && _directBuffer.compareAndSet(direct,null))
+ _cachedSize.addAndGet(-BufferUtil.length(direct));
+
_cachedFiles.decrementAndGet();
_resource.close();
}
@@ -507,7 +514,6 @@ public class ResourceCache implements HttpContent.Factory
return _lastModified==null?null:_lastModified.getValue();
}
-
/* ------------------------------------------------------------ */
@Override
public HttpField getContentType()
@@ -569,7 +575,11 @@ public class ResourceCache implements HttpContent.Factory
if (buffer2==null)
LOG.warn("Could not load "+this);
else if (_indirectBuffer.compareAndSet(null,buffer2))
+ {
buffer=buffer2;
+ if (_cachedSize.addAndGet(BufferUtil.length(buffer))>_maxCacheSize)
+ shrinkCache();
+ }
else
buffer=_indirectBuffer.get();
}
@@ -578,7 +588,6 @@ public class ResourceCache implements HttpContent.Factory
return buffer.slice();
}
-
/* ------------------------------------------------------------ */
@Override
public ByteBuffer getDirectBuffer()
@@ -591,7 +600,12 @@ public class ResourceCache implements HttpContent.Factory
if (buffer2==null)
LOG.warn("Could not load "+this);
else if (_directBuffer.compareAndSet(null,buffer2))
+ {
buffer=buffer2;
+
+ if (!BufferUtil.isMappedBuffer(buffer) && _cachedSize.addAndGet(BufferUtil.length(buffer))>_maxCacheSize)
+ shrinkCache();
+ }
else
buffer=_directBuffer.get();
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceContentFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceContentFactory.java
index 2e0edde673..11d8810734 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceContentFactory.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceContentFactory.java
@@ -27,55 +27,47 @@ import org.eclipse.jetty.http.ResourceHttpContent;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceFactory;
+
+/**
+ * A HttpContent.Factory for transient content. The HttpContent's created by
+ * this factory are not intended to be cached, so memory limits for individual
+ * HttpOutput streams are enforced.
+ */
public class ResourceContentFactory implements Factory
{
private final ResourceFactory _factory;
private final MimeTypes _mimeTypes;
- private final int _maxBufferSize;
private final boolean _gzip;
-
/* ------------------------------------------------------------ */
- public ResourceContentFactory(ResourceFactory factory, MimeTypes mimeTypes, int maxBufferSize, boolean gzip)
+ public ResourceContentFactory(ResourceFactory factory, MimeTypes mimeTypes, boolean gzip)
{
_factory=factory;
_mimeTypes=mimeTypes;
- _maxBufferSize=maxBufferSize;
_gzip=gzip;
}
/* ------------------------------------------------------------ */
- /** Get a Entry from the cache.
- * Get either a valid entry object or create a new one if possible.
- *
- * @param pathInContext The key into the cache
- * @return The entry matching <code>pathInContext</code>, or a new entry
- * if no matching entry was found. If the content exists but is not cachable,
- * then a {@link ResourceHttpContent} instance is return. If
- * the resource does not exist, then null is returned.
- * @throws IOException Problem loading the resource
- */
@Override
- public HttpContent getContent(String pathInContext)
+ public HttpContent getContent(String pathInContext,int maxBufferSize)
throws IOException
{
-
// try loading the content from our factory.
Resource resource=_factory.getResource(pathInContext);
- HttpContent loaded = load(pathInContext,resource);
+ HttpContent loaded = load(pathInContext,resource,maxBufferSize);
return loaded;
}
/* ------------------------------------------------------------ */
- private HttpContent load(String pathInContext, Resource resource)
+ private HttpContent load(String pathInContext, Resource resource, int maxBufferSize)
throws IOException
{
if (resource==null || !resource.exists())
return null;
if (resource.isDirectory())
- return new ResourceHttpContent(resource,_mimeTypes.getMimeByExtension(resource.toString()),_maxBufferSize);
+ return new ResourceHttpContent(resource,_mimeTypes.getMimeByExtension(resource.toString()),maxBufferSize);
// Look for a gzip resource or content
String mt = _mimeTypes.getMimeByExtension(pathInContext);
@@ -85,11 +77,11 @@ public class ResourceContentFactory implements Factory
String pathInContextGz=pathInContext+".gz";
Resource resourceGz=_factory.getResource(pathInContextGz);
if (resourceGz.exists() && resourceGz.lastModified()>=resource.lastModified() && resourceGz.length()<resource.length())
- return new ResourceHttpContent(resource,mt,_maxBufferSize,
- new ResourceHttpContent(resourceGz,_mimeTypes.getMimeByExtension(pathInContextGz),_maxBufferSize));
+ return new ResourceHttpContent(resource,mt,maxBufferSize,
+ new ResourceHttpContent(resourceGz,_mimeTypes.getMimeByExtension(pathInContextGz),maxBufferSize));
}
- return new ResourceHttpContent(resource,mt,_maxBufferSize);
+ return new ResourceHttpContent(resource,mt,maxBufferSize);
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java
index da6182604e..9ebec26543 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java
@@ -74,7 +74,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
private final IncludeExclude<String> _agentPatterns=new IncludeExclude<>(RegexSet.class);
private final IncludeExclude<String> _methods = new IncludeExclude<>();
- private final IncludeExclude<String> _paths = new IncludeExclude<String>(PathSpecSet.class);
+ private final IncludeExclude<String> _paths = new IncludeExclude<>(PathSpecSet.class);
private final IncludeExclude<String> _mimeTypes = new IncludeExclude<>();
private HttpField _vary;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResourceCacheTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResourceCacheTest.java
index 67c6e2447f..fb465b8a94 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResourceCacheTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResourceCacheTest.java
@@ -20,6 +20,7 @@ package org.eclipse.jetty.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
import java.io.BufferedReader;
import java.io.File;
@@ -30,6 +31,7 @@ import java.io.OutputStream;
import org.eclipse.jetty.http.HttpContent;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.http.ResourceHttpContent;
+import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
@@ -136,50 +138,83 @@ public class ResourceCacheTest
cache.setMaxCachedFileSize(85);
cache.setMaxCachedFiles(4);
- assertTrue(cache.lookup("does not exist")==null);
- assertTrue(cache.lookup(names[9]) instanceof ResourceHttpContent);
+ assertTrue(cache.getContent("does not exist",4096)==null);
+ assertTrue(cache.getContent(names[9],4096) instanceof ResourceHttpContent);
+ assertTrue(cache.getContent(names[9],4096).getIndirectBuffer()!=null);
HttpContent content;
- content=cache.lookup(names[8]);
+ content=cache.getContent(names[8],4096);
assertTrue(content!=null);
assertEquals(80,content.getContentLengthValue());
-
+ assertEquals(0,cache.getCachedSize());
+
+ if (OS.IS_LINUX)
+ {
+ // Initially not using memory mapped files
+ content.getDirectBuffer();
+ assertEquals(80,cache.getCachedSize());
+
+ // with both types of buffer loaded, this is too large for cache
+ content.getIndirectBuffer();
+ assertEquals(0,cache.getCachedSize());
+ assertEquals(0,cache.getCachedFiles());
+
+ cache=new ResourceCache(null,directory,new MimeTypes(),true,false,false);
+ cache.setMaxCacheSize(95);
+ cache.setMaxCachedFileSize(85);
+ cache.setMaxCachedFiles(4);
+
+ content=cache.getContent(names[8],4096);
+ content.getDirectBuffer();
+ assertEquals(cache.isUseFileMappedBuffer()?0:80,cache.getCachedSize());
+
+ // with both types of buffer loaded, this is not too large for cache because
+ // mapped buffers don't count, so we can continue
+ }
+ content.getIndirectBuffer();
assertEquals(80,cache.getCachedSize());
assertEquals(1,cache.getCachedFiles());
Thread.sleep(200);
- content=cache.lookup(names[1]);
+ content=cache.getContent(names[1],4096);
+ assertEquals(80,cache.getCachedSize());
+ content.getIndirectBuffer();
assertEquals(90,cache.getCachedSize());
assertEquals(2,cache.getCachedFiles());
Thread.sleep(200);
- content=cache.lookup(names[2]);
+ content=cache.getContent(names[2],4096);
+ content.getIndirectBuffer();
assertEquals(30,cache.getCachedSize());
assertEquals(2,cache.getCachedFiles());
Thread.sleep(200);
- content=cache.lookup(names[3]);
+ content=cache.getContent(names[3],4096);
+ content.getIndirectBuffer();
assertEquals(60,cache.getCachedSize());
assertEquals(3,cache.getCachedFiles());
Thread.sleep(200);
- content=cache.lookup(names[4]);
+ content=cache.getContent(names[4],4096);
+ content.getIndirectBuffer();
assertEquals(90,cache.getCachedSize());
assertEquals(3,cache.getCachedFiles());
Thread.sleep(200);
- content=cache.lookup(names[5]);
+ content=cache.getContent(names[5],4096);
+ content.getIndirectBuffer();
assertEquals(90,cache.getCachedSize());
assertEquals(2,cache.getCachedFiles());
Thread.sleep(200);
- content=cache.lookup(names[6]);
+ content=cache.getContent(names[6],4096);
+ content.getIndirectBuffer();
assertEquals(60,cache.getCachedSize());
assertEquals(1,cache.getCachedFiles());
@@ -189,37 +224,43 @@ public class ResourceCacheTest
{
out.write(' ');
}
- content=cache.lookup(names[7]);
+ content=cache.getContent(names[7],4096);
+ content.getIndirectBuffer();
assertEquals(70,cache.getCachedSize());
assertEquals(1,cache.getCachedFiles());
Thread.sleep(200);
- content=cache.lookup(names[6]);
+ content=cache.getContent(names[6],4096);
+ content.getIndirectBuffer();
assertEquals(71,cache.getCachedSize());
assertEquals(2,cache.getCachedFiles());
Thread.sleep(200);
- content=cache.lookup(names[0]);
+ content=cache.getContent(names[0],4096);
+ content.getIndirectBuffer();
assertEquals(72,cache.getCachedSize());
assertEquals(3,cache.getCachedFiles());
Thread.sleep(200);
- content=cache.lookup(names[1]);
+ content=cache.getContent(names[1],4096);
+ content.getIndirectBuffer();
assertEquals(82,cache.getCachedSize());
assertEquals(4,cache.getCachedFiles());
Thread.sleep(200);
- content=cache.lookup(names[2]);
+ content=cache.getContent(names[2],4096);
+ content.getIndirectBuffer();
assertEquals(32,cache.getCachedSize());
assertEquals(4,cache.getCachedFiles());
Thread.sleep(200);
- content=cache.lookup(names[3]);
+ content=cache.getContent(names[3],4096);
+ content.getIndirectBuffer();
assertEquals(61,cache.getCachedSize());
assertEquals(4,cache.getCachedFiles());
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java
index 90b641c8fa..a5182fe13c 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java
@@ -289,8 +289,15 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
throw new UnavailableException(e.toString());
}
- _contentFactory=_cache==null?new ResourceContentFactory(this,_mimeTypes,-1,_gzip):_cache; // TODO pass a buffer size
-
+ if (_cache!=null)
+ _contentFactory=_cache;
+ else
+ {
+ _contentFactory=new ResourceContentFactory(this,_mimeTypes,_gzip);
+ if (resourceCache!=null)
+ _servletContext.setAttribute(resourceCache,_contentFactory);
+ }
+
_gzipEquivalentFileExtensions = new ArrayList<String>();
String otherGzipExtensions = getInitParameter("otherGzipFileExtensions");
if (otherGzipExtensions != null)
@@ -461,7 +468,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
try
{
// Find the content
- content=_contentFactory.getContent(pathInContext);
+ content=_contentFactory.getContent(pathInContext,response.getBufferSize());
if (LOG.isDebugEnabled())
LOG.info("content={}",content);
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
index ebafc965b2..d7accdf6d6 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
@@ -53,6 +53,8 @@ import org.eclipse.jetty.http.pathmap.MappedResource;
import org.eclipse.jetty.http.pathmap.PathMappings;
import org.eclipse.jetty.http.pathmap.PathSpec;
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
+import org.eclipse.jetty.http.pathmap.PathSpec;
+import org.eclipse.jetty.http.pathmap.ServletPathSpec;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.Request;
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
index b9519021a0..36ab05fa6d 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
@@ -207,15 +207,29 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
{
if (sh==this)
return 0;
+
if (sh._initOrder<_initOrder)
return 1;
+
if (sh._initOrder>_initOrder)
return -1;
- int c=(_className!=null && sh._className!=null)?_className.compareTo(sh._className):0;
+ // consider _className, need to position properly when one is configured but not the other
+ int c;
+ if (_className==null && sh._className==null)
+ c=0;
+ else if (_className==null)
+ c=-1;
+ else if (sh._className==null)
+ c=1;
+ else
+ c=_className.compareTo(sh._className);
+
+ // if _initOrder and _className are the same, consider the _name
if (c==0)
c=_name.compareTo(sh._name);
- return c;
+
+ return c;
}
/* ------------------------------------------------------------ */
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/listener/ELContextCleaner.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/listener/ELContextCleaner.java
index 40303b1c26..821c926ca9 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/listener/ELContextCleaner.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/listener/ELContextCleaner.java
@@ -20,6 +20,7 @@ package org.eclipse.jetty.servlet.listener;
import java.lang.reflect.Field;
import java.util.Iterator;
+import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletContextEvent;
@@ -98,7 +99,7 @@ public class ELContextCleaner implements ServletContextListener
if (!properties.isAccessible())
properties.setAccessible(true);
- ConcurrentHashMap<Class<?>, Object> map = (ConcurrentHashMap<Class<?>, Object>) properties.get(null);
+ Map map = (Map) properties.get(null);
if (map == null)
return;
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java
index 0f740d9da9..13a54837e5 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -39,8 +40,10 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.eclipse.jetty.http.DateGenerator;
+import org.eclipse.jetty.http.HttpContent;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.LocalConnector;
+import org.eclipse.jetty.server.ResourceContentFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker;
import org.eclipse.jetty.toolchain.test.FS;
@@ -48,6 +51,7 @@ 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.IO;
+import org.eclipse.jetty.util.resource.Resource;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Assert;
@@ -522,6 +526,45 @@ public class DefaultServletTest
}
@Test
+ public void testDirectFromResourceHttpContent() throws Exception
+ {
+ if (!OS.IS_LINUX)
+ return;
+
+ testdir.ensureEmpty();
+ File resBase = testdir.getPathFile("docroot").toFile();
+ FS.ensureDirExists(resBase);
+ context.setBaseResource(Resource.newResource(resBase));
+
+ File index = new File(resBase, "index.html");
+ createFile(index, "<h1>Hello World</h1>");
+
+ ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
+ defholder.setInitParameter("dirAllowed", "true");
+ defholder.setInitParameter("redirectWelcome", "false");
+ defholder.setInitParameter("useFileMappedBuffer", "true");
+ defholder.setInitParameter("welcomeServlets", "exact");
+ defholder.setInitParameter("gzip", "false");
+ defholder.setInitParameter("resourceCache","resourceCache");
+
+ String response;
+
+ response = connector.getResponses("GET /context/index.html HTTP/1.0\r\n\r\n");
+ assertResponseContains("<h1>Hello World</h1>", response);
+
+ ResourceContentFactory factory = (ResourceContentFactory)context.getServletContext().getAttribute("resourceCache");
+
+ HttpContent content = factory.getContent("/index.html",200);
+ ByteBuffer buffer = content.getDirectBuffer();
+ Assert.assertTrue(buffer.isDirect());
+ content = factory.getContent("/index.html",5);
+ buffer = content.getDirectBuffer();
+ Assert.assertTrue(buffer==null);
+ }
+
+
+
+ @Test
public void testRangeRequests() throws Exception
{
testdir.ensureEmpty();
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java
index 3ba305d8da..9cc9696a3c 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java
@@ -18,7 +18,10 @@
package org.eclipse.jetty.servlet;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
@@ -26,6 +29,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
+import java.util.Arrays;
import java.util.zip.GZIPInputStream;
import javax.servlet.ServletException;
@@ -198,4 +202,16 @@ public class GzipHandlerTest
assertEquals(__icontent, testOut.toString("UTF8"));
}
+
+ @Test
+ public void testAddGetPaths()
+ {
+ GzipHandler gzip = new GzipHandler();
+ gzip.addIncludedPaths("/foo");
+ gzip.addIncludedPaths("^/bar.*$");
+
+ String[] includedPaths = gzip.getIncludedPaths();
+ assertThat("Included Paths.size", includedPaths.length, is(2));
+ assertThat("Included Paths", Arrays.asList(includedPaths), contains("/foo","^/bar.*$"));
+ }
}
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHolderTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHolderTest.java
new file mode 100644
index 0000000000..7ec8c17277
--- /dev/null
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHolderTest.java
@@ -0,0 +1,55 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.servlet;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+public class ServletHolderTest {
+
+ @Test
+ public void testTransitiveCompareTo() throws Exception
+ {
+ // example of jsp-file referenced in web.xml
+ final ServletHolder one = new ServletHolder();
+ one.setInitOrder(-1);
+ one.setName("Login");
+ one.setClassName(null);
+
+ // example of pre-compiled jsp
+ final ServletHolder two = new ServletHolder();
+ two.setInitOrder(-1);
+ two.setName("org.my.package.jsp.WEB_002dINF.pages.precompiled_002dpage_jsp");
+ two.setClassName("org.my.package.jsp.WEB_002dINF.pages.precompiled_002dpage_jsp");
+
+ // example of servlet referenced in web.xml
+ final ServletHolder three = new ServletHolder();
+ three.setInitOrder(-1);
+ three.setName("Download");
+ three.setClassName("org.my.package.web.DownloadServlet");
+
+ // verify compareTo transitivity
+ Assert.assertTrue(one.compareTo(two) < 0);
+ Assert.assertTrue(two.compareTo(three) < 0);
+ Assert.assertTrue(one.compareTo(three) < 0);
+ }
+}
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java
index 8a13382865..aad404d5db 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java
@@ -1107,10 +1107,10 @@ public class DoSFilter implements Filter
{
private static final long serialVersionUID = 3534663738034577872L;
- protected transient final String _id;
- protected transient final int _type;
- protected transient final long[] _timestamps;
- protected transient int _next;
+ protected final String _id;
+ protected final int _type;
+ protected final long[] _timestamps;
+ protected int _next;
public RateTracker(String id, int type, int maxRequestsPerSecond)
{
@@ -1164,16 +1164,14 @@ public class DoSFilter implements Filter
public void sessionWillPassivate(HttpSessionEvent se)
{
//take the tracker of the list of trackers (if its still there)
- //and ensure that we take ourselves out of the session so we are not saved
_rateTrackers.remove(_id);
- se.getSession().removeAttribute(__TRACKER);
- if (LOG.isDebugEnabled())
- LOG.debug("Value removed: {}", getId());
}
public void sessionDidActivate(HttpSessionEvent se)
{
- LOG.warn("Unexpected session activation");
+ RateTracker tracker = (RateTracker)se.getSession().getAttribute(__TRACKER);
+ if (tracker!=null)
+ _rateTrackers.put(tracker.getId(),tracker);
}
@Override
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java
index 49377144e1..fa1ef983ab 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java
@@ -19,17 +19,21 @@
package org.eclipse.jetty.util;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
+import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import org.eclipse.jetty.util.log.Log;
@@ -903,12 +907,48 @@ public class BufferUtil
public static ByteBuffer toMappedBuffer(File file) throws IOException
{
- try (RandomAccessFile raf = new RandomAccessFile(file, "r"))
+ try (FileChannel channel = FileChannel.open(file.toPath(),StandardOpenOption.READ))
{
- return raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length());
+ return channel.map(MapMode.READ_ONLY, 0, file.length());
}
}
+ static final Field fdMappedByteBuffer;
+ static
+ {
+ Field fd = null;
+ try
+ {
+ fd=MappedByteBuffer.class.getDeclaredField("fd");
+ fd.setAccessible(true);
+ }
+ catch(Exception e)
+ {
+ }
+ fdMappedByteBuffer=fd;
+ }
+
+ public static boolean isMappedBuffer(ByteBuffer buffer)
+ {
+ if (!(buffer instanceof MappedByteBuffer))
+ return false;
+ MappedByteBuffer mapped = (MappedByteBuffer) buffer;
+
+ if (fdMappedByteBuffer!=null)
+ {
+ try
+ {
+ if (fdMappedByteBuffer.get(mapped) instanceof FileDescriptor)
+ return true;
+ }
+ catch(Exception e)
+ {
+ }
+ }
+ return false;
+ }
+
+
public static ByteBuffer toBuffer(Resource resource,boolean direct) throws IOException
{
int len=(int)resource.length();
@@ -1156,4 +1196,5 @@ public class BufferUtil
+
}
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/IncludeExclude.java b/jetty-util/src/main/java/org/eclipse/jetty/util/IncludeExclude.java
index 03cf0553a1..340761d99f 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/IncludeExclude.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/IncludeExclude.java
@@ -35,8 +35,8 @@ import java.util.function.Predicate;
public class IncludeExclude<ITEM>
{
private final Set<ITEM> _includes;
- private final Set<ITEM> _excludes;
private final Predicate<ITEM> _includePredicate;
+ private final Set<ITEM> _excludes;
private final Predicate<ITEM> _excludePredicate;
private static class SetContainsPredicate<ITEM> implements Predicate<ITEM>
@@ -58,6 +58,7 @@ public class IncludeExclude<ITEM>
/**
* Default constructor over {@link HashSet}
*/
+ @SuppressWarnings("unchecked")
public IncludeExclude()
{
this(HashSet.class);
@@ -68,17 +69,20 @@ public class IncludeExclude<ITEM>
* @param setClass The type of {@link Set} to using internally
* @param predicate A predicate function to test if a passed ITEM is matched by the passed SET}
*/
+ @SuppressWarnings("unchecked")
public <SET extends Set<ITEM>> IncludeExclude(Class<SET> setClass)
{
try
{
_includes = setClass.newInstance();
_excludes = setClass.newInstance();
+
if(_includes instanceof Predicate) {
_includePredicate = (Predicate<ITEM>)_includes;
} else {
_includePredicate = new SetContainsPredicate<>(_includes);
}
+
if(_excludes instanceof Predicate) {
_excludePredicate = (Predicate<ITEM>)_excludes;
} else {
@@ -112,7 +116,7 @@ public class IncludeExclude<ITEM>
_includes.add(element);
}
- public void include(ITEM... element)
+ public void include(@SuppressWarnings("unchecked") ITEM... element)
{
for (ITEM e: element)
_includes.add(e);
@@ -123,7 +127,7 @@ public class IncludeExclude<ITEM>
_excludes.add(element);
}
- public void exclude(ITEM... element)
+ public void exclude(@SuppressWarnings("unchecked") ITEM... element)
{
for (ITEM e: element)
_excludes.add(e);
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/RegexSet.java b/jetty-util/src/main/java/org/eclipse/jetty/util/RegexSet.java
index c8db063fd7..ca5a0305d8 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/RegexSet.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/RegexSet.java
@@ -23,11 +23,9 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
-import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.regex.Pattern;
-
/**
* A Set of Regular expressions strings.
* <p>
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java
index d2f8b24bec..9e44393d7c 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/BufferUtilTest.java
@@ -21,13 +21,20 @@ package org.eclipse.jetty.util;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileWriter;
import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileChannel.MapMode;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.OpenOption;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
@@ -335,4 +342,39 @@ public class BufferUtilTest
BufferUtil.writeTo(buffer.asReadOnlyBuffer(), out);
assertThat("Bytes in out equal bytes in buffer", Arrays.equals(bytes, out.toByteArray()), is(true));
}
+
+ @Test
+ public void testMappedFile() throws Exception
+ {
+ String data="Now is the time for all good men to come to the aid of the party";
+ File file = File.createTempFile("test",".txt");
+ file.deleteOnExit();
+ try(FileWriter out = new FileWriter(file);)
+ {
+ out.write(data);
+ }
+
+ ByteBuffer mapped = BufferUtil.toMappedBuffer(file);
+ assertEquals(data,BufferUtil.toString(mapped));
+ assertTrue(BufferUtil.isMappedBuffer(mapped));
+
+ ByteBuffer direct = BufferUtil.allocateDirect(data.length());
+ direct.clear();
+ direct.put(data.getBytes(StandardCharsets.ISO_8859_1));
+ direct.flip();
+ assertEquals(data,BufferUtil.toString(direct));
+ assertFalse(BufferUtil.isMappedBuffer(direct));
+
+ ByteBuffer slice = direct.slice();
+ assertEquals(data,BufferUtil.toString(slice));
+ assertFalse(BufferUtil.isMappedBuffer(slice));
+
+ ByteBuffer duplicate = direct.duplicate();
+ assertEquals(data,BufferUtil.toString(duplicate));
+ assertFalse(BufferUtil.isMappedBuffer(duplicate));
+
+ ByteBuffer readonly = direct.asReadOnlyBuffer();
+ assertEquals(data,BufferUtil.toString(readonly));
+ assertFalse(BufferUtil.isMappedBuffer(readonly));
+ }
}
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java
index 898288d58f..c23742795c 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java
@@ -32,12 +32,15 @@ import java.security.KeyStore;
import javax.net.ssl.SSLEngine;
+import org.eclipse.jetty.toolchain.test.JDK;
+import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.StdErrLog;
import org.eclipse.jetty.util.resource.Resource;
import org.hamcrest.Matchers;
import org.junit.Assert;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
@@ -207,6 +210,8 @@ public class SslContextFactoryTest
public void testSetIncludeCipherSuitesRegex() throws Exception
{
cf.setIncludeCipherSuites(".*ECDHE.*",".*WIBBLE.*");
+ Assume.assumeFalse(JDK.IS_8);
+
cf.start();
SSLEngine sslEngine = cf.newSSLEngine();
String[] enabledCipherSuites = sslEngine.getEnabledCipherSuites();
diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrPongMessage.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrPongMessage.java
index 961329a113..e3458b7762 100644
--- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrPongMessage.java
+++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrPongMessage.java
@@ -22,6 +22,8 @@ import java.nio.ByteBuffer;
import javax.websocket.PongMessage;
+import org.eclipse.jetty.util.BufferUtil;
+
public class JsrPongMessage implements PongMessage
{
private final ByteBuffer data;
@@ -34,6 +36,10 @@ public class JsrPongMessage implements PongMessage
@Override
public ByteBuffer getApplicationData()
{
+ if (data == null)
+ {
+ return BufferUtil.EMPTY_BUFFER;
+ }
return data.slice();
}
}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java
index 60016f4d1d..6954cb01d2 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java
@@ -29,6 +29,8 @@ import javax.websocket.Extension.Parameter;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;
+import org.eclipse.jetty.http.pathmap.PathSpec;
+import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -37,8 +39,6 @@ import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.jsr356.JsrExtension;
import org.eclipse.jetty.websocket.jsr356.endpoints.EndpointInstance;
-import org.eclipse.jetty.websocket.jsr356.server.pathmap.WebSocketPathSpec;
-import org.eclipse.jetty.websocket.server.pathmap.PathSpec;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
@@ -148,10 +148,10 @@ public class JsrCreator implements WebSocketCreator
// Do not decorate here (let the Connection and Session start first)
// This will allow CDI to see Session for injection into Endpoint classes.
PathSpec pathSpec = hsreq.getRequestPathSpec();
- if (pathSpec instanceof WebSocketPathSpec)
+ if (pathSpec instanceof UriTemplatePathSpec)
{
// We have a PathParam path spec
- WebSocketPathSpec wspathSpec = (WebSocketPathSpec)pathSpec;
+ UriTemplatePathSpec wspathSpec = (UriTemplatePathSpec)pathSpec;
String requestPath = req.getRequestPath();
// Wrap the config with the path spec information
config = new PathParamServerEndpointConfig(containerScope,config,wspathSpec,requestPath);
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
index 6db246d801..023b676531 100644
--- 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
@@ -25,7 +25,7 @@ import java.util.Map;
import javax.websocket.server.HandshakeRequest;
-import org.eclipse.jetty.websocket.server.pathmap.PathSpec;
+import org.eclipse.jetty.http.pathmap.PathSpec;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
public class JsrHandshakeRequest implements HandshakeRequest
diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/PathParamServerEndpointConfig.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/PathParamServerEndpointConfig.java
index d709a0039a..a4bcb3b8e1 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/PathParamServerEndpointConfig.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/PathParamServerEndpointConfig.java
@@ -23,8 +23,8 @@ import java.util.Map;
import javax.websocket.server.ServerEndpointConfig;
+import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
-import org.eclipse.jetty.websocket.jsr356.server.pathmap.WebSocketPathSpec;
/**
* Wrapper for a {@link ServerEndpointConfig} where there PathParm information from the incoming request.
@@ -33,7 +33,7 @@ public class PathParamServerEndpointConfig extends BasicServerEndpointConfig imp
{
private final Map<String, String> pathParamMap;
- public PathParamServerEndpointConfig(WebSocketContainerScope containerScope, ServerEndpointConfig config, WebSocketPathSpec pathSpec, String requestPath)
+ public PathParamServerEndpointConfig(WebSocketContainerScope containerScope, ServerEndpointConfig config, UriTemplatePathSpec pathSpec, String requestPath)
{
super(containerScope, config);
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 7fdba0426d..dba7a88567 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
@@ -27,6 +27,7 @@ import javax.websocket.Endpoint;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
+import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
@@ -35,7 +36,6 @@ import org.eclipse.jetty.websocket.jsr356.JsrSessionFactory;
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
import org.eclipse.jetty.websocket.jsr356.endpoints.EndpointInstance;
import org.eclipse.jetty.websocket.jsr356.metadata.EndpointMetadata;
-import org.eclipse.jetty.websocket.jsr356.server.pathmap.WebSocketPathSpec;
import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
@@ -99,7 +99,7 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
private void addEndpoint(ServerEndpointMetadata metadata) throws DeploymentException
{
JsrCreator creator = new JsrCreator(this,metadata,webSocketServerFactory.getExtensionFactory());
- mappedCreator.addMapping(new WebSocketPathSpec(metadata.getPath()),creator);
+ mappedCreator.addMapping(new UriTemplatePathSpec(metadata.getPath()),creator);
}
@Override
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
deleted file mode 100644
index 014466a60e..0000000000
--- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpec.java
+++ /dev/null
@@ -1,347 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.jsr356.server.pathmap;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-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.util.TypeUtil;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-import org.eclipse.jetty.websocket.server.pathmap.PathSpecGroup;
-import org.eclipse.jetty.websocket.server.pathmap.RegexPathSpec;
-
-/**
- * PathSpec for WebSocket &#064;{@link ServerEndpoint} declarations with support for URI templates and &#064;{@link PathParam} annotations
- *
- * @see javax.websocket spec (JSR-356) Section 3.1.1 URI Mapping
- * @see <a href="https://tools.ietf.org/html/rfc6570">URI Templates (Level 1)</a>
- */
-public class WebSocketPathSpec extends RegexPathSpec
-{
- private static final Logger LOG = Log.getLogger(WebSocketPathSpec.class);
-
- private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\{(.*)\\}");
- /** Reserved Symbols in URI Template variable */
- private static final String VARIABLE_RESERVED = ":/?#[]@" + // gen-delims
- "!$&'()*+,;="; // sub-delims
- /** Allowed Symboles in a URI Template variable */
- private static final String VARIABLE_SYMBOLS="-._";
- private static final Set<String> FORBIDDEN_SEGMENTS;
-
- static
- {
- FORBIDDEN_SEGMENTS = new HashSet<>();
- FORBIDDEN_SEGMENTS.add("/./");
- FORBIDDEN_SEGMENTS.add("/../");
- FORBIDDEN_SEGMENTS.add("//");
- }
-
- private String variables[];
-
- public WebSocketPathSpec(String pathParamSpec)
- {
- super();
- Objects.requireNonNull(pathParamSpec,"Path Param Spec cannot be null");
-
- if ("".equals(pathParamSpec) || "/".equals(pathParamSpec))
- {
- super.pathSpec = "/";
- super.pattern = Pattern.compile("^/$");
- super.pathDepth = 1;
- this.specLength = 1;
- this.variables = new String[0];
- this.group = PathSpecGroup.EXACT;
- return;
- }
-
- if (pathParamSpec.charAt(0) != '/')
- {
- // path specs must start with '/'
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: path spec \"");
- err.append(pathParamSpec);
- err.append("\" must start with '/'");
- throw new IllegalArgumentException(err.toString());
- }
-
- for (String forbidden : FORBIDDEN_SEGMENTS)
- {
- if (pathParamSpec.contains(forbidden))
- {
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: segment ");
- err.append(forbidden);
- err.append(" is forbidden in path spec: ");
- err.append(pathParamSpec);
- throw new IllegalArgumentException(err.toString());
- }
- }
-
- this.pathSpec = pathParamSpec;
-
- StringBuilder regex = new StringBuilder();
- regex.append('^');
-
- List<String> varNames = new ArrayList<>();
- // split up into path segments (ignoring the first slash that will always be empty)
- String segments[] = pathParamSpec.substring(1).split("/");
- char segmentSignature[] = new char[segments.length];
- this.pathDepth = segments.length;
- for (int i = 0; i < segments.length; i++)
- {
- String segment = segments[i];
- Matcher mat = VARIABLE_PATTERN.matcher(segment);
-
- if (mat.matches())
- {
- // entire path segment is a variable.
- String variable = mat.group(1);
- if (varNames.contains(variable))
- {
- // duplicate variable names
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: variable ");
- err.append(variable);
- err.append(" is duplicated in path spec: ");
- err.append(pathParamSpec);
- throw new IllegalArgumentException(err.toString());
- }
-
- assertIsValidVariableLiteral(variable);
-
- segmentSignature[i] = 'v'; // variable
- // valid variable name
- varNames.add(variable);
- // build regex
- regex.append("/([^/]+)");
- }
- else if (mat.find(0))
- {
- // variable exists as partial segment
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: variable ");
- err.append(mat.group());
- err.append(" must exist as entire path segment: ");
- err.append(pathParamSpec);
- throw new IllegalArgumentException(err.toString());
- }
- else if ((segment.indexOf('{') >= 0) || (segment.indexOf('}') >= 0))
- {
- // variable is split with a path separator
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: invalid path segment /");
- err.append(segment);
- err.append("/ variable declaration incomplete: ");
- err.append(pathParamSpec);
- throw new IllegalArgumentException(err.toString());
- }
- else if (segment.indexOf('*') >= 0)
- {
- // glob segment
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: path segment /");
- err.append(segment);
- err.append("/ contains a wildcard symbol (not supported by javax.websocket): ");
- err.append(pathParamSpec);
- throw new IllegalArgumentException(err.toString());
- }
- else
- {
- // valid path segment
- segmentSignature[i] = 'e'; // exact
- // build regex
- regex.append('/');
- // escape regex special characters
- for (char c : segment.toCharArray())
- {
- if ((c == '.') || (c == '[') || (c == ']') || (c == '\\'))
- {
- regex.append('\\');
- }
- regex.append(c);
- }
- }
- }
-
- // Handle trailing slash (which is not picked up during split)
- if(pathParamSpec.charAt(pathParamSpec.length()-1) == '/')
- {
- regex.append('/');
- }
-
- regex.append('$');
-
- this.pattern = Pattern.compile(regex.toString());
-
- int varcount = varNames.size();
- this.variables = varNames.toArray(new String[varcount]);
-
- // Convert signature to group
- String sig = String.valueOf(segmentSignature);
-
- if (Pattern.matches("^e*$",sig))
- {
- this.group = PathSpecGroup.EXACT;
- }
- else if (Pattern.matches("^e*v+",sig))
- {
- this.group = PathSpecGroup.PREFIX_GLOB;
- }
- else if (Pattern.matches("^v+e+",sig))
- {
- this.group = PathSpecGroup.SUFFIX_GLOB;
- }
- else
- {
- this.group = PathSpecGroup.MIDDLE_GLOB;
- }
- }
-
- /**
- * Validate variable literal name, per RFC6570, Section 2.1 Literals
- * @param variable
- * @param pathParamSpec
- */
- private void assertIsValidVariableLiteral(String variable)
- {
- int len = variable.length();
-
- int i = 0;
- int codepoint;
- boolean valid = (len > 0); // must not be zero length
-
- while (valid && i < len)
- {
- codepoint = variable.codePointAt(i);
- i += Character.charCount(codepoint);
-
- // basic letters, digits, or symbols
- if (isValidBasicLiteralCodepoint(codepoint))
- {
- continue;
- }
-
- // The ucschar and iprivate pieces
- if (Character.isSupplementaryCodePoint(codepoint))
- {
- continue;
- }
-
- // pct-encoded
- if (codepoint == '%')
- {
- if (i + 2 > len)
- {
- // invalid percent encoding, missing extra 2 chars
- valid = false;
- continue;
- }
- codepoint = TypeUtil.convertHexDigit(variable.codePointAt(i++)) << 4;
- codepoint |= TypeUtil.convertHexDigit(variable.codePointAt(i++));
-
- // validate basic literal
- if (isValidBasicLiteralCodepoint(codepoint))
- {
- continue;
- }
- }
-
- valid = false;
- }
-
- if (!valid)
- {
- // invalid variable name
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: variable {");
- err.append(variable);
- err.append("} an invalid variable name: ");
- err.append(pathSpec);
- throw new IllegalArgumentException(err.toString());
- }
- }
-
- private boolean isValidBasicLiteralCodepoint(int codepoint)
- {
- // basic letters or digits
- if((codepoint >= 'a' && codepoint <= 'z') ||
- (codepoint >= 'A' && codepoint <= 'Z') ||
- (codepoint >= '0' && codepoint <= '9'))
- {
- return true;
- }
-
- // basic allowed symbols
- if(VARIABLE_SYMBOLS.indexOf(codepoint) >= 0)
- {
- return true; // valid simple value
- }
-
- // basic reserved symbols
- if(VARIABLE_RESERVED.indexOf(codepoint) >= 0)
- {
- LOG.warn("Detected URI Template reserved symbol [{}] in path spec \"{}\"",(char)codepoint,pathSpec);
- return false; // valid simple value
- }
-
- return false;
- }
-
- public Map<String, String> getPathParams(String path)
- {
- Matcher matcher = getMatcher(path);
- if (matcher.matches())
- {
- if (group == PathSpecGroup.EXACT)
- {
- return Collections.emptyMap();
- }
- Map<String, String> ret = new HashMap<>();
- int groupCount = matcher.groupCount();
- for (int i = 1; i <= groupCount; i++)
- {
- ret.put(this.variables[i - 1],matcher.group(i));
- }
- return ret;
- }
- return null;
- }
-
- public int getVariableCount()
- {
- return variables.length;
- }
-
- public String[] getVariables()
- {
- return this.variables;
- }
-}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/DummyCreator.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/DummyCreator.java
index d3e5553766..e1d5ca7710 100644
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/DummyCreator.java
+++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/DummyCreator.java
@@ -18,9 +18,9 @@
package org.eclipse.jetty.websocket.jsr356.server;
+import org.eclipse.jetty.http.pathmap.PathMappings;
+import org.eclipse.jetty.http.pathmap.PathSpec;
import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
-import org.eclipse.jetty.websocket.server.pathmap.PathMappings;
-import org.eclipse.jetty.websocket.server.pathmap.PathSpec;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
public class DummyCreator implements MappedWebSocketCreator
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
deleted file mode 100644
index 3196b0c5d5..0000000000
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/PathMappingsTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.jsr356.server.pathmap;
-
-import static org.hamcrest.Matchers.notNullValue;
-
-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;
-
-public class PathMappingsTest
-{
- private void assertMatch(PathMappings<String> pathmap, String path, String expectedValue)
- {
- String msg = String.format(".getMatch(\"%s\")",path);
- MappedResource<String> match = pathmap.getMatch(path);
- Assert.assertThat(msg,match,notNullValue());
- String actualMatch = match.getResource();
- Assert.assertEquals(msg,expectedValue,actualMatch);
- }
-
- public void dumpMappings(PathMappings<String> p)
- {
- for (MappedResource<String> res : p)
- {
- System.out.printf(" %s%n",res);
- }
- }
-
- /**
- * Test the match order rules with a mixed Servlet and WebSocket path specs
- * <p>
- * <ul>
- * <li>Exact match</li>
- * <li>Longest prefix match</li>
- * <li>Longest suffix match</li>
- * </ul>
- */
- @Test
- public void testMixedMatchOrder()
- {
- PathMappings<String> p = new PathMappings<>();
-
- p.put(new ServletPathSpec("/"),"default");
- p.put(new ServletPathSpec("/animal/bird/*"),"birds");
- p.put(new ServletPathSpec("/animal/fish/*"),"fishes");
- p.put(new ServletPathSpec("/animal/*"),"animals");
- p.put(new WebSocketPathSpec("/animal/{type}/{name}/chat"),"animalChat");
- p.put(new WebSocketPathSpec("/animal/{type}/{name}/cam"),"animalCam");
- p.put(new WebSocketPathSpec("/entrance/cam"),"entranceCam");
-
- // dumpMappings(p);
-
- assertMatch(p,"/animal/bird/eagle","birds");
- assertMatch(p,"/animal/fish/bass/sea","fishes");
- assertMatch(p,"/animal/peccary/javalina/evolution","animals");
- assertMatch(p,"/","default");
- assertMatch(p,"/animal/bird/eagle/chat","animalChat");
- assertMatch(p,"/animal/bird/penguin/chat","animalChat");
- assertMatch(p,"/animal/fish/trout/cam","animalCam");
- assertMatch(p,"/entrance/cam","entranceCam");
- }
-
- /**
- * Test the match order rules imposed by the WebSocket API (JSR-356)
- * <p>
- * <ul>
- * <li>Exact match</li>
- * <li>Longest prefix match</li>
- * <li>Longest suffix match</li>
- * </ul>
- */
- @Test
- public void testWebsocketMatchOrder()
- {
- PathMappings<String> p = new PathMappings<>();
-
- p.put(new WebSocketPathSpec("/a/{var}/c"),"endpointA");
- p.put(new WebSocketPathSpec("/a/b/c"),"endpointB");
- p.put(new WebSocketPathSpec("/a/{var1}/{var2}"),"endpointC");
- p.put(new WebSocketPathSpec("/{var1}/d"),"endpointD");
- p.put(new WebSocketPathSpec("/b/{var2}"),"endpointE");
-
- // dumpMappings(p);
-
- assertMatch(p,"/a/b/c","endpointB");
- assertMatch(p,"/a/d/c","endpointA");
- assertMatch(p,"/a/x/y","endpointC");
-
- assertMatch(p,"/b/d","endpointE");
- }
-}
diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpecBadSpecsTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpecBadSpecsTest.java
deleted file mode 100644
index efc6af2268..0000000000
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpecBadSpecsTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.jsr356.server.pathmap;
-
-import static org.junit.Assert.fail;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-/**
- * Tests for bad path specs on ServerEndpoint Path Param / URI Template
- */
-@RunWith(Parameterized.class)
-public class WebSocketPathSpecBadSpecsTest
-{
- private static void bad(List<String[]> data, String str)
- {
- data.add(new String[]
- { str });
- }
-
- @Parameters
- public static Collection<String[]> data()
- {
- List<String[]> data = new ArrayList<>();
- bad(data,"/a/b{var}"); // bad syntax - variable does not encompass whole path segment
- bad(data,"a/{var}"); // bad syntax - no start slash
- bad(data,"/a/{var/b}"); // path segment separator in variable name
- bad(data,"/{var}/*"); // bad syntax - no globs allowed
- bad(data,"/{var}.do"); // bad syntax - variable does not encompass whole path segment
- bad(data,"/a/{var*}"); // use of glob character not allowed in variable name
- bad(data,"/a/{}"); // bad syntax - no variable name
- // MIGHT BE ALLOWED bad(data,"/a/{---}"); // no alpha in variable name
- bad(data,"{var}"); // bad syntax - no start slash
- bad(data,"/a/{my special variable}"); // bad syntax - space in variable name
- bad(data,"/a/{var}/{var}"); // variable name duplicate
- // MIGHT BE ALLOWED bad(data,"/a/{var}/{Var}/{vAR}"); // variable name duplicated (diff case)
- bad(data,"/a/../../../{var}"); // path navigation not allowed
- bad(data,"/a/./{var}"); // path navigation not allowed
- bad(data,"/a//{var}"); // bad syntax - double path slash (no path segment)
- return data;
- }
-
- private String pathSpec;
-
- public WebSocketPathSpecBadSpecsTest(String pathSpec)
- {
- this.pathSpec = pathSpec;
- }
-
- @Test
- public void testBadPathSpec()
- {
- try
- {
- new WebSocketPathSpec(this.pathSpec);
- fail("Expected IllegalArgumentException for a bad PathParam pathspec on: " + pathSpec);
- }
- catch (IllegalArgumentException e)
- {
- // expected path
- System.out.println(e.getMessage());
- }
- }
-}
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
deleted file mode 100644
index 23b87e71f2..0000000000
--- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/pathmap/WebSocketPathSpecTest.java
+++ /dev/null
@@ -1,286 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.jsr356.server.pathmap;
-
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-
-import java.util.Map;
-
-import org.eclipse.jetty.websocket.server.pathmap.PathSpec;
-import org.eclipse.jetty.websocket.server.pathmap.PathSpecGroup;
-import org.junit.Test;
-
-/**
- * Tests for ServerEndpoint Path Param / URI Template Path Specs
- */
-public class WebSocketPathSpecTest
-{
- private void assertDetectedVars(WebSocketPathSpec spec, String... expectedVars)
- {
- String prefix = String.format("Spec(\"%s\")",spec.getPathSpec());
- assertEquals(prefix + ".variableCount",expectedVars.length,spec.getVariableCount());
- assertEquals(prefix + ".variable.length",expectedVars.length,spec.getVariables().length);
- for (int i = 0; i < expectedVars.length; i++)
- {
- assertEquals(String.format("%s.variable[%d]",prefix,i),expectedVars[i],spec.getVariables()[i]);
- }
- }
-
- private void assertMatches(PathSpec spec, String path)
- {
- String msg = String.format("Spec(\"%s\").matches(\"%s\")",spec.getPathSpec(),path);
- assertThat(msg,spec.matches(path),is(true));
- }
-
- private 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 testDefaultPathSpec()
- {
- WebSocketPathSpec spec = new WebSocketPathSpec("/");
- assertEquals("Spec.pathSpec","/",spec.getPathSpec());
- assertEquals("Spec.pattern","^/$",spec.getPattern().pattern());
- assertEquals("Spec.pathDepth",1,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.EXACT,spec.getGroup());
-
- assertEquals("Spec.variableCount",0,spec.getVariableCount());
- assertEquals("Spec.variable.length",0,spec.getVariables().length);
- }
-
- @Test
- public void testExactOnePathSpec()
- {
- WebSocketPathSpec spec = new WebSocketPathSpec("/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.getGroup());
-
- assertMatches(spec,"/a");
- assertMatches(spec,"/a?type=other");
- assertNotMatches(spec,"/a/b");
- assertNotMatches(spec,"/a/");
-
- assertEquals("Spec.variableCount",0,spec.getVariableCount());
- assertEquals("Spec.variable.length",0,spec.getVariables().length);
- }
-
- @Test
- public void testExactPathSpec_TestWebapp()
- {
- WebSocketPathSpec spec = new WebSocketPathSpec("/javax.websocket/");
- assertEquals("Spec.pathSpec","/javax.websocket/",spec.getPathSpec());
- assertEquals("Spec.pattern","^/javax\\.websocket/$",spec.getPattern().pattern());
- assertEquals("Spec.pathDepth",1,spec.getPathDepth());
- assertEquals("Spec.group",PathSpecGroup.EXACT,spec.getGroup());
-
- assertMatches(spec,"/javax.websocket/");
- assertNotMatches(spec,"/javax.websocket");
-
- assertEquals("Spec.variableCount",0,spec.getVariableCount());
- assertEquals("Spec.variable.length",0,spec.getVariables().length);
- }
-
- @Test
- public void testExactTwoPathSpec()
- {
- WebSocketPathSpec spec = new WebSocketPathSpec("/a/b");
- 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.getGroup());
-
- assertEquals("Spec.variableCount",0,spec.getVariableCount());
- assertEquals("Spec.variable.length",0,spec.getVariables().length);
-
- assertMatches(spec,"/a/b");
-
- assertNotMatches(spec,"/a/b/");
- assertNotMatches(spec,"/a/");
- assertNotMatches(spec,"/a/bb");
- }
-
- @Test
- public void testMiddleVarPathSpec()
- {
- WebSocketPathSpec spec = new WebSocketPathSpec("/a/{var}/c");
- 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.getGroup());
-
- assertDetectedVars(spec,"var");
-
- assertMatches(spec,"/a/b/c");
- assertMatches(spec,"/a/zz/c");
- assertMatches(spec,"/a/hello+world/c");
- assertNotMatches(spec,"/a/bc");
- assertNotMatches(spec,"/a/b/");
- assertNotMatches(spec,"/a/b");
-
- Map<String, String> mapped = spec.getPathParams("/a/b/c");
- assertThat("Spec.pathParams",mapped,notNullValue());
- assertThat("Spec.pathParams.size",mapped.size(),is(1));
- assertEquals("Spec.pathParams[var]","b",mapped.get("var"));
- }
-
- @Test
- public void testOneVarPathSpec()
- {
- WebSocketPathSpec spec = new WebSocketPathSpec("/a/{foo}");
- 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.getGroup());
-
- assertDetectedVars(spec,"foo");
-
- assertMatches(spec,"/a/b");
- assertNotMatches(spec,"/a/");
- assertNotMatches(spec,"/a");
-
- Map<String, String> mapped = spec.getPathParams("/a/b");
- assertThat("Spec.pathParams",mapped,notNullValue());
- assertThat("Spec.pathParams.size",mapped.size(),is(1));
- assertEquals("Spec.pathParams[foo]","b",mapped.get("foo"));
- }
-
- @Test
- public void testOneVarSuffixPathSpec()
- {
- WebSocketPathSpec spec = new WebSocketPathSpec("/{var}/b/c");
- 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.getGroup());
-
- assertDetectedVars(spec,"var");
-
- assertMatches(spec,"/a/b/c");
- assertMatches(spec,"/az/b/c");
- assertMatches(spec,"/hello+world/b/c");
- assertNotMatches(spec,"/a/bc");
- assertNotMatches(spec,"/a/b/");
- assertNotMatches(spec,"/a/b");
-
- Map<String, String> mapped = spec.getPathParams("/a/b/c");
- assertThat("Spec.pathParams",mapped,notNullValue());
- assertThat("Spec.pathParams.size",mapped.size(),is(1));
- assertEquals("Spec.pathParams[var]","a",mapped.get("var"));
- }
-
- @Test
- public void testTwoVarComplexInnerPathSpec()
- {
- WebSocketPathSpec spec = new WebSocketPathSpec("/a/{var1}/c/{var2}/e");
- 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.getGroup());
-
- assertDetectedVars(spec,"var1","var2");
-
- assertMatches(spec,"/a/b/c/d/e");
- assertNotMatches(spec,"/a/bc/d/e");
- assertNotMatches(spec,"/a/b/d/e");
- assertNotMatches(spec,"/a/b//d/e");
-
- Map<String, String> mapped = spec.getPathParams("/a/b/c/d/e");
- assertThat("Spec.pathParams",mapped,notNullValue());
- assertThat("Spec.pathParams.size",mapped.size(),is(2));
- assertEquals("Spec.pathParams[var1]","b",mapped.get("var1"));
- assertEquals("Spec.pathParams[var2]","d",mapped.get("var2"));
- }
-
- @Test
- public void testTwoVarComplexOuterPathSpec()
- {
- WebSocketPathSpec spec = new WebSocketPathSpec("/{var1}/b/{var2}/{var3}");
- 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.getGroup());
-
- assertDetectedVars(spec,"var1","var2","var3");
-
- assertMatches(spec,"/a/b/c/d");
- assertNotMatches(spec,"/a/bc/d/e");
- assertNotMatches(spec,"/a/c/d/e");
- assertNotMatches(spec,"/a//d/e");
-
- Map<String, String> mapped = spec.getPathParams("/a/b/c/d");
- assertThat("Spec.pathParams",mapped,notNullValue());
- assertThat("Spec.pathParams.size",mapped.size(),is(3));
- assertEquals("Spec.pathParams[var1]","a",mapped.get("var1"));
- assertEquals("Spec.pathParams[var2]","c",mapped.get("var2"));
- assertEquals("Spec.pathParams[var3]","d",mapped.get("var3"));
- }
-
- @Test
- public void testTwoVarPrefixPathSpec()
- {
- WebSocketPathSpec spec = new WebSocketPathSpec("/a/{var1}/{var2}");
- 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.getGroup());
-
- assertDetectedVars(spec,"var1","var2");
-
- assertMatches(spec,"/a/b/c");
- assertNotMatches(spec,"/a/bc");
- assertNotMatches(spec,"/a/b/");
- assertNotMatches(spec,"/a/b");
-
- Map<String, String> mapped = spec.getPathParams("/a/b/c");
- assertThat("Spec.pathParams",mapped,notNullValue());
- assertThat("Spec.pathParams.size",mapped.size(),is(2));
- assertEquals("Spec.pathParams[var1]","b",mapped.get("var1"));
- assertEquals("Spec.pathParams[var2]","c",mapped.get("var2"));
- }
-
- @Test
- public void testVarOnlyPathSpec()
- {
- WebSocketPathSpec spec = new WebSocketPathSpec("/{var1}");
- 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.getGroup());
-
- assertDetectedVars(spec,"var1");
-
- assertMatches(spec,"/a");
- assertNotMatches(spec,"/");
- assertNotMatches(spec,"/a/b");
- assertNotMatches(spec,"/a/b/c");
-
- Map<String, String> mapped = spec.getPathParams("/a");
- assertThat("Spec.pathParams",mapped,notNullValue());
- assertThat("Spec.pathParams.size",mapped.size(),is(1));
- assertEquals("Spec.pathParams[var1]","a",mapped.get("var1"));
- }
-}
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java
index 7e4bb330c4..394b8de7c4 100644
--- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java
+++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java
@@ -103,7 +103,8 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Web
@Override
public void close()
{
- connection.close();
+ /* This is assumed to always be a NORMAL closure, no reason phrase */
+ connection.close(StatusCode.NORMAL, null);
}
@Override
diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/MappedWebSocketCreator.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/MappedWebSocketCreator.java
index c8d51924fe..8b668f1826 100644
--- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/MappedWebSocketCreator.java
+++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/MappedWebSocketCreator.java
@@ -18,8 +18,8 @@
package org.eclipse.jetty.websocket.server;
-import org.eclipse.jetty.websocket.server.pathmap.PathMappings;
-import org.eclipse.jetty.websocket.server.pathmap.PathSpec;
+import org.eclipse.jetty.http.pathmap.PathMappings;
+import org.eclipse.jetty.http.pathmap.PathSpec;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
/**
diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java
index 9b9b113eba..bbd60a06fd 100644
--- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java
+++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java
@@ -33,6 +33,9 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.eclipse.jetty.http.pathmap.MappedResource;
+import org.eclipse.jetty.http.pathmap.PathMappings;
+import org.eclipse.jetty.http.pathmap.PathSpec;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.servlet.FilterHolder;
@@ -44,9 +47,6 @@ import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
-import org.eclipse.jetty.websocket.server.pathmap.PathMappings;
-import org.eclipse.jetty.websocket.server.pathmap.PathMappings.MappedResource;
-import org.eclipse.jetty.websocket.server.pathmap.PathSpec;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
/**
diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeHandlerWrapper.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeHandlerWrapper.java
index 97251ddd46..b35b7da0a9 100644
--- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeHandlerWrapper.java
+++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeHandlerWrapper.java
@@ -24,13 +24,13 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.eclipse.jetty.http.pathmap.MappedResource;
+import org.eclipse.jetty.http.pathmap.PathMappings;
+import org.eclipse.jetty.http.pathmap.PathSpec;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper;
-import org.eclipse.jetty.websocket.server.pathmap.PathMappings;
-import org.eclipse.jetty.websocket.server.pathmap.PathMappings.MappedResource;
-import org.eclipse.jetty.websocket.server.pathmap.PathSpec;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
public class WebSocketUpgradeHandlerWrapper extends HandlerWrapper implements MappedWebSocketCreator
diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathMappings.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathMappings.java
deleted file mode 100644
index c8c256d517..0000000000
--- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathMappings.java
+++ /dev/null
@@ -1,190 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.server.pathmap;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.jetty.util.annotation.ManagedAttribute;
-import org.eclipse.jetty.util.annotation.ManagedObject;
-import org.eclipse.jetty.util.component.ContainerLifeCycle;
-import org.eclipse.jetty.util.component.Dumpable;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-import org.eclipse.jetty.websocket.server.pathmap.PathMappings.MappedResource;
-
-/**
- * Path Mappings of PathSpec to Resource.
- * <p>
- * Sorted into search order upon entry into the Set
- *
- * @param <E> the type of mapping endpoint
- */
-@ManagedObject("Path Mappings")
-public class PathMappings<E> implements Iterable<MappedResource<E>>, Dumpable
-{
- @ManagedObject("Mapped Resource")
- 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;
- }
-
- @ManagedAttribute(value = "path spec", readonly = true)
- public PathSpec getPathSpec()
- {
- return pathSpec;
- }
-
- @ManagedAttribute(value = "resource", readonly = true)
- 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 static final Logger LOG = Log.getLogger(PathMappings.class);
- private List<MappedResource<E>> mappings = new ArrayList<MappedResource<E>>();
- private MappedResource<E> defaultResource = null;
-
- @Override
- public String dump()
- {
- return ContainerLifeCycle.dump(this);
- }
-
- @Override
- public void dump(Appendable out, String indent) throws IOException
- {
- ContainerLifeCycle.dump(out,indent,mappings);
- }
-
- @ManagedAttribute(value = "mappings", readonly = true)
- public List<MappedResource<E>> getMappings()
- {
- return mappings;
- }
-
- public void reset()
- {
- mappings.clear();
- }
-
- 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);
- if (LOG.isDebugEnabled())
- LOG.debug("Added {} to {}",entry,this);
- Collections.sort(mappings);
- }
-
- @Override
- public String toString()
- {
- return String.format("%s[size=%d]",this.getClass().getSimpleName(),mappings.size());
- }
-}
diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathSpec.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathSpec.java
deleted file mode 100644
index 2e8999c01c..0000000000
--- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathSpec.java
+++ /dev/null
@@ -1,167 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.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;
- }
-
- public PathSpecGroup getGroup()
- {
- return group;
- }
-
- /**
- * 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/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathSpecGroup.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathSpecGroup.java
deleted file mode 100644
index 287d02df04..0000000000
--- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathSpecGroup.java
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.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/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/RegexPathSpec.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/RegexPathSpec.java
index cf5f75809a..a74c4d06a3 100644
--- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/RegexPathSpec.java
+++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/RegexPathSpec.java
@@ -18,159 +18,14 @@
package org.eclipse.jetty.websocket.server.pathmap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class RegexPathSpec extends PathSpec
+/**
+ * @deprecated moved to jetty-http {@link org.eclipse.jetty.http.pathmap.RegexPathSpec} (this facade will be removed in Jetty 9.4)
+ */
+@Deprecated
+public class RegexPathSpec extends org.eclipse.jetty.http.pathmap.RegexPathSpec
{
- 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(final String path)
- {
- int idx = path.indexOf('?');
- if (idx >= 0)
- {
- // match only non-query part
- return getMatcher(path.substring(0,idx)).matches();
- }
- else
- {
- // match entire path
- return getMatcher(path).matches();
- }
+ super(regex);
}
}
diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/ServletPathSpec.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/ServletPathSpec.java
index b09b15b790..b24f3d8b0c 100644
--- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/ServletPathSpec.java
+++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/ServletPathSpec.java
@@ -18,274 +18,14 @@
package org.eclipse.jetty.websocket.server.pathmap;
-import org.eclipse.jetty.util.URIUtil;
-
-public class ServletPathSpec extends PathSpec
+/**
+ * @deprecated moved to jetty-http {@link org.eclipse.jetty.http.pathmap.ServletPathSpec} (this facade will be removed in Jetty 9.4)
+ */
+@Deprecated
+public class ServletPathSpec extends org.eclipse.jetty.http.pathmap.ServletPathSpec
{
- 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;
- }
+ super(servletPathSpec);
}
}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/PathMappingsBenchmarkTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/PathMappingsBenchmarkTest.java
deleted file mode 100644
index 49b846c7cc..0000000000
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/PathMappingsBenchmarkTest.java
+++ /dev/null
@@ -1,226 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.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;
- @SuppressWarnings("unused")
- private long success;
- @SuppressWarnings("unused")
- 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/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/PathMappingsTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/PathMappingsTest.java
deleted file mode 100644
index bac59379d5..0000000000
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/PathMappingsTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.server.pathmap;
-
-import static org.hamcrest.Matchers.notNullValue;
-
-import org.eclipse.jetty.websocket.server.pathmap.PathMappings.MappedResource;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class PathMappingsTest
-{
- private void assertMatch(PathMappings<String> pathmap, String path, String expectedValue)
- {
- String msg = String.format(".getMatch(\"%s\")",path);
- MappedResource<String> match = pathmap.getMatch(path);
- Assert.assertThat(msg,match,notNullValue());
- String actualMatch = match.getResource();
- Assert.assertEquals(msg,expectedValue,actualMatch);
- }
-
- public void dumpMappings(PathMappings<String> p)
- {
- for (MappedResource<String> res : p)
- {
- System.out.printf(" %s%n",res);
- }
- }
-
- /**
- * Test the match order rules with a mixed Servlet and WebSocket path specs
- * <p>
- * <ul>
- * <li>Exact match</li>
- * <li>Longest prefix match</li>
- * <li>Longest suffix match</li>
- * </ul>
- */
- @Test
- public void testMixedMatchOrder()
- {
- PathMappings<String> p = new PathMappings<>();
-
- p.put(new ServletPathSpec("/"),"default");
- p.put(new ServletPathSpec("/animal/bird/*"),"birds");
- p.put(new ServletPathSpec("/animal/fish/*"),"fishes");
- p.put(new ServletPathSpec("/animal/*"),"animals");
- p.put(new RegexPathSpec("^/animal/.*/chat$"),"animalChat");
- p.put(new RegexPathSpec("^/animal/.*/cam$"),"animalCam");
- p.put(new RegexPathSpec("^/entrance/cam$"),"entranceCam");
-
- // dumpMappings(p);
-
- assertMatch(p,"/animal/bird/eagle","birds");
- assertMatch(p,"/animal/fish/bass/sea","fishes");
- assertMatch(p,"/animal/peccary/javalina/evolution","animals");
- assertMatch(p,"/","default");
- assertMatch(p,"/animal/bird/eagle/chat","animalChat");
- assertMatch(p,"/animal/bird/penguin/chat","animalChat");
- assertMatch(p,"/animal/fish/trout/cam","animalCam");
- assertMatch(p,"/entrance/cam","entranceCam");
- }
-
- /**
- * 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");
-
- // dumpMappings(p);
-
- 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");
- }
-}
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/RegexPathSpecTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/RegexPathSpecTest.java
deleted file mode 100644
index 94d16e25dc..0000000000
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/RegexPathSpecTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.server.pathmap;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-
-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 testMiddleSpecNoGrouping()
- {
- 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/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/ServletPathSpecTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/ServletPathSpecTest.java
deleted file mode 100644
index b0b8e29c44..0000000000
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/pathmap/ServletPathSpecTest.java
+++ /dev/null
@@ -1,188 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.websocket.server.pathmap;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-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"));
- }
-}

Back to the top