Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-11.0.x
Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
commit
4e8aec47e5
|
@ -211,7 +211,7 @@ public class WebServletAnnotation extends DiscoveredAnnotation
|
|||
for (String p : urlPatternList)
|
||||
{
|
||||
ServletMapping existingMapping = _context.getServletHandler().getServletMapping(p);
|
||||
if (existingMapping != null && existingMapping.isDefault())
|
||||
if (existingMapping != null && existingMapping.isFromDefaultDescriptor())
|
||||
{
|
||||
String[] updatedPaths = ArrayUtil.removeFromArray(existingMapping.getPathSpecs(), p);
|
||||
//if we removed the last path from a servletmapping, delete the servletmapping
|
||||
|
@ -264,7 +264,7 @@ public class WebServletAnnotation extends DiscoveredAnnotation
|
|||
return false;
|
||||
for (ServletMapping m : mappings)
|
||||
{
|
||||
if (!m.isDefault())
|
||||
if (!m.isFromDefaultDescriptor())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -117,7 +117,7 @@ public class TestServletAnnotations
|
|||
ServletMapping m = new ServletMapping();
|
||||
m.setPathSpec("/");
|
||||
m.setServletName("default");
|
||||
m.setDefault(true); //this mapping will be from a default descriptor
|
||||
m.setFromDefaultDescriptor(true); //this mapping will be from a default descriptor
|
||||
wac.getServletHandler().addServletMapping(m);
|
||||
|
||||
WebServletAnnotation annotation = new WebServletAnnotation(wac, "org.eclipse.jetty.annotations.ServletD", null);
|
||||
|
@ -150,13 +150,13 @@ public class TestServletAnnotations
|
|||
ServletMapping m = new ServletMapping();
|
||||
m.setPathSpec("/");
|
||||
m.setServletName("default");
|
||||
m.setDefault(true); //this mapping will be from a default descriptor
|
||||
m.setFromDefaultDescriptor(true); //this mapping will be from a default descriptor
|
||||
wac.getServletHandler().addServletMapping(m);
|
||||
|
||||
ServletMapping m2 = new ServletMapping();
|
||||
m2.setPathSpec("/other");
|
||||
m2.setServletName("default");
|
||||
m2.setDefault(true); //this mapping will be from a default descriptor
|
||||
m2.setFromDefaultDescriptor(true); //this mapping will be from a default descriptor
|
||||
wac.getServletHandler().addServletMapping(m2);
|
||||
|
||||
WebServletAnnotation annotation = new WebServletAnnotation(wac, "org.eclipse.jetty.annotations.ServletD", null);
|
||||
|
@ -235,7 +235,7 @@ public class TestServletAnnotations
|
|||
|
||||
ServletMapping m = new ServletMapping();
|
||||
m.setPathSpec("/default");
|
||||
m.setDefault(true);
|
||||
m.setFromDefaultDescriptor(true);
|
||||
m.setServletName("DServlet");
|
||||
wac.getServletHandler().addServletMapping(m);
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor
|
|||
{
|
||||
String origin = node.getAttribute(_originAttributeName);
|
||||
if (!StringUtil.isBlank(origin) && origin.startsWith(DefaultsDescriptor.class.getSimpleName()))
|
||||
mapping.setDefault(true);
|
||||
mapping.setFromDefaultDescriptor(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ public class TestQuickStart
|
|||
server.dumpStdErr();
|
||||
|
||||
//verify that FooServlet is now mapped to / and not the DefaultServlet
|
||||
ServletHolder sh = webapp.getServletHandler().getMappedServlet("/").getResource();
|
||||
ServletHolder sh = webapp.getServletHandler().getMappedServlet("/").getServletHolder();
|
||||
assertNotNull(sh);
|
||||
assertEquals("foo", sh.getName());
|
||||
}
|
||||
|
|
|
@ -28,24 +28,20 @@ import org.eclipse.jetty.util.Attributes;
|
|||
|
||||
class AsyncAttributes extends Attributes.Wrapper
|
||||
{
|
||||
private String _requestURI;
|
||||
private String _contextPath;
|
||||
private String _servletPath;
|
||||
private String _pathInfo;
|
||||
private String _queryString;
|
||||
private HttpServletMapping _httpServletMapping;
|
||||
private final String _requestURI;
|
||||
private final String _contextPath;
|
||||
private final String _pathInContext;
|
||||
private ServletPathMapping _mapping;
|
||||
private final String _queryString;
|
||||
|
||||
public AsyncAttributes(Attributes attributes, String requestUri, String contextPath, String servletPath, String pathInfo, String queryString, HttpServletMapping httpServletMapping)
|
||||
public AsyncAttributes(Attributes attributes, String requestUri, String contextPath, String pathInContext, ServletPathMapping mapping, String queryString)
|
||||
{
|
||||
super(attributes);
|
||||
|
||||
// TODO: make fields final in jetty-10 and NOOP when one of these attributes is set.
|
||||
_requestURI = requestUri;
|
||||
_contextPath = contextPath;
|
||||
_servletPath = servletPath;
|
||||
_pathInfo = pathInfo;
|
||||
_pathInContext = pathInContext;
|
||||
_mapping = mapping;
|
||||
_queryString = queryString;
|
||||
_httpServletMapping = httpServletMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,13 +54,13 @@ class AsyncAttributes extends Attributes.Wrapper
|
|||
case AsyncContext.ASYNC_CONTEXT_PATH:
|
||||
return _contextPath;
|
||||
case AsyncContext.ASYNC_SERVLET_PATH:
|
||||
return _servletPath;
|
||||
return _mapping == null ? null : _mapping.getServletPath();
|
||||
case AsyncContext.ASYNC_PATH_INFO:
|
||||
return _pathInfo;
|
||||
return _mapping == null ? _pathInContext : _mapping.getPathInfo();
|
||||
case AsyncContext.ASYNC_QUERY_STRING:
|
||||
return _queryString;
|
||||
case AsyncContext.ASYNC_MAPPING:
|
||||
return _httpServletMapping;
|
||||
return _mapping;
|
||||
default:
|
||||
return super.getAttribute(key);
|
||||
}
|
||||
|
@ -74,18 +70,12 @@ class AsyncAttributes extends Attributes.Wrapper
|
|||
public Set<String> getAttributeNameSet()
|
||||
{
|
||||
Set<String> set = new HashSet<>(super.getAttributeNameSet());
|
||||
if (_requestURI != null)
|
||||
set.add(AsyncContext.ASYNC_REQUEST_URI);
|
||||
if (_contextPath != null)
|
||||
set.add(AsyncContext.ASYNC_CONTEXT_PATH);
|
||||
if (_servletPath != null)
|
||||
set.add(AsyncContext.ASYNC_SERVLET_PATH);
|
||||
if (_pathInfo != null)
|
||||
set.add(AsyncContext.ASYNC_PATH_INFO);
|
||||
if (_queryString != null)
|
||||
set.add(AsyncContext.ASYNC_QUERY_STRING);
|
||||
if (_httpServletMapping != null)
|
||||
set.add(AsyncContext.ASYNC_MAPPING);
|
||||
set.add(AsyncContext.ASYNC_REQUEST_URI);
|
||||
set.add(AsyncContext.ASYNC_CONTEXT_PATH);
|
||||
set.add(AsyncContext.ASYNC_SERVLET_PATH);
|
||||
set.add(AsyncContext.ASYNC_PATH_INFO);
|
||||
set.add(AsyncContext.ASYNC_QUERY_STRING);
|
||||
set.add(AsyncContext.ASYNC_MAPPING);
|
||||
return set;
|
||||
}
|
||||
|
||||
|
@ -95,54 +85,17 @@ class AsyncAttributes extends Attributes.Wrapper
|
|||
switch (key)
|
||||
{
|
||||
case AsyncContext.ASYNC_REQUEST_URI:
|
||||
_requestURI = (String)value;
|
||||
break;
|
||||
case AsyncContext.ASYNC_CONTEXT_PATH:
|
||||
_contextPath = (String)value;
|
||||
break;
|
||||
case AsyncContext.ASYNC_SERVLET_PATH:
|
||||
_servletPath = (String)value;
|
||||
break;
|
||||
case AsyncContext.ASYNC_PATH_INFO:
|
||||
_pathInfo = (String)value;
|
||||
break;
|
||||
case AsyncContext.ASYNC_QUERY_STRING:
|
||||
_queryString = (String)value;
|
||||
break;
|
||||
case AsyncContext.ASYNC_MAPPING:
|
||||
_httpServletMapping = (HttpServletMapping)value;
|
||||
// Ignore sets for these reserved names as this class is applied
|
||||
// we will always override these particular attributes.
|
||||
break;
|
||||
default:
|
||||
super.setAttribute(key, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAttributes()
|
||||
{
|
||||
_requestURI = null;
|
||||
_contextPath = null;
|
||||
_servletPath = null;
|
||||
_pathInfo = null;
|
||||
_queryString = null;
|
||||
_httpServletMapping = null;
|
||||
super.clearAttributes();
|
||||
}
|
||||
|
||||
public static void applyAsyncAttributes(Attributes attributes, String requestURI, String contextPath, String servletPath, String pathInfo, String queryString, HttpServletMapping httpServletMapping)
|
||||
{
|
||||
if (requestURI != null)
|
||||
attributes.setAttribute(AsyncContext.ASYNC_REQUEST_URI, requestURI);
|
||||
if (contextPath != null)
|
||||
attributes.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH, contextPath);
|
||||
if (servletPath != null)
|
||||
attributes.setAttribute(AsyncContext.ASYNC_SERVLET_PATH, servletPath);
|
||||
if (pathInfo != null)
|
||||
attributes.setAttribute(AsyncContext.ASYNC_PATH_INFO, pathInfo);
|
||||
if (queryString != null)
|
||||
attributes.setAttribute(AsyncContext.ASYNC_QUERY_STRING, queryString);
|
||||
if (httpServletMapping != null)
|
||||
attributes.setAttribute(AsyncContext.ASYNC_MAPPING, httpServletMapping);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,14 +101,7 @@ public class Dispatcher implements RequestDispatcher
|
|||
}
|
||||
else
|
||||
{
|
||||
IncludeAttributes attr = new IncludeAttributes(old_attr);
|
||||
|
||||
attr._requestURI = _uri.getPath();
|
||||
attr._contextPath = _contextHandler.getContextPath();
|
||||
attr._servletPath = null; // set by ServletHandler
|
||||
attr._pathInfo = _pathInContext;
|
||||
attr._query = _uri.getQuery();
|
||||
attr._mapping = null; //set by ServletHandler
|
||||
IncludeAttributes attr = new IncludeAttributes(old_attr, _uri.getPath(), _contextHandler.getContextPath(), _pathInContext, _uri.getQuery());
|
||||
if (attr._query != null)
|
||||
baseRequest.mergeQueryParameters(baseRequest.getQueryString(), attr._query);
|
||||
baseRequest.setAttributes(attr);
|
||||
|
@ -147,7 +140,7 @@ public class Dispatcher implements RequestDispatcher
|
|||
final String old_context_path = baseRequest.getContextPath();
|
||||
final String old_servlet_path = baseRequest.getServletPath();
|
||||
final String old_path_info = baseRequest.getPathInfo();
|
||||
final HttpServletMapping old_mapping = baseRequest.getHttpServletMapping();
|
||||
final ServletPathMapping old_mapping = baseRequest.getServletPathMapping();
|
||||
|
||||
final MultiMap<String> old_query_params = baseRequest.getQueryParameters();
|
||||
final Attributes old_attr = baseRequest.getAttributes();
|
||||
|
@ -163,30 +156,26 @@ public class Dispatcher implements RequestDispatcher
|
|||
}
|
||||
else
|
||||
{
|
||||
ForwardAttributes attr = new ForwardAttributes(old_attr);
|
||||
|
||||
//If we have already been forwarded previously, then keep using the established
|
||||
//original value. Otherwise, this is the first forward and we need to establish the values.
|
||||
//Note: the established value on the original request for pathInfo and
|
||||
//for queryString is allowed to be null, but cannot be null for the other values.
|
||||
if (old_attr.getAttribute(FORWARD_REQUEST_URI) != null)
|
||||
{
|
||||
attr._pathInfo = (String)old_attr.getAttribute(FORWARD_PATH_INFO);
|
||||
attr._query = (String)old_attr.getAttribute(FORWARD_QUERY_STRING);
|
||||
attr._requestURI = (String)old_attr.getAttribute(FORWARD_REQUEST_URI);
|
||||
attr._contextPath = (String)old_attr.getAttribute(FORWARD_CONTEXT_PATH);
|
||||
attr._servletPath = (String)old_attr.getAttribute(FORWARD_SERVLET_PATH);
|
||||
attr._mapping = (HttpServletMapping)old_attr.getAttribute(FORWARD_MAPPING);
|
||||
}
|
||||
else
|
||||
{
|
||||
attr._pathInfo = old_path_info;
|
||||
attr._query = old_uri.getQuery();
|
||||
attr._requestURI = old_uri.getPath();
|
||||
attr._contextPath = old_context_path;
|
||||
attr._servletPath = old_servlet_path;
|
||||
attr._mapping = old_mapping;
|
||||
}
|
||||
// If we have already been forwarded previously, then keep using the established
|
||||
// original value. Otherwise, this is the first forward and we need to establish the values.
|
||||
// Note: the established value on the original request for pathInfo and
|
||||
// for queryString is allowed to be null, but cannot be null for the other values.
|
||||
// Note: the pathInfo is passed as the pathInContext since it is only used when there is
|
||||
// no mapping, and when there is no mapping the pathInfo is the pathInContext.
|
||||
// TODO Ultimately it is intended for the request to carry the pathInContext for easy access
|
||||
ForwardAttributes attr = old_attr.getAttribute(FORWARD_REQUEST_URI) != null
|
||||
? new ForwardAttributes(old_attr,
|
||||
(String)old_attr.getAttribute(FORWARD_REQUEST_URI),
|
||||
(String)old_attr.getAttribute(FORWARD_CONTEXT_PATH),
|
||||
(String)old_attr.getAttribute(FORWARD_PATH_INFO),
|
||||
(ServletPathMapping)old_attr.getAttribute(FORWARD_MAPPING),
|
||||
(String)old_attr.getAttribute(FORWARD_QUERY_STRING))
|
||||
: new ForwardAttributes(old_attr,
|
||||
old_uri.getPath(),
|
||||
old_context_path,
|
||||
baseRequest.getPathInfo(), // TODO replace with pathInContext
|
||||
old_mapping,
|
||||
old_uri.getQuery());
|
||||
|
||||
String query = _uri.getQuery();
|
||||
if (query == null)
|
||||
|
@ -194,6 +183,7 @@ public class Dispatcher implements RequestDispatcher
|
|||
|
||||
baseRequest.setHttpURI(HttpURI.build(old_uri, _uri.getPath(), _uri.getParam(), query));
|
||||
baseRequest.setContextPath(_contextHandler.getContextPath());
|
||||
baseRequest.setServletPathMapping(null);
|
||||
baseRequest.setServletPath(null);
|
||||
baseRequest.setPathInfo(_pathInContext);
|
||||
|
||||
|
@ -257,16 +247,20 @@ public class Dispatcher implements RequestDispatcher
|
|||
|
||||
private class ForwardAttributes extends Attributes.Wrapper
|
||||
{
|
||||
String _requestURI;
|
||||
String _contextPath;
|
||||
String _servletPath;
|
||||
String _pathInfo;
|
||||
String _query;
|
||||
HttpServletMapping _mapping;
|
||||
private final String _requestURI;
|
||||
private final String _contextPath;
|
||||
private final String _pathInContext;
|
||||
private final ServletPathMapping _servletPathMapping;
|
||||
private final String _query;
|
||||
|
||||
ForwardAttributes(Attributes attributes)
|
||||
public ForwardAttributes(Attributes attributes, String requestURI, String contextPath, String pathInContext, ServletPathMapping mapping, String query)
|
||||
{
|
||||
super(attributes);
|
||||
_requestURI = requestURI;
|
||||
_contextPath = contextPath;
|
||||
_pathInContext = pathInContext;
|
||||
_servletPathMapping = mapping;
|
||||
_query = query;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -277,22 +271,23 @@ public class Dispatcher implements RequestDispatcher
|
|||
switch (key)
|
||||
{
|
||||
case FORWARD_PATH_INFO:
|
||||
return _pathInfo;
|
||||
return _servletPathMapping == null ? _pathInContext : _servletPathMapping.getPathInfo();
|
||||
case FORWARD_REQUEST_URI:
|
||||
return _requestURI;
|
||||
case FORWARD_SERVLET_PATH:
|
||||
return _servletPath;
|
||||
return _servletPathMapping == null ? null : _servletPathMapping.getServletPath();
|
||||
case FORWARD_CONTEXT_PATH:
|
||||
return _contextPath;
|
||||
case FORWARD_QUERY_STRING:
|
||||
return _query;
|
||||
case FORWARD_MAPPING:
|
||||
return _mapping;
|
||||
return _servletPathMapping;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we are forwarded then we hide include attributes
|
||||
if (key.startsWith(__INCLUDE_PREFIX))
|
||||
return null;
|
||||
|
||||
|
@ -312,18 +307,12 @@ public class Dispatcher implements RequestDispatcher
|
|||
|
||||
if (_named == null)
|
||||
{
|
||||
if (_pathInfo != null)
|
||||
set.add(FORWARD_PATH_INFO);
|
||||
else
|
||||
set.remove(FORWARD_PATH_INFO);
|
||||
set.add(FORWARD_PATH_INFO);
|
||||
set.add(FORWARD_REQUEST_URI);
|
||||
set.add(FORWARD_SERVLET_PATH);
|
||||
set.add(FORWARD_CONTEXT_PATH);
|
||||
set.add(FORWARD_MAPPING);
|
||||
if (_query != null)
|
||||
set.add(FORWARD_QUERY_STRING);
|
||||
else
|
||||
set.remove(FORWARD_QUERY_STRING);
|
||||
set.add(FORWARD_QUERY_STRING);
|
||||
}
|
||||
|
||||
return set;
|
||||
|
@ -332,40 +321,11 @@ public class Dispatcher implements RequestDispatcher
|
|||
@Override
|
||||
public void setAttribute(String key, Object value)
|
||||
{
|
||||
if (_named == null && key.startsWith("jakarta.servlet."))
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case FORWARD_PATH_INFO:
|
||||
_pathInfo = (String)value;
|
||||
break;
|
||||
case FORWARD_REQUEST_URI:
|
||||
_requestURI = (String)value;
|
||||
break;
|
||||
case FORWARD_SERVLET_PATH:
|
||||
_servletPath = (String)value;
|
||||
break;
|
||||
case FORWARD_CONTEXT_PATH:
|
||||
_contextPath = (String)value;
|
||||
break;
|
||||
case FORWARD_QUERY_STRING:
|
||||
_query = (String)value;
|
||||
break;
|
||||
case FORWARD_MAPPING:
|
||||
_mapping = (HttpServletMapping)value;
|
||||
return;
|
||||
default:
|
||||
if (value == null)
|
||||
_attributes.removeAttribute(key);
|
||||
else
|
||||
_attributes.setAttribute(key, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (value == null)
|
||||
_attributes.removeAttribute(key);
|
||||
else
|
||||
_attributes.setAttribute(key, value);
|
||||
// Allow any attribute to be set, even if a reserved name. If a reserved
|
||||
// name is set here, it will be hidden by this class during the forward,
|
||||
// but revealed after the forward is complete just as if the reserved name
|
||||
// attribute had be set by the application before the forward.
|
||||
_attributes.setAttribute(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -389,16 +349,19 @@ public class Dispatcher implements RequestDispatcher
|
|||
|
||||
private class IncludeAttributes extends Attributes.Wrapper
|
||||
{
|
||||
String _requestURI;
|
||||
String _contextPath;
|
||||
String _servletPath;
|
||||
String _pathInfo;
|
||||
String _query;
|
||||
HttpServletMapping _mapping;
|
||||
private final String _requestURI;
|
||||
private final String _contextPath;
|
||||
private final String _pathInContext;
|
||||
private ServletPathMapping _servletPathMapping; // Set later by ServletHandler
|
||||
private final String _query;
|
||||
|
||||
IncludeAttributes(Attributes attributes)
|
||||
public IncludeAttributes(Attributes attributes, String requestURI, String contextPath, String pathInContext, String query)
|
||||
{
|
||||
super(attributes);
|
||||
_requestURI = requestURI;
|
||||
_contextPath = contextPath;
|
||||
_pathInContext = pathInContext;
|
||||
_query = query;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -409,9 +372,9 @@ public class Dispatcher implements RequestDispatcher
|
|||
switch (key)
|
||||
{
|
||||
case INCLUDE_PATH_INFO:
|
||||
return _pathInfo;
|
||||
return _servletPathMapping == null ? _pathInContext : _servletPathMapping.getPathInfo();
|
||||
case INCLUDE_SERVLET_PATH:
|
||||
return _servletPath;
|
||||
return _servletPathMapping == null ? null : _servletPathMapping.getServletPath();
|
||||
case INCLUDE_CONTEXT_PATH:
|
||||
return _contextPath;
|
||||
case INCLUDE_QUERY_STRING:
|
||||
|
@ -419,13 +382,11 @@ public class Dispatcher implements RequestDispatcher
|
|||
case INCLUDE_REQUEST_URI:
|
||||
return _requestURI;
|
||||
case INCLUDE_MAPPING:
|
||||
return _mapping;
|
||||
return _servletPathMapping;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (key.startsWith(__INCLUDE_PREFIX))
|
||||
return null;
|
||||
|
||||
return _attributes.getAttribute(key);
|
||||
}
|
||||
|
@ -442,18 +403,12 @@ public class Dispatcher implements RequestDispatcher
|
|||
|
||||
if (_named == null)
|
||||
{
|
||||
if (_pathInfo != null)
|
||||
set.add(INCLUDE_PATH_INFO);
|
||||
else
|
||||
set.remove(INCLUDE_PATH_INFO);
|
||||
set.add(INCLUDE_PATH_INFO);
|
||||
set.add(INCLUDE_REQUEST_URI);
|
||||
set.add(INCLUDE_SERVLET_PATH);
|
||||
set.add(INCLUDE_CONTEXT_PATH);
|
||||
set.add(INCLUDE_MAPPING);
|
||||
if (_query != null)
|
||||
set.add(INCLUDE_QUERY_STRING);
|
||||
else
|
||||
set.remove(INCLUDE_QUERY_STRING);
|
||||
set.add(INCLUDE_QUERY_STRING);
|
||||
}
|
||||
|
||||
return set;
|
||||
|
@ -462,40 +417,8 @@ public class Dispatcher implements RequestDispatcher
|
|||
@Override
|
||||
public void setAttribute(String key, Object value)
|
||||
{
|
||||
if (_named == null && key.startsWith("jakarta.servlet."))
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case INCLUDE_PATH_INFO:
|
||||
_pathInfo = (String)value;
|
||||
break;
|
||||
case INCLUDE_REQUEST_URI:
|
||||
_requestURI = (String)value;
|
||||
break;
|
||||
case INCLUDE_SERVLET_PATH:
|
||||
_servletPath = (String)value;
|
||||
break;
|
||||
case INCLUDE_CONTEXT_PATH:
|
||||
_contextPath = (String)value;
|
||||
break;
|
||||
case INCLUDE_QUERY_STRING:
|
||||
_query = (String)value;
|
||||
break;
|
||||
case INCLUDE_MAPPING:
|
||||
_mapping = (HttpServletMapping)value;
|
||||
break;
|
||||
default:
|
||||
if (value == null)
|
||||
_attributes.removeAttribute(key);
|
||||
else
|
||||
_attributes.setAttribute(key, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (value == null)
|
||||
_attributes.removeAttribute(key);
|
||||
else
|
||||
_attributes.setAttribute(key, value);
|
||||
if (_servletPathMapping == null && _named == null && INCLUDE_MAPPING.equals(key))
|
||||
_servletPathMapping = (ServletPathMapping)value;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -83,8 +83,6 @@ import org.eclipse.jetty.http.HttpURI;
|
|||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.http.pathmap.PathSpec;
|
||||
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
||||
import org.eclipse.jetty.io.RuntimeIOException;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler.Context;
|
||||
|
@ -193,85 +191,6 @@ public class Request implements HttpServletRequest
|
|||
return null;
|
||||
}
|
||||
|
||||
public static HttpServletMapping getServletMapping(PathSpec pathSpec, String servletPath, String servletName)
|
||||
{
|
||||
final MappingMatch match;
|
||||
final String mapping;
|
||||
if (pathSpec instanceof ServletPathSpec)
|
||||
{
|
||||
switch (pathSpec.getGroup())
|
||||
{
|
||||
case ROOT:
|
||||
match = MappingMatch.CONTEXT_ROOT;
|
||||
mapping = "";
|
||||
break;
|
||||
case DEFAULT:
|
||||
match = MappingMatch.DEFAULT;
|
||||
mapping = "/";
|
||||
break;
|
||||
case EXACT:
|
||||
match = MappingMatch.EXACT;
|
||||
mapping = servletPath.startsWith("/") ? servletPath.substring(1) : servletPath;
|
||||
break;
|
||||
case SUFFIX_GLOB:
|
||||
match = MappingMatch.EXTENSION;
|
||||
int dot = servletPath.lastIndexOf('.');
|
||||
mapping = servletPath.substring(0, dot);
|
||||
break;
|
||||
case PREFIX_GLOB:
|
||||
match = MappingMatch.PATH;
|
||||
mapping = servletPath;
|
||||
break;
|
||||
default:
|
||||
match = null;
|
||||
mapping = servletPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
match = null;
|
||||
mapping = servletPath;
|
||||
}
|
||||
|
||||
return new HttpServletMapping()
|
||||
{
|
||||
@Override
|
||||
public String getMatchValue()
|
||||
{
|
||||
return (mapping == null ? "" : mapping);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPattern()
|
||||
{
|
||||
if (pathSpec != null)
|
||||
return pathSpec.getDeclaration();
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServletName()
|
||||
{
|
||||
return (servletName == null ? "" : servletName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingMatch getMappingMatch()
|
||||
{
|
||||
return match;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "HttpServletMapping{matchValue=" + getMatchValue() +
|
||||
", pattern=" + getPattern() + ", servletName=" + getServletName() +
|
||||
", mappingMatch=" + getMappingMatch() + "}";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final HttpChannel _channel;
|
||||
private final List<ServletRequestAttributeListener> _requestAttributeListeners = new ArrayList<>();
|
||||
private final HttpInput _input;
|
||||
|
@ -283,7 +202,7 @@ public class Request implements HttpServletRequest
|
|||
private String _contextPath;
|
||||
private String _servletPath;
|
||||
private String _pathInfo;
|
||||
private PathSpec _pathSpec;
|
||||
private ServletPathMapping _servletPathMapping;
|
||||
private boolean _secure;
|
||||
private String _asyncNotSupportedSource = null;
|
||||
private boolean _newContext;
|
||||
|
@ -1841,7 +1760,6 @@ public class Request implements HttpServletRequest
|
|||
_queryParameters = null;
|
||||
_contentParameters = null;
|
||||
_parameters = null;
|
||||
_pathSpec = null;
|
||||
_contentParamsExtracted = false;
|
||||
_inputState = INPUT_NONE;
|
||||
_multiParts = null;
|
||||
|
@ -1925,50 +1843,67 @@ public class Request implements HttpServletRequest
|
|||
if (getAttribute(AsyncContext.ASYNC_REQUEST_URI) != null)
|
||||
return;
|
||||
|
||||
String requestURI;
|
||||
String contextPath;
|
||||
String servletPath;
|
||||
String pathInfo;
|
||||
String queryString;
|
||||
HttpServletMapping httpServletMapping;
|
||||
|
||||
// Have we been forwarded before?
|
||||
requestURI = (String)getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
|
||||
if (requestURI != null)
|
||||
{
|
||||
contextPath = (String)getAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH);
|
||||
servletPath = (String)getAttribute(RequestDispatcher.FORWARD_SERVLET_PATH);
|
||||
pathInfo = (String)getAttribute(RequestDispatcher.FORWARD_PATH_INFO);
|
||||
queryString = (String)getAttribute(RequestDispatcher.FORWARD_QUERY_STRING);
|
||||
httpServletMapping = (HttpServletMapping)getAttribute(RequestDispatcher.FORWARD_MAPPING);
|
||||
}
|
||||
else
|
||||
{
|
||||
requestURI = getRequestURI();
|
||||
contextPath = getContextPath();
|
||||
servletPath = getServletPath();
|
||||
pathInfo = getPathInfo();
|
||||
queryString = getQueryString();
|
||||
httpServletMapping = getHttpServletMapping();
|
||||
}
|
||||
|
||||
// Unwrap the _attributes to get the base attributes instance.
|
||||
Attributes baseAttributes;
|
||||
if (_attributes == null)
|
||||
_attributes = baseAttributes = new ServletAttributes();
|
||||
baseAttributes = _attributes = new ServletAttributes();
|
||||
else
|
||||
baseAttributes = Attributes.unwrap(_attributes);
|
||||
|
||||
if (baseAttributes instanceof ServletAttributes)
|
||||
// We cannot use a apply AsyncAttribute via #setAttributes as that
|
||||
// will wrap over any dispatch specific attribute wrappers (eg.
|
||||
// Dispatcher#ForwardAttributes). Async attributes must persist
|
||||
// after the current dispatch, so they must be set under any other
|
||||
// wrappers.
|
||||
|
||||
String fwdRequestURI = (String)getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
|
||||
if (fwdRequestURI == null)
|
||||
{
|
||||
// Set the AsyncAttributes on the ServletAttributes.
|
||||
ServletAttributes servletAttributes = (ServletAttributes)baseAttributes;
|
||||
servletAttributes.setAsyncAttributes(requestURI, contextPath, servletPath, pathInfo, queryString, httpServletMapping);
|
||||
if (baseAttributes instanceof ServletAttributes)
|
||||
{
|
||||
// The baseAttributes map is our ServletAttributes, so we can set the async
|
||||
// attributes there, under any other wrappers.
|
||||
((ServletAttributes)baseAttributes).setAsyncAttributes(getRequestURI(),
|
||||
getContextPath(),
|
||||
getPathInfo(), // TODO change to pathInContext when cheaply available
|
||||
getServletPathMapping(),
|
||||
getQueryString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// We cannot find our ServletAttributes instance, so just set directly and hope
|
||||
// whatever non jetty wrappers that have been applied will do the right thing.
|
||||
_attributes.setAttribute(AsyncContext.ASYNC_REQUEST_URI, getRequestURI());
|
||||
_attributes.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH, getContextPath());
|
||||
_attributes.setAttribute(AsyncContext.ASYNC_SERVLET_PATH, getServletPath());
|
||||
_attributes.setAttribute(AsyncContext.ASYNC_PATH_INFO, getPathInfo());
|
||||
_attributes.setAttribute(AsyncContext.ASYNC_QUERY_STRING, getQueryString());
|
||||
_attributes.setAttribute(AsyncContext.ASYNC_MAPPING, getHttpServletMapping());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If ServletAttributes has been replaced just set them on the top level Attributes.
|
||||
AsyncAttributes.applyAsyncAttributes(_attributes, requestURI, contextPath, servletPath, pathInfo, queryString, httpServletMapping);
|
||||
if (baseAttributes instanceof ServletAttributes)
|
||||
{
|
||||
// The baseAttributes map is our ServletAttributes, so we can set the async
|
||||
// attributes there, under any other wrappers.
|
||||
((ServletAttributes)baseAttributes).setAsyncAttributes(fwdRequestURI,
|
||||
(String)getAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH),
|
||||
(String)getAttribute(RequestDispatcher.FORWARD_PATH_INFO),
|
||||
(ServletPathMapping)getAttribute(RequestDispatcher.FORWARD_MAPPING),
|
||||
(String)getAttribute(RequestDispatcher.FORWARD_QUERY_STRING));
|
||||
}
|
||||
else
|
||||
{
|
||||
// We cannot find our ServletAttributes instance, so just set directly and hope
|
||||
// whatever non jetty wrappers that have been applied will do the right thing.
|
||||
_attributes.setAttribute(AsyncContext.ASYNC_REQUEST_URI, fwdRequestURI);
|
||||
_attributes.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH, getAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH));
|
||||
_attributes.setAttribute(AsyncContext.ASYNC_SERVLET_PATH, getAttribute(RequestDispatcher.FORWARD_SERVLET_PATH));
|
||||
_attributes.setAttribute(AsyncContext.ASYNC_PATH_INFO, getAttribute(RequestDispatcher.FORWARD_PATH_INFO));
|
||||
_attributes.setAttribute(AsyncContext.ASYNC_QUERY_STRING, getAttribute(RequestDispatcher.FORWARD_QUERY_STRING));
|
||||
_attributes.setAttribute(AsyncContext.ASYNC_MAPPING, getAttribute(RequestDispatcher.FORWARD_MAPPING));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2411,19 +2346,34 @@ public class Request implements HttpServletRequest
|
|||
throw new ServletException("HttpServletRequest.upgrade() not supported in Jetty");
|
||||
}
|
||||
|
||||
public void setPathSpec(PathSpec pathSpec)
|
||||
/**
|
||||
* Set the servletPathMapping, the servletPath and the pathInfo.
|
||||
* TODO remove the side effect on servletPath and pathInfo by removing those fields.
|
||||
* @param servletPathMapping The mapping used to return from {@link #getHttpServletMapping()}
|
||||
*/
|
||||
public void setServletPathMapping(ServletPathMapping servletPathMapping)
|
||||
{
|
||||
_pathSpec = pathSpec;
|
||||
_servletPathMapping = servletPathMapping;
|
||||
if (servletPathMapping == null)
|
||||
{
|
||||
// TODO reset the servletPath and pathInfo, but currently cannot do that
|
||||
// as we don't know the pathInContext.
|
||||
}
|
||||
else
|
||||
{
|
||||
_servletPath = servletPathMapping.getServletPath();
|
||||
_pathInfo = servletPathMapping.getPathInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public PathSpec getPathSpec()
|
||||
public ServletPathMapping getServletPathMapping()
|
||||
{
|
||||
return _pathSpec;
|
||||
return _servletPathMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpServletMapping getHttpServletMapping()
|
||||
{
|
||||
return Request.getServletMapping(_pathSpec, _servletPath, getServletName());
|
||||
return _servletPathMapping;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,18 +21,24 @@ package org.eclipse.jetty.server;
|
|||
import java.util.Set;
|
||||
|
||||
import jakarta.servlet.http.HttpServletMapping;
|
||||
|
||||
import org.eclipse.jetty.util.Attributes;
|
||||
import org.eclipse.jetty.util.AttributesMap;
|
||||
|
||||
/**
|
||||
* An implementation of Attributes that supports the standard async attributes.
|
||||
*
|
||||
* This implementation delegates to an internal {@link AttributesMap} instance, which
|
||||
* can optionally be wrapped with a {@link AsyncAttributes} instance. This allows async
|
||||
* attributes to be applied underneath any other attribute wrappers.
|
||||
*/
|
||||
public class ServletAttributes implements Attributes
|
||||
{
|
||||
private final Attributes _attributes = new AttributesMap();
|
||||
private AsyncAttributes _asyncAttributes;
|
||||
|
||||
public void setAsyncAttributes(String requestURI, String contextPath, String servletPath, String pathInfo, String queryString, HttpServletMapping httpServletMapping)
|
||||
public void setAsyncAttributes(String requestURI, String contextPath, String pathInContext, ServletPathMapping servletPathMapping, String queryString)
|
||||
{
|
||||
_asyncAttributes = new AsyncAttributes(_attributes, requestURI, contextPath, servletPath, pathInfo, queryString, httpServletMapping);
|
||||
_asyncAttributes = new AsyncAttributes(_attributes, requestURI, contextPath, pathInContext, servletPathMapping, queryString);
|
||||
}
|
||||
|
||||
private Attributes getAttributes()
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import jakarta.servlet.http.HttpServletMapping;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.MappingMatch;
|
||||
|
||||
import org.eclipse.jetty.http.pathmap.PathSpec;
|
||||
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
||||
|
||||
/**
|
||||
* Implementation of HttpServletMapping.
|
||||
*
|
||||
* Represents the application of a {@link ServletPathSpec} to a specific path
|
||||
* that resulted in a mapping to a {@link jakarta.servlet.Servlet}.
|
||||
* As well as supporting the standard {@link HttpServletMapping} methods, this
|
||||
* class also carries fields, which can be precomputed for the implementation
|
||||
* of {@link HttpServletRequest#getServletPath()} and
|
||||
* {@link HttpServletRequest#getPathInfo()}
|
||||
*/
|
||||
public class ServletPathMapping implements HttpServletMapping
|
||||
{
|
||||
private final MappingMatch _mappingMatch;
|
||||
private final String _matchValue;
|
||||
private final String _pattern;
|
||||
private final String _servletName;
|
||||
private final String _servletPath;
|
||||
private final String _pathInfo;
|
||||
|
||||
public ServletPathMapping(PathSpec pathSpec, String servletName, String pathInContext)
|
||||
{
|
||||
_servletName = (servletName == null ? "" : servletName);
|
||||
_pattern = pathSpec == null ? null : pathSpec.getDeclaration();
|
||||
|
||||
if (pathSpec instanceof ServletPathSpec && pathInContext != null)
|
||||
{
|
||||
switch (pathSpec.getGroup())
|
||||
{
|
||||
case ROOT:
|
||||
_mappingMatch = MappingMatch.CONTEXT_ROOT;
|
||||
_matchValue = "";
|
||||
_servletPath = "";
|
||||
_pathInfo = "/";
|
||||
break;
|
||||
|
||||
case DEFAULT:
|
||||
_mappingMatch = MappingMatch.DEFAULT;
|
||||
_matchValue = "";
|
||||
_servletPath = pathInContext;
|
||||
_pathInfo = null;
|
||||
break;
|
||||
|
||||
case EXACT:
|
||||
_mappingMatch = MappingMatch.EXACT;
|
||||
_matchValue = _pattern.startsWith("/") ? _pattern.substring(1) : _pattern;
|
||||
_servletPath = _pattern;
|
||||
_pathInfo = null;
|
||||
break;
|
||||
|
||||
case PREFIX_GLOB:
|
||||
_mappingMatch = MappingMatch.PATH;
|
||||
_servletPath = pathSpec.getPrefix();
|
||||
// TODO avoid the substring on the known servletPath!
|
||||
_matchValue = _servletPath.startsWith("/") ? _servletPath.substring(1) : _servletPath;
|
||||
_pathInfo = pathSpec.getPathInfo(pathInContext);
|
||||
break;
|
||||
|
||||
case SUFFIX_GLOB:
|
||||
_mappingMatch = MappingMatch.EXTENSION;
|
||||
int dot = pathInContext.lastIndexOf('.');
|
||||
_matchValue = pathInContext.substring(pathInContext.startsWith("/") ? 1 : 0, dot);
|
||||
_servletPath = pathInContext;
|
||||
_pathInfo = null;
|
||||
break;
|
||||
|
||||
case MIDDLE_GLOB:
|
||||
_mappingMatch = null;
|
||||
_matchValue = "";
|
||||
_servletPath = pathInContext;
|
||||
_pathInfo = null;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_mappingMatch = null;
|
||||
_matchValue = "";
|
||||
_servletPath = pathInContext;
|
||||
_pathInfo = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMatchValue()
|
||||
{
|
||||
return _matchValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPattern()
|
||||
{
|
||||
return _pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServletName()
|
||||
{
|
||||
return _servletName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingMatch getMappingMatch()
|
||||
{
|
||||
return _mappingMatch;
|
||||
}
|
||||
|
||||
public String getServletPath()
|
||||
{
|
||||
return _servletPath;
|
||||
}
|
||||
|
||||
public String getPathInfo()
|
||||
{
|
||||
return _pathInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "ServletPathMapping{" +
|
||||
"matchValue=" + _matchValue +
|
||||
", pattern=" + _pattern +
|
||||
", servletName=" + _servletName +
|
||||
", mappingMatch=" + _mappingMatch +
|
||||
", servletPath=" + _servletPath +
|
||||
", pathInfo=" + _pathInfo +
|
||||
"}";
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@ import jakarta.servlet.http.HttpServletMapping;
|
|||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import jakarta.servlet.http.MappingMatch;
|
||||
import jakarta.servlet.http.Part;
|
||||
import jakarta.servlet.http.PushBuilder;
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
|
@ -86,6 +87,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
@ -1427,69 +1429,6 @@ public class RequestTest
|
|||
assertThat(response, containsString("Hello World"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpServletMapping() throws Exception
|
||||
{
|
||||
String request = "GET / HTTP/1.1\n" +
|
||||
"Host: whatever\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
|
||||
_server.stop();
|
||||
PathMappingHandler handler = new PathMappingHandler(null, null, null);
|
||||
_server.setHandler(handler);
|
||||
_server.start();
|
||||
String response = _connector.getResponse(request);
|
||||
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
|
||||
assertThat("Response body content", response, containsString("HttpServletMapping{matchValue=, pattern=, servletName=, mappingMatch=null}"));
|
||||
_server.stop();
|
||||
|
||||
ServletPathSpec spec = new ServletPathSpec("");
|
||||
handler = new PathMappingHandler(spec, spec.getPathMatch("foo"), "Something");
|
||||
_server.setHandler(handler);
|
||||
_server.start();
|
||||
response = _connector.getResponse(request);
|
||||
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
|
||||
assertThat("Response body content", response, containsString("HttpServletMapping{matchValue=, pattern=, servletName=Something, mappingMatch=CONTEXT_ROOT}"));
|
||||
_server.stop();
|
||||
|
||||
spec = new ServletPathSpec("/");
|
||||
handler = new PathMappingHandler(spec, "", "Default");
|
||||
_server.setHandler(handler);
|
||||
_server.start();
|
||||
response = _connector.getResponse(request);
|
||||
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
|
||||
assertThat("Response body content", response, containsString("HttpServletMapping{matchValue=/, pattern=/, servletName=Default, mappingMatch=DEFAULT}"));
|
||||
_server.stop();
|
||||
|
||||
spec = new ServletPathSpec("/foo/*");
|
||||
handler = new PathMappingHandler(spec, spec.getPathMatch("/foo/bar"), "BarServlet");
|
||||
_server.setHandler(handler);
|
||||
_server.start();
|
||||
response = _connector.getResponse(request);
|
||||
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
|
||||
assertThat("Response body content", response, containsString("HttpServletMapping{matchValue=/foo, pattern=/foo/*, servletName=BarServlet, mappingMatch=PATH}"));
|
||||
_server.stop();
|
||||
|
||||
spec = new ServletPathSpec("*.jsp");
|
||||
handler = new PathMappingHandler(spec, spec.getPathMatch("/foo/bar.jsp"), "JspServlet");
|
||||
_server.setHandler(handler);
|
||||
_server.start();
|
||||
response = _connector.getResponse(request);
|
||||
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
|
||||
assertThat("Response body content", response, containsString("HttpServletMapping{matchValue=/foo/bar, pattern=*.jsp, servletName=JspServlet, mappingMatch=EXTENSION}"));
|
||||
_server.stop();
|
||||
|
||||
spec = new ServletPathSpec("/catalog");
|
||||
handler = new PathMappingHandler(spec, spec.getPathMatch("/catalog"), "CatalogServlet");
|
||||
_server.setHandler(handler);
|
||||
_server.start();
|
||||
response = _connector.getResponse(request);
|
||||
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
|
||||
assertThat("Response body content", response, containsString("HttpServletMapping{matchValue=catalog, pattern=/catalog, servletName=CatalogServlet, mappingMatch=EXACT}"));
|
||||
_server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCookies() throws Exception
|
||||
{
|
||||
|
@ -1935,6 +1874,92 @@ public class RequestTest
|
|||
assertThat(builder.getHeader("Cookie"), not(containsString("bad")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServletPathMapping() throws Exception
|
||||
{
|
||||
ServletPathSpec spec;
|
||||
String uri;
|
||||
ServletPathMapping m;
|
||||
|
||||
spec = null;
|
||||
uri = null;
|
||||
m = new ServletPathMapping(spec, null, uri);
|
||||
assertThat(m.getMappingMatch(), nullValue());
|
||||
assertThat(m.getMatchValue(), is(""));
|
||||
assertThat(m.getPattern(), nullValue());
|
||||
assertThat(m.getServletName(), is(""));
|
||||
assertThat(m.getServletPath(), nullValue());
|
||||
assertThat(m.getPathInfo(), nullValue());
|
||||
|
||||
spec = new ServletPathSpec("");
|
||||
uri = "/";
|
||||
m = new ServletPathMapping(spec, "Something", uri);
|
||||
assertThat(m.getMappingMatch(), is(MappingMatch.CONTEXT_ROOT));
|
||||
assertThat(m.getMatchValue(), is(""));
|
||||
assertThat(m.getPattern(), is(""));
|
||||
assertThat(m.getServletName(), is("Something"));
|
||||
assertThat(m.getServletPath(), is(spec.getPathMatch(uri)));
|
||||
assertThat(m.getPathInfo(), is(spec.getPathInfo(uri)));
|
||||
|
||||
spec = new ServletPathSpec("/");
|
||||
uri = "/some/path";
|
||||
m = new ServletPathMapping(spec, "Default", uri);
|
||||
assertThat(m.getMappingMatch(), is(MappingMatch.DEFAULT));
|
||||
assertThat(m.getMatchValue(), is(""));
|
||||
assertThat(m.getPattern(), is("/"));
|
||||
assertThat(m.getServletName(), is("Default"));
|
||||
assertThat(m.getServletPath(), is(spec.getPathMatch(uri)));
|
||||
assertThat(m.getPathInfo(), is(spec.getPathInfo(uri)));
|
||||
|
||||
spec = new ServletPathSpec("/foo/*");
|
||||
uri = "/foo/bar";
|
||||
m = new ServletPathMapping(spec, "FooServlet", uri);
|
||||
assertThat(m.getMappingMatch(), is(MappingMatch.PATH));
|
||||
assertThat(m.getMatchValue(), is("foo"));
|
||||
assertThat(m.getPattern(), is("/foo/*"));
|
||||
assertThat(m.getServletName(), is("FooServlet"));
|
||||
assertThat(m.getServletPath(), is(spec.getPathMatch(uri)));
|
||||
assertThat(m.getPathInfo(), is(spec.getPathInfo(uri)));
|
||||
|
||||
uri = "/foo/";
|
||||
m = new ServletPathMapping(spec, "FooServlet", uri);
|
||||
assertThat(m.getMappingMatch(), is(MappingMatch.PATH));
|
||||
assertThat(m.getMatchValue(), is("foo"));
|
||||
assertThat(m.getPattern(), is("/foo/*"));
|
||||
assertThat(m.getServletName(), is("FooServlet"));
|
||||
assertThat(m.getServletPath(), is(spec.getPathMatch(uri)));
|
||||
assertThat(m.getPathInfo(), is(spec.getPathInfo(uri)));
|
||||
|
||||
uri = "/foo";
|
||||
m = new ServletPathMapping(spec, "FooServlet", uri);
|
||||
assertThat(m.getMappingMatch(), is(MappingMatch.PATH));
|
||||
assertThat(m.getMatchValue(), is("foo"));
|
||||
assertThat(m.getPattern(), is("/foo/*"));
|
||||
assertThat(m.getServletName(), is("FooServlet"));
|
||||
assertThat(m.getServletPath(), is(spec.getPathMatch(uri)));
|
||||
assertThat(m.getPathInfo(), is(spec.getPathInfo(uri)));
|
||||
|
||||
spec = new ServletPathSpec("*.jsp");
|
||||
uri = "/foo/bar.jsp";
|
||||
m = new ServletPathMapping(spec, "JspServlet", uri);
|
||||
assertThat(m.getMappingMatch(), is(MappingMatch.EXTENSION));
|
||||
assertThat(m.getMatchValue(), is("foo/bar"));
|
||||
assertThat(m.getPattern(), is("*.jsp"));
|
||||
assertThat(m.getServletName(), is("JspServlet"));
|
||||
assertThat(m.getServletPath(), is(spec.getPathMatch(uri)));
|
||||
assertThat(m.getPathInfo(), is(spec.getPathInfo(uri)));
|
||||
|
||||
spec = new ServletPathSpec("/catalog");
|
||||
uri = "/catalog";
|
||||
m = new ServletPathMapping(spec, "CatalogServlet", uri);
|
||||
assertThat(m.getMappingMatch(), is(MappingMatch.EXACT));
|
||||
assertThat(m.getMatchValue(), is("catalog"));
|
||||
assertThat(m.getPattern(), is("/catalog"));
|
||||
assertThat(m.getServletName(), is("CatalogServlet"));
|
||||
assertThat(m.getServletPath(), is(spec.getPathMatch(uri)));
|
||||
assertThat(m.getPathInfo(), is(spec.getPathInfo(uri)));
|
||||
}
|
||||
|
||||
interface RequestTester
|
||||
{
|
||||
boolean check(HttpServletRequest request, HttpServletResponse response) throws IOException;
|
||||
|
@ -2169,7 +2194,6 @@ public class RequestTest
|
|||
{
|
||||
((Request)request).setHandled(true);
|
||||
baseRequest.setServletPath(_servletPath);
|
||||
baseRequest.setPathSpec(_spec);
|
||||
if (_servletName != null)
|
||||
baseRequest.setUserIdentityScope(new TestUserIdentityScope(null, null, _servletName));
|
||||
HttpServletMapping mapping = baseRequest.getHttpServletMapping();
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.eclipse.jetty.http.HttpContent;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http.pathmap.MappedResource;
|
||||
import org.eclipse.jetty.server.CachedContentFactory;
|
||||
import org.eclipse.jetty.server.ResourceContentFactory;
|
||||
import org.eclipse.jetty.server.ResourceService;
|
||||
|
@ -500,9 +499,9 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory, Welc
|
|||
|
||||
if ((_welcomeServlets || _welcomeExactServlets) && welcomeServlet == null)
|
||||
{
|
||||
MappedResource<ServletHolder> entry = _servletHandler.getMappedServlet(welcomeInContext);
|
||||
ServletHandler.MappedServlet entry = _servletHandler.getMappedServlet(welcomeInContext);
|
||||
@SuppressWarnings("ReferenceEquality")
|
||||
boolean isDefaultHolder = (entry.getResource() != _defaultHolder);
|
||||
boolean isDefaultHolder = (entry.getServletHolder() != _defaultHolder);
|
||||
if (entry != null && isDefaultHolder &&
|
||||
(_welcomeServlets || (_welcomeExactServlets && entry.getPathSpec().getDeclaration().equals(welcomeInContext))))
|
||||
welcomeServlet = welcomeInContext;
|
||||
|
|
|
@ -71,7 +71,7 @@ public class Invoker extends HttpServlet
|
|||
|
||||
private ContextHandler _contextHandler;
|
||||
private ServletHandler _servletHandler;
|
||||
private MappedResource<ServletHolder> _invokerEntry;
|
||||
private ServletHandler.MappedServlet _invokerEntry;
|
||||
private Map<String, String> _parameters;
|
||||
private boolean _nonContextServlets;
|
||||
private boolean _verbose;
|
||||
|
@ -171,12 +171,12 @@ public class Invoker extends HttpServlet
|
|||
|
||||
// Check for existing mapping (avoid threaded race).
|
||||
String path = URIUtil.addPaths(servletPath, servlet);
|
||||
MappedResource<ServletHolder> entry = _servletHandler.getMappedServlet(path);
|
||||
ServletHandler.MappedServlet entry = _servletHandler.getMappedServlet(path);
|
||||
|
||||
if (entry != null && !entry.equals(_invokerEntry))
|
||||
{
|
||||
// Use the holder
|
||||
holder = (ServletHolder)entry.getResource();
|
||||
holder = (ServletHolder)entry.getServletHolder();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -26,7 +26,6 @@ import java.util.EnumSet;
|
|||
import java.util.EventListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
|
@ -57,6 +56,7 @@ 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;
|
||||
import org.eclipse.jetty.server.ServletPathMapping;
|
||||
import org.eclipse.jetty.server.ServletRequestHttpWrapper;
|
||||
import org.eclipse.jetty.server.ServletResponseHttpWrapper;
|
||||
import org.eclipse.jetty.server.UserIdentity;
|
||||
|
@ -92,8 +92,6 @@ public class ServletHandler extends ScopedHandler
|
|||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ServletHandler.class);
|
||||
|
||||
public static final String __DEFAULT_SERVLET = "default";
|
||||
|
||||
private ServletContextHandler _contextHandler;
|
||||
private ServletContext _servletContext;
|
||||
private FilterHolder[] _filters = new FilterHolder[0];
|
||||
|
@ -113,8 +111,8 @@ public class ServletHandler extends ScopedHandler
|
|||
private List<FilterMapping> _filterPathMappings;
|
||||
private MultiMap<FilterMapping> _filterNameMappings;
|
||||
|
||||
private final Map<String, ServletHolder> _servletNameMap = new HashMap<>();
|
||||
private PathMappings<ServletHolder> _servletPathMap;
|
||||
private final Map<String, MappedServlet> _servletNameMap = new HashMap<>();
|
||||
private PathMappings<MappedServlet> _servletPathMap;
|
||||
|
||||
private ListenerHolder[] _listeners = new ListenerHolder[0];
|
||||
private boolean _initialized = false;
|
||||
|
@ -167,7 +165,7 @@ public class ServletHandler extends ScopedHandler
|
|||
LOG.debug("Adding Default404Servlet to {}", this);
|
||||
addServletWithMapping(Default404Servlet.class, "/");
|
||||
updateMappings();
|
||||
getServletMapping("/").setDefault(true);
|
||||
getServletMapping("/").setFromDefaultDescriptor(true);
|
||||
}
|
||||
|
||||
if (isFilterChainsCached())
|
||||
|
@ -247,13 +245,7 @@ public class ServletHandler extends ScopedHandler
|
|||
//remove all of the mappings that were for non-embedded filters
|
||||
_filterNameMap.remove(filter.getName());
|
||||
//remove any mappings associated with this filter
|
||||
ListIterator<FilterMapping> fmitor = filterMappings.listIterator();
|
||||
while (fmitor.hasNext())
|
||||
{
|
||||
FilterMapping fm = fmitor.next();
|
||||
if (fm.getFilterName().equals(filter.getName()))
|
||||
fmitor.remove();
|
||||
}
|
||||
filterMappings.removeIf(fm -> fm.getFilterName().equals(filter.getName()));
|
||||
}
|
||||
else
|
||||
filterHolders.add(filter); //only retain embedded
|
||||
|
@ -261,10 +253,8 @@ public class ServletHandler extends ScopedHandler
|
|||
}
|
||||
|
||||
//Retain only filters and mappings that were added using jetty api (ie Source.EMBEDDED)
|
||||
FilterHolder[] fhs = (FilterHolder[])LazyList.toArray(filterHolders, FilterHolder.class);
|
||||
_filters = fhs;
|
||||
FilterMapping[] fms = (FilterMapping[])LazyList.toArray(filterMappings, FilterMapping.class);
|
||||
_filterMappings = fms;
|
||||
_filters = (FilterHolder[])LazyList.toArray(filterHolders, FilterHolder.class);
|
||||
_filterMappings = (FilterMapping[])LazyList.toArray(filterMappings, FilterMapping.class);
|
||||
|
||||
_matchAfterIndex = (_filterMappings == null || _filterMappings.length == 0 ? -1 : _filterMappings.length - 1);
|
||||
_matchBeforeIndex = -1;
|
||||
|
@ -291,13 +281,7 @@ public class ServletHandler extends ScopedHandler
|
|||
//remove from servlet name map
|
||||
_servletNameMap.remove(servlet.getName());
|
||||
//remove any mappings associated with this servlet
|
||||
ListIterator<ServletMapping> smitor = servletMappings.listIterator();
|
||||
while (smitor.hasNext())
|
||||
{
|
||||
ServletMapping sm = smitor.next();
|
||||
if (sm.getServletName().equals(servlet.getName()))
|
||||
smitor.remove();
|
||||
}
|
||||
servletMappings.removeIf(sm -> sm.getServletName().equals(servlet.getName()));
|
||||
}
|
||||
else
|
||||
servletHolders.add(servlet); //only retain embedded
|
||||
|
@ -305,10 +289,8 @@ public class ServletHandler extends ScopedHandler
|
|||
}
|
||||
|
||||
//Retain only Servlets and mappings added via jetty apis (ie Source.EMBEDDED)
|
||||
ServletHolder[] shs = (ServletHolder[])LazyList.toArray(servletHolders, ServletHolder.class);
|
||||
_servlets = shs;
|
||||
ServletMapping[] sms = (ServletMapping[])LazyList.toArray(servletMappings, ServletMapping.class);
|
||||
_servletMappings = sms;
|
||||
_servlets = (ServletHolder[])LazyList.toArray(servletHolders, ServletHolder.class);
|
||||
_servletMappings = (ServletMapping[])LazyList.toArray(servletMappings, ServletMapping.class);
|
||||
|
||||
if (_contextHandler != null)
|
||||
_contextHandler.contextDestroyed();
|
||||
|
@ -332,8 +314,7 @@ public class ServletHandler extends ScopedHandler
|
|||
listenerHolders.add(listener);
|
||||
}
|
||||
}
|
||||
ListenerHolder[] listeners = (ListenerHolder[])LazyList.toArray(listenerHolders, ListenerHolder.class);
|
||||
_listeners = listeners;
|
||||
_listeners = (ListenerHolder[])LazyList.toArray(listenerHolders, ListenerHolder.class);
|
||||
|
||||
//will be regenerated on next start
|
||||
_filterPathMappings = null;
|
||||
|
@ -425,50 +406,40 @@ public class ServletHandler extends ScopedHandler
|
|||
|
||||
public ServletHolder getServlet(String name)
|
||||
{
|
||||
return _servletNameMap.get(name);
|
||||
MappedServlet mapped = _servletNameMap.get(name);
|
||||
if (mapped != null)
|
||||
return mapped.getServletHolder();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
// Get the base requests
|
||||
final String old_servlet_path = baseRequest.getServletPath();
|
||||
final String old_path_info = baseRequest.getPathInfo();
|
||||
final PathSpec old_path_spec = baseRequest.getPathSpec();
|
||||
final ServletPathMapping old_servlet_path_mapping = baseRequest.getServletPathMapping();
|
||||
|
||||
DispatcherType type = baseRequest.getDispatcherType();
|
||||
|
||||
ServletHolder servletHolder = null;
|
||||
UserIdentity.Scope oldScope = null;
|
||||
|
||||
MappedResource<ServletHolder> mapping = getMappedServlet(target);
|
||||
if (mapping != null)
|
||||
MappedServlet mappedServlet = getMappedServlet(target);
|
||||
if (mappedServlet != null)
|
||||
{
|
||||
servletHolder = mapping.getResource();
|
||||
|
||||
if (mapping.getPathSpec() != null)
|
||||
servletHolder = mappedServlet.getServletHolder();
|
||||
ServletPathMapping servletPathMapping = mappedServlet.getServletPathMapping(target);
|
||||
if (servletPathMapping != null)
|
||||
{
|
||||
PathSpec pathSpec = mapping.getPathSpec();
|
||||
String servletPath = pathSpec.getPathMatch(target);
|
||||
String pathInfo = pathSpec.getPathInfo(target);
|
||||
|
||||
// Setting the servletPathMapping also provides the servletPath and pathInfo
|
||||
if (DispatcherType.INCLUDE.equals(type))
|
||||
{
|
||||
baseRequest.setAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH, servletPath);
|
||||
baseRequest.setAttribute(RequestDispatcher.INCLUDE_PATH_INFO, pathInfo);
|
||||
baseRequest.setAttribute(RequestDispatcher.INCLUDE_MAPPING, Request.getServletMapping(pathSpec, servletPath, servletHolder.getName()));
|
||||
}
|
||||
baseRequest.setAttribute(RequestDispatcher.INCLUDE_MAPPING, servletPathMapping);
|
||||
else
|
||||
{
|
||||
baseRequest.setPathSpec(pathSpec);
|
||||
baseRequest.setServletPath(servletPath);
|
||||
baseRequest.setPathInfo(pathInfo);
|
||||
}
|
||||
baseRequest.setServletPathMapping(servletPathMapping);
|
||||
}
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("servlet {}|{}|{} -> {}", baseRequest.getContextPath(), baseRequest.getServletPath(), baseRequest.getPathInfo(), servletHolder);
|
||||
LOG.debug("servlet {}|{}|{}|{} -> {}", baseRequest.getContextPath(), baseRequest.getServletPath(), baseRequest.getPathInfo(), baseRequest.getHttpServletMapping(), servletHolder);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -484,11 +455,7 @@ public class ServletHandler extends ScopedHandler
|
|||
baseRequest.setUserIdentityScope(oldScope);
|
||||
|
||||
if (!(DispatcherType.INCLUDE.equals(type)))
|
||||
{
|
||||
baseRequest.setServletPath(old_servlet_path);
|
||||
baseRequest.setPathInfo(old_path_info);
|
||||
baseRequest.setPathSpec(old_path_spec);
|
||||
}
|
||||
baseRequest.setServletPathMapping(old_servlet_path_mapping);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -550,34 +517,33 @@ public class ServletHandler extends ScopedHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* ServletHolder matching path.
|
||||
* Get MappedServlet for target.
|
||||
*
|
||||
* @param target Path within _context or servlet name
|
||||
* @return MappedResource to the ServletHolder. Named servlets have a null PathSpec
|
||||
* @return MappedServlet matched by path or name. Named servlets have a null PathSpec
|
||||
*/
|
||||
public MappedResource<ServletHolder> getMappedServlet(String target)
|
||||
public MappedServlet getMappedServlet(String target)
|
||||
{
|
||||
if (target.startsWith("/"))
|
||||
{
|
||||
if (_servletPathMap == null)
|
||||
return null;
|
||||
return _servletPathMap.getMatch(target);
|
||||
|
||||
MappedResource<MappedServlet> match = _servletPathMap.getMatch(target);
|
||||
if (match == null)
|
||||
return null;
|
||||
return match.getResource();
|
||||
}
|
||||
|
||||
if (_servletNameMap == null)
|
||||
return null;
|
||||
ServletHolder holder = _servletNameMap.get(target);
|
||||
if (holder == null)
|
||||
return null;
|
||||
return new MappedResource<>(null, holder);
|
||||
return _servletNameMap.get(target);
|
||||
}
|
||||
|
||||
protected FilterChain getFilterChain(Request baseRequest, String pathInContext, ServletHolder servletHolder)
|
||||
private FilterChain getFilterChain(Request baseRequest, String pathInContext, ServletHolder servletHolder)
|
||||
{
|
||||
String key = pathInContext == null ? servletHolder.getName() : pathInContext;
|
||||
int dispatch = FilterMapping.dispatch(baseRequest.getDispatcherType());
|
||||
|
||||
if (_filterChainsCached && _chainCache != null)
|
||||
if (_filterChainsCached)
|
||||
{
|
||||
FilterChain chain = _chainCache[dispatch].get(key);
|
||||
if (chain != null)
|
||||
|
@ -624,8 +590,7 @@ public class ServletHandler extends ScopedHandler
|
|||
FilterChain chain = null;
|
||||
if (_filterChainsCached)
|
||||
{
|
||||
if (!filters.isEmpty())
|
||||
chain = newCachedChain(filters, servletHolder);
|
||||
chain = newCachedChain(filters, servletHolder);
|
||||
|
||||
final Map<String, FilterChain> cache = _chainCache[dispatch];
|
||||
final Queue<String> lru = _chainLRU[dispatch];
|
||||
|
@ -648,7 +613,7 @@ public class ServletHandler extends ScopedHandler
|
|||
cache.put(key, chain);
|
||||
lru.add(key);
|
||||
}
|
||||
else if (!filters.isEmpty())
|
||||
else
|
||||
chain = new Chain(baseRequest, filters, servletHolder);
|
||||
|
||||
return chain;
|
||||
|
@ -1133,7 +1098,7 @@ public class ServletHandler extends ScopedHandler
|
|||
if (mappings == null || mappings.length == 0)
|
||||
{
|
||||
setFilterMappings(insertFilterMapping(mapping, 0, false));
|
||||
if (source != null && source == Source.JAVAX_API)
|
||||
if (source == Source.JAVAX_API)
|
||||
_matchAfterIndex = 0;
|
||||
}
|
||||
else
|
||||
|
@ -1141,7 +1106,7 @@ public class ServletHandler extends ScopedHandler
|
|||
//there are existing entries. If this is a programmatic filtermapping, it is added at the end of the list.
|
||||
//If this is a normal filtermapping, it is inserted after all the other filtermappings (matchBefores and normals),
|
||||
//but before the first matchAfter filtermapping.
|
||||
if (source != null && Source.JAVAX_API == source)
|
||||
if (Source.JAVAX_API == source)
|
||||
{
|
||||
setFilterMappings(insertFilterMapping(mapping, mappings.length - 1, false));
|
||||
if (_matchAfterIndex < 0)
|
||||
|
@ -1177,12 +1142,12 @@ public class ServletHandler extends ScopedHandler
|
|||
if (mappings == null || mappings.length == 0)
|
||||
{
|
||||
setFilterMappings(insertFilterMapping(mapping, 0, false));
|
||||
if (source != null && Source.JAVAX_API == source)
|
||||
if (Source.JAVAX_API == source)
|
||||
_matchBeforeIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (source != null && Source.JAVAX_API == source)
|
||||
if (Source.JAVAX_API == source)
|
||||
{
|
||||
//programmatically defined filter mappings are prepended to mapping list in the order
|
||||
//in which they were defined. In other words, insert this mapping at the tail of the
|
||||
|
@ -1281,7 +1246,7 @@ public class ServletHandler extends ScopedHandler
|
|||
// update the maps
|
||||
for (ServletHolder servlet : _servlets)
|
||||
{
|
||||
_servletNameMap.put(servlet.getName(), servlet);
|
||||
_servletNameMap.put(servlet.getName(), new MappedServlet(null, servlet));
|
||||
servlet.setServletHandler(this);
|
||||
}
|
||||
}
|
||||
|
@ -1321,13 +1286,13 @@ public class ServletHandler extends ScopedHandler
|
|||
}
|
||||
|
||||
// Map servlet paths to holders
|
||||
if (_servletMappings == null || _servletNameMap == null)
|
||||
if (_servletMappings == null)
|
||||
{
|
||||
_servletPathMap = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
PathMappings<ServletHolder> pm = new PathMappings<>();
|
||||
PathMappings<MappedServlet> pm = new PathMappings<>();
|
||||
|
||||
//create a map of paths to set of ServletMappings that define that mapping
|
||||
HashMap<String, List<ServletMapping>> sms = new HashMap<>();
|
||||
|
@ -1338,12 +1303,7 @@ public class ServletHandler extends ScopedHandler
|
|||
{
|
||||
for (String pathSpec : pathSpecs)
|
||||
{
|
||||
List<ServletMapping> mappings = sms.get(pathSpec);
|
||||
if (mappings == null)
|
||||
{
|
||||
mappings = new ArrayList<>();
|
||||
sms.put(pathSpec, mappings);
|
||||
}
|
||||
List<ServletMapping> mappings = sms.computeIfAbsent(pathSpec, k -> new ArrayList<>());
|
||||
mappings.add(servletMapping);
|
||||
}
|
||||
}
|
||||
|
@ -1360,7 +1320,7 @@ public class ServletHandler extends ScopedHandler
|
|||
for (ServletMapping mapping : mappings)
|
||||
{
|
||||
//Get servlet associated with the mapping and check it is enabled
|
||||
ServletHolder servletHolder = _servletNameMap.get(mapping.getServletName());
|
||||
ServletHolder servletHolder = getServlet(mapping.getServletName());
|
||||
if (servletHolder == null)
|
||||
throw new IllegalStateException("No such servlet: " + mapping.getServletName());
|
||||
//if the servlet related to the mapping is not enabled, skip it from consideration
|
||||
|
@ -1374,7 +1334,7 @@ public class ServletHandler extends ScopedHandler
|
|||
{
|
||||
//already have a candidate - only accept another one
|
||||
//if the candidate is a default, or we're allowing duplicate mappings
|
||||
if (finalMapping.isDefault())
|
||||
if (finalMapping.isFromDefaultDescriptor())
|
||||
finalMapping = mapping;
|
||||
else if (isAllowDuplicateMappings())
|
||||
{
|
||||
|
@ -1384,9 +1344,9 @@ public class ServletHandler extends ScopedHandler
|
|||
else
|
||||
{
|
||||
//existing candidate isn't a default, if the one we're looking at isn't a default either, then its an error
|
||||
if (!mapping.isDefault())
|
||||
if (!mapping.isFromDefaultDescriptor())
|
||||
{
|
||||
ServletHolder finalMappedServlet = _servletNameMap.get(finalMapping.getServletName());
|
||||
ServletHolder finalMappedServlet = getServlet(finalMapping.getServletName());
|
||||
throw new IllegalStateException("Multiple servlets map to path " +
|
||||
pathSpec + ": " +
|
||||
finalMappedServlet.getName() + "[mapped:" + finalMapping.getSource() + "]," +
|
||||
|
@ -1403,22 +1363,21 @@ public class ServletHandler extends ScopedHandler
|
|||
pathSpec,
|
||||
finalMapping.getSource(),
|
||||
finalMapping.getServletName(),
|
||||
_servletNameMap.get(finalMapping.getServletName()).getSource());
|
||||
getServlet(finalMapping.getServletName()).getSource());
|
||||
|
||||
pm.put(new ServletPathSpec(pathSpec), _servletNameMap.get(finalMapping.getServletName()));
|
||||
ServletPathSpec servletPathSpec = new ServletPathSpec(pathSpec);
|
||||
MappedServlet mappedServlet = new MappedServlet(servletPathSpec, getServlet(finalMapping.getServletName()));
|
||||
pm.put(servletPathSpec, mappedServlet);
|
||||
}
|
||||
|
||||
_servletPathMap = pm;
|
||||
}
|
||||
|
||||
// flush filter chain cache
|
||||
if (_chainCache != null)
|
||||
for (int i = _chainCache.length; i-- > 0; )
|
||||
{
|
||||
for (int i = _chainCache.length; i-- > 0; )
|
||||
{
|
||||
if (_chainCache[i] != null)
|
||||
_chainCache[i].clear();
|
||||
}
|
||||
if (_chainCache[i] != null)
|
||||
_chainCache[i].clear();
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
|
@ -1453,28 +1412,26 @@ public class ServletHandler extends ScopedHandler
|
|||
{
|
||||
if (_filters == null)
|
||||
return false;
|
||||
boolean found = false;
|
||||
for (FilterHolder f : _filters)
|
||||
{
|
||||
if (f == holder)
|
||||
found = true;
|
||||
return true;
|
||||
}
|
||||
return found;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected synchronized boolean containsServletHolder(ServletHolder holder)
|
||||
{
|
||||
if (_servlets == null)
|
||||
return false;
|
||||
boolean found = false;
|
||||
for (ServletHolder s : _servlets)
|
||||
{
|
||||
@SuppressWarnings("ReferenceEquality")
|
||||
boolean foundServletHolder = (s == holder);
|
||||
if (foundServletHolder)
|
||||
found = true;
|
||||
return true;
|
||||
}
|
||||
return found;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1731,6 +1688,68 @@ public class ServletHandler extends ScopedHandler
|
|||
_contextHandler.destroyListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* A mapping of a servlet by pathSpec or by name
|
||||
*/
|
||||
public static class MappedServlet
|
||||
{
|
||||
private final PathSpec _pathSpec;
|
||||
private final ServletHolder _servletHolder;
|
||||
private final ServletPathMapping _servletPathMapping;
|
||||
|
||||
MappedServlet(PathSpec pathSpec, ServletHolder servletHolder)
|
||||
{
|
||||
_pathSpec = pathSpec;
|
||||
_servletHolder = servletHolder;
|
||||
|
||||
// Create the HttpServletMapping only once if possible.
|
||||
if (pathSpec instanceof ServletPathSpec)
|
||||
{
|
||||
switch (pathSpec.getGroup())
|
||||
{
|
||||
case EXACT:
|
||||
case ROOT:
|
||||
_servletPathMapping = new ServletPathMapping(_pathSpec, _servletHolder.getName(), _pathSpec.getPrefix());
|
||||
break;
|
||||
default:
|
||||
_servletPathMapping = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_servletPathMapping = null;
|
||||
}
|
||||
}
|
||||
|
||||
public PathSpec getPathSpec()
|
||||
{
|
||||
return _pathSpec;
|
||||
}
|
||||
|
||||
public ServletHolder getServletHolder()
|
||||
{
|
||||
return _servletHolder;
|
||||
}
|
||||
|
||||
public ServletPathMapping getServletPathMapping(String pathInContext)
|
||||
{
|
||||
if (_servletPathMapping != null)
|
||||
return _servletPathMapping;
|
||||
if (_pathSpec != null)
|
||||
return new ServletPathMapping(_pathSpec, _servletHolder.getName(), pathInContext);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("MappedServlet%x{%s->%s}",
|
||||
hashCode(), _pathSpec == null ? null : _pathSpec.getDeclaration(), _servletHolder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class Default404Servlet extends HttpServlet
|
||||
{
|
||||
|
|
|
@ -918,7 +918,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
|||
if (mapping != null)
|
||||
{
|
||||
//if the servlet mapping was from a default descriptor, then allow it to be overridden
|
||||
if (!mapping.isDefault())
|
||||
if (!mapping.isFromDefaultDescriptor())
|
||||
{
|
||||
if (clash == null)
|
||||
clash = new HashSet<>();
|
||||
|
|
|
@ -104,12 +104,12 @@ public class ServletMapping
|
|||
}
|
||||
|
||||
@ManagedAttribute(value = "default", readonly = true)
|
||||
public boolean isDefault()
|
||||
public boolean isFromDefaultDescriptor()
|
||||
{
|
||||
return _default;
|
||||
}
|
||||
|
||||
public void setDefault(boolean fromDefault)
|
||||
public void setFromDefaultDescriptor(boolean fromDefault)
|
||||
{
|
||||
_default = fromDefault;
|
||||
}
|
||||
|
|
|
@ -257,7 +257,7 @@ public class AsyncContextTest
|
|||
assertThat("async run attr query string", responseBody, containsString("async:run:attr:queryString:dispatch=true"));
|
||||
assertThat("async run context path", responseBody, containsString("async:run:attr:contextPath:/ctx"));
|
||||
assertThat("async run request uri has correct encoding", responseBody, containsString("async:run:attr:requestURI:/ctx/test/hello%2fthere"));
|
||||
assertThat("http servlet mapping matchValue is correct", responseBody, containsString("async:run:attr:mapping:matchValue:/test"));
|
||||
assertThat("http servlet mapping matchValue is correct", responseBody, containsString("async:run:attr:mapping:matchValue:test"));
|
||||
assertThat("http servlet mapping pattern is correct", responseBody, containsString("async:run:attr:mapping:pattern:/test/*"));
|
||||
assertThat("http servlet mapping servletName is correct", responseBody, containsString("async:run:attr:mapping:servletName:"));
|
||||
assertThat("http servlet mapping mappingMatch is correct", responseBody, containsString("async:run:attr:mapping:mappingMatch:PATH"));
|
||||
|
|
|
@ -170,6 +170,43 @@ public class DispatcherTest
|
|||
assertEquals(expected, responses);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamedForward() throws Exception
|
||||
{
|
||||
_contextHandler.addServlet(NamedForwardServlet.class, "/forward/*");
|
||||
String echo = _contextHandler.addServlet(EchoURIServlet.class, "/echo/*").getName();
|
||||
|
||||
String expected =
|
||||
"HTTP/1.1 200 OK\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Content-Length: 62\r\n" +
|
||||
"\r\n" +
|
||||
"/context\r\n" +
|
||||
"/forward\r\n" +
|
||||
"/info\r\n" +
|
||||
"/context/forward/info;param=value\r\n";
|
||||
String responses = _connector.getResponse("GET /context/forward/info;param=value?name=" + echo + " HTTP/1.0\n\n");
|
||||
assertEquals(expected, responses);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamedInclude() throws Exception
|
||||
{
|
||||
_contextHandler.addServlet(NamedIncludeServlet.class, "/include/*");
|
||||
String echo = _contextHandler.addServlet(EchoURIServlet.class, "/echo/*").getName();
|
||||
|
||||
String expected =
|
||||
"HTTP/1.1 200 OK\r\n" +
|
||||
"Content-Length: 62\r\n" +
|
||||
"\r\n" +
|
||||
"/context\r\n" +
|
||||
"/include\r\n" +
|
||||
"/info\r\n" +
|
||||
"/context/include/info;param=value\r\n";
|
||||
String responses = _connector.getResponse("GET /context/include/info;param=value?name=" + echo + " HTTP/1.0\n\n");
|
||||
assertEquals(expected, responses);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForwardWithBadParams() throws Exception
|
||||
{
|
||||
|
@ -507,6 +544,24 @@ public class DispatcherTest
|
|||
}
|
||||
}
|
||||
|
||||
public static class NamedForwardServlet extends HttpServlet implements Servlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
getServletContext().getNamedDispatcher(request.getParameter("name")).forward(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
public static class NamedIncludeServlet extends HttpServlet implements Servlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
getServletContext().getNamedDispatcher(request.getParameter("name")).include(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ForwardNonUTF8Servlet extends HttpServlet implements Servlet
|
||||
{
|
||||
@Override
|
||||
|
@ -734,7 +789,7 @@ public class DispatcherTest
|
|||
assertEquals("do=assertforward&do=more&test=1", request.getAttribute(Dispatcher.FORWARD_QUERY_STRING));
|
||||
HttpServletMapping fwdMapping = (HttpServletMapping)request.getAttribute(Dispatcher.FORWARD_MAPPING);
|
||||
assertNotNull(fwdMapping);
|
||||
assertEquals("/ForwardServlet", fwdMapping.getMatchValue());
|
||||
assertEquals("ForwardServlet", fwdMapping.getMatchValue());
|
||||
|
||||
List<String> expectedAttributeNames = Arrays.asList(Dispatcher.FORWARD_REQUEST_URI, Dispatcher.FORWARD_CONTEXT_PATH,
|
||||
Dispatcher.FORWARD_SERVLET_PATH, Dispatcher.FORWARD_QUERY_STRING, Dispatcher.FORWARD_MAPPING);
|
||||
|
@ -769,7 +824,7 @@ public class DispatcherTest
|
|||
assertEquals("do=assertforward&foreign=%d2%e5%ec%ef%e5%f0%e0%f2%f3%f0%e0&test=1", request.getAttribute(Dispatcher.FORWARD_QUERY_STRING));
|
||||
HttpServletMapping fwdMapping = (HttpServletMapping)request.getAttribute(Dispatcher.FORWARD_MAPPING);
|
||||
assertNotNull(fwdMapping);
|
||||
assertEquals("/ForwardServlet", fwdMapping.getMatchValue());
|
||||
assertEquals("ForwardServlet", fwdMapping.getMatchValue());
|
||||
|
||||
List<String> expectedAttributeNames = Arrays.asList(Dispatcher.FORWARD_REQUEST_URI, Dispatcher.FORWARD_CONTEXT_PATH,
|
||||
Dispatcher.FORWARD_SERVLET_PATH, Dispatcher.FORWARD_QUERY_STRING, Dispatcher.FORWARD_MAPPING);
|
||||
|
@ -818,7 +873,7 @@ public class DispatcherTest
|
|||
assertEquals("do=end&do=the", request.getAttribute(Dispatcher.INCLUDE_QUERY_STRING));
|
||||
HttpServletMapping incMapping = (HttpServletMapping)request.getAttribute(Dispatcher.INCLUDE_MAPPING);
|
||||
assertNotNull(incMapping);
|
||||
assertEquals("/AssertIncludeServlet", incMapping.getMatchValue());
|
||||
assertEquals("AssertIncludeServlet", incMapping.getMatchValue());
|
||||
|
||||
List expectedAttributeNames = Arrays.asList(Dispatcher.INCLUDE_REQUEST_URI, Dispatcher.INCLUDE_CONTEXT_PATH,
|
||||
Dispatcher.INCLUDE_SERVLET_PATH, Dispatcher.INCLUDE_QUERY_STRING, Dispatcher.INCLUDE_MAPPING);
|
||||
|
@ -851,7 +906,7 @@ public class DispatcherTest
|
|||
assertEquals("do=include", request.getAttribute(Dispatcher.FORWARD_QUERY_STRING));
|
||||
HttpServletMapping fwdMapping = (HttpServletMapping)request.getAttribute(Dispatcher.FORWARD_MAPPING);
|
||||
assertNotNull(fwdMapping);
|
||||
assertEquals("/ForwardServlet", fwdMapping.getMatchValue());
|
||||
assertEquals("ForwardServlet", fwdMapping.getMatchValue());
|
||||
|
||||
assertEquals("/context/AssertForwardIncludeServlet/assertpath", request.getAttribute(Dispatcher.INCLUDE_REQUEST_URI));
|
||||
assertEquals("/context", request.getAttribute(Dispatcher.INCLUDE_CONTEXT_PATH));
|
||||
|
@ -860,7 +915,7 @@ public class DispatcherTest
|
|||
assertEquals("do=end", request.getAttribute(Dispatcher.INCLUDE_QUERY_STRING));
|
||||
HttpServletMapping incMapping = (HttpServletMapping)request.getAttribute(Dispatcher.INCLUDE_MAPPING);
|
||||
assertNotNull(incMapping);
|
||||
assertEquals("/AssertForwardIncludeServlet", incMapping.getMatchValue());
|
||||
assertEquals("AssertForwardIncludeServlet", incMapping.getMatchValue());
|
||||
|
||||
List expectedAttributeNames = Arrays.asList(Dispatcher.FORWARD_REQUEST_URI, Dispatcher.FORWARD_CONTEXT_PATH, Dispatcher.FORWARD_SERVLET_PATH,
|
||||
Dispatcher.FORWARD_PATH_INFO, Dispatcher.FORWARD_QUERY_STRING, Dispatcher.FORWARD_MAPPING,
|
||||
|
@ -902,7 +957,7 @@ public class DispatcherTest
|
|||
assertEquals("do=forward", request.getAttribute(Dispatcher.FORWARD_QUERY_STRING));
|
||||
HttpServletMapping fwdMapping = (HttpServletMapping)request.getAttribute(Dispatcher.FORWARD_MAPPING);
|
||||
assertNotNull(fwdMapping);
|
||||
assertEquals("/IncludeServlet", fwdMapping.getMatchValue());
|
||||
assertEquals("IncludeServlet", fwdMapping.getMatchValue());
|
||||
|
||||
List expectedAttributeNames = Arrays.asList(Dispatcher.FORWARD_REQUEST_URI, Dispatcher.FORWARD_CONTEXT_PATH, Dispatcher.FORWARD_SERVLET_PATH,
|
||||
Dispatcher.FORWARD_PATH_INFO, Dispatcher.FORWARD_QUERY_STRING, Dispatcher.FORWARD_MAPPING);
|
||||
|
|
|
@ -1376,9 +1376,9 @@ public class ServletContextHandlerTest
|
|||
|
||||
root.addBean(new MySCIStarter(root.getServletContext(), new JSPAddingSCI()), true);
|
||||
_server.start();
|
||||
MappedResource<ServletHolder> mappedServlet = root.getServletHandler().getMappedServlet("/somejsp/xxx");
|
||||
assertNotNull(mappedServlet.getResource());
|
||||
assertEquals("some.jsp", mappedServlet.getResource().getName());
|
||||
ServletHandler.MappedServlet mappedServlet = root.getServletHandler().getMappedServlet("/somejsp/xxx");
|
||||
assertNotNull(mappedServlet.getServletHolder());
|
||||
assertEquals("some.jsp", mappedServlet.getServletHolder().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1452,9 +1452,9 @@ public class ServletContextHandlerTest
|
|||
|
||||
root.addBean(new MySCIStarter(root.getServletContext(), new JSPAddingSCI()), true);
|
||||
_server.start();
|
||||
MappedResource<ServletHolder> mappedServlet = root.getServletHandler().getMappedServlet("/bar/xxx");
|
||||
assertNotNull(mappedServlet.getResource());
|
||||
assertEquals("some.jsp", mappedServlet.getResource().getName());
|
||||
ServletHandler.MappedServlet mappedServlet = root.getServletHandler().getMappedServlet("/bar/xxx");
|
||||
assertNotNull(mappedServlet.getServletHolder());
|
||||
assertEquals("some.jsp", mappedServlet.getServletHolder().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -79,17 +79,17 @@ public class ServletHandlerTest
|
|||
fm5.setFilterHolder(fh5);
|
||||
|
||||
sh1.setName("s1");
|
||||
sm1.setDefault(false);
|
||||
sm1.setFromDefaultDescriptor(false);
|
||||
sm1.setPathSpec("/foo/*");
|
||||
sm1.setServletName("s1");
|
||||
|
||||
sh2.setName("s2");
|
||||
sm2.setDefault(false);
|
||||
sm2.setFromDefaultDescriptor(false);
|
||||
sm2.setPathSpec("/foo/*");
|
||||
sm2.setServletName("s2");
|
||||
|
||||
sh3.setName("s3");
|
||||
sm3.setDefault(true);
|
||||
sm3.setFromDefaultDescriptor(true);
|
||||
sm3.setPathSpec("/foo/*");
|
||||
sm3.setServletName("s3");
|
||||
}
|
||||
|
@ -251,9 +251,9 @@ public class ServletHandlerTest
|
|||
|
||||
handler.updateMappings();
|
||||
|
||||
MappedResource<ServletHolder> entry = handler.getMappedServlet("/foo/*");
|
||||
ServletHandler.MappedServlet entry = handler.getMappedServlet("/foo/*");
|
||||
assertNotNull(entry);
|
||||
assertEquals("s1", entry.getResource().getName());
|
||||
assertEquals("s1", entry.getServletHolder().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -292,9 +292,9 @@ public class ServletHandlerTest
|
|||
handler.addServletMapping(sm2);
|
||||
handler.updateMappings();
|
||||
|
||||
MappedResource<ServletHolder> entry = handler.getMappedServlet("/foo/*");
|
||||
ServletHandler.MappedServlet entry = handler.getMappedServlet("/foo/*");
|
||||
assertNotNull(entry);
|
||||
assertEquals("s2", entry.getResource().getName());
|
||||
assertEquals("s2", entry.getServletHolder().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -1200,7 +1200,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
|
|||
{
|
||||
ServletMapping mapping = new ServletMapping(new Source(Source.Origin.DESCRIPTOR, descriptor.getResource().toString()));
|
||||
mapping.setServletName(servletName);
|
||||
mapping.setDefault(descriptor instanceof DefaultsDescriptor);
|
||||
mapping.setFromDefaultDescriptor(descriptor instanceof DefaultsDescriptor);
|
||||
|
||||
List<String> paths = new ArrayList<String>();
|
||||
Iterator<XmlParser.Node> iter = node.iterator("url-pattern");
|
||||
|
@ -1221,9 +1221,9 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
|
|||
{
|
||||
//The same path has been mapped multiple times, either to a different servlet or the same servlet.
|
||||
//If its a different servlet, this is only valid to do if the old mapping was from a default descriptor.
|
||||
if (p.equals(ps) && (sm.isDefault() || servletName.equals(sm.getServletName())))
|
||||
if (p.equals(ps) && (sm.isFromDefaultDescriptor() || servletName.equals(sm.getServletName())))
|
||||
{
|
||||
if (sm.isDefault())
|
||||
if (sm.isFromDefaultDescriptor())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} in mapping {} from defaults descriptor is overridden by ", ps, sm, servletName);
|
||||
|
|
Loading…
Reference in New Issue