diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java index c310dfc0036..0ad7e061bc7 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java @@ -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; diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java index c8e5d29516f..3572e08185d 100644 --- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java +++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java @@ -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); diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorProcessor.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorProcessor.java index 386c0258187..b2e13e269a4 100644 --- a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorProcessor.java +++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorProcessor.java @@ -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); } } diff --git a/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/TestQuickStart.java b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/TestQuickStart.java index ba0541986d1..5ae648a5f82 100644 --- a/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/TestQuickStart.java +++ b/jetty-quickstart/src/test/java/org/eclipse/jetty/quickstart/TestQuickStart.java @@ -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()); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncAttributes.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncAttributes.java index ebbbc32ac91..4856a99fa5d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncAttributes.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncAttributes.java @@ -21,30 +21,25 @@ package org.eclipse.jetty.server; import java.util.HashSet; import java.util.Set; import javax.servlet.AsyncContext; -import javax.servlet.http.HttpServletMapping; 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 @@ -57,13 +52,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); } @@ -73,18 +68,12 @@ class AsyncAttributes extends Attributes.Wrapper public Set getAttributeNameSet() { Set 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; } @@ -94,54 +83,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); - } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java index 8f6ff444fd0..086ba3cb16a 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java @@ -26,7 +26,6 @@ import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -101,14 +100,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 +139,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 old_query_params = baseRequest.getQueryParameters(); final Attributes old_attr = baseRequest.getAttributes(); @@ -163,30 +155,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 +182,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 +246,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 +270,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 +306,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 +320,11 @@ public class Dispatcher implements RequestDispatcher @Override public void setAttribute(String key, Object value) { - if (_named == null && key.startsWith("javax.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 +348,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 +371,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 +381,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 +402,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,39 +416,11 @@ public class Dispatcher implements RequestDispatcher @Override public void setAttribute(String key, Object value) { - if (_named == null && key.startsWith("javax.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); + if (_servletPathMapping == null && _named == null && INCLUDE_MAPPING.equals(key)) + _servletPathMapping = (ServletPathMapping)value; else + // Allow any attribute to be set, even if a reserved name. If a reserved + // name is set here, it will be revealed after the include is complete. _attributes.setAttribute(key, value); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index e2790df11ca..8f39b9a7900 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -63,7 +63,6 @@ import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpUpgradeHandler; -import javax.servlet.http.MappingMatch; import javax.servlet.http.Part; import javax.servlet.http.PushBuilder; @@ -83,8 +82,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 +190,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 _requestAttributeListeners = new ArrayList<>(); private final HttpInput _input; @@ -283,7 +201,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 +1759,6 @@ public class Request implements HttpServletRequest _queryParameters = null; _contentParameters = null; _parameters = null; - _pathSpec = null; _contentParamsExtracted = false; _inputState = INPUT_NONE; _multiParts = null; @@ -1925,50 +1842,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 +2345,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; } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletAttributes.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletAttributes.java index d7126d189fa..cc25c125555 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletAttributes.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletAttributes.java @@ -20,19 +20,24 @@ package org.eclipse.jetty.server; import java.util.Set; -import javax.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() diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletPathMapping.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletPathMapping.java new file mode 100644 index 00000000000..a1c5541088e --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletPathMapping.java @@ -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 javax.servlet.http.HttpServletMapping; +import javax.servlet.http.HttpServletRequest; +import javax.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 javax.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 + + "}"; + } +} diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java index a23c4c8aef4..a38af17e0cb 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java @@ -47,6 +47,7 @@ import javax.servlet.http.HttpServletMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import javax.servlet.http.MappingMatch; import javax.servlet.http.Part; import javax.servlet.http.PushBuilder; @@ -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(); 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 8db55db6ec0..57b9ae0d389 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 @@ -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 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; diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Invoker.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Invoker.java index 75a77c9ed0a..17ae35dea14 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Invoker.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Invoker.java @@ -31,7 +31,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.pathmap.MappedResource; import org.eclipse.jetty.server.Dispatcher; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; @@ -71,7 +70,7 @@ public class Invoker extends HttpServlet private ContextHandler _contextHandler; private ServletHandler _servletHandler; - private MappedResource _invokerEntry; + private ServletHandler.MappedServlet _invokerEntry; private Map _parameters; private boolean _nonContextServlets; private boolean _verbose; @@ -171,12 +170,12 @@ public class Invoker extends HttpServlet // Check for existing mapping (avoid threaded race). String path = URIUtil.addPaths(servletPath, servlet); - MappedResource 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 { 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 47570d37a4f..69c2340937f 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 @@ -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 _filterPathMappings; private MultiMap _filterNameMappings; - private final Map _servletNameMap = new HashMap<>(); - private PathMappings _servletPathMap; + private final Map _servletNameMap = new HashMap<>(); + private PathMappings _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 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 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 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 getMappedServlet(String target) + public MappedServlet getMappedServlet(String target) { if (target.startsWith("/")) { if (_servletPathMap == null) return null; - return _servletPathMap.getMatch(target); + + MappedResource 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 cache = _chainCache[dispatch]; final Queue 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 pm = new PathMappings<>(); + PathMappings pm = new PathMappings<>(); //create a map of paths to set of ServletMappings that define that mapping HashMap> sms = new HashMap<>(); @@ -1338,12 +1303,7 @@ public class ServletHandler extends ScopedHandler { for (String pathSpec : pathSpecs) { - List mappings = sms.get(pathSpec); - if (mappings == null) - { - mappings = new ArrayList<>(); - sms.put(pathSpec, mappings); - } + List 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 { 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 ad185ff6488..4e42bb6f014 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 @@ -918,7 +918,7 @@ public class ServletHolder extends Holder 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<>(); diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java index b4a9a2a68ae..8bd15c87492 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java @@ -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; } diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java index 48cf1380151..2c50289dfd8 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java @@ -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")); diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java index 8c886a54149..a6dcb6e8a9f 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java @@ -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 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 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); diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java index bef8ceef9a4..643fd6bc65c 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java @@ -62,7 +62,6 @@ import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionIdListener; import javax.servlet.http.HttpSessionListener; -import org.eclipse.jetty.http.pathmap.MappedResource; import org.eclipse.jetty.logging.StacklessLogging; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.RoleInfo; @@ -1376,9 +1375,9 @@ public class ServletContextHandlerTest root.addBean(new MySCIStarter(root.getServletContext(), new JSPAddingSCI()), true); _server.start(); - MappedResource 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 +1451,9 @@ public class ServletContextHandlerTest root.addBean(new MySCIStarter(root.getServletContext(), new JSPAddingSCI()), true); _server.start(); - MappedResource 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 diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java index fa5736a2619..25d635f66c6 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java @@ -21,7 +21,6 @@ package org.eclipse.jetty.servlet; import java.util.EnumSet; import javax.servlet.DispatcherType; -import org.eclipse.jetty.http.pathmap.MappedResource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -79,17 +78,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 +250,9 @@ public class ServletHandlerTest handler.updateMappings(); - MappedResource 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 +291,9 @@ public class ServletHandlerTest handler.addServletMapping(sm2); handler.updateMappings(); - MappedResource entry = handler.getMappedServlet("/foo/*"); + ServletHandler.MappedServlet entry = handler.getMappedServlet("/foo/*"); assertNotNull(entry); - assertEquals("s2", entry.getResource().getName()); + assertEquals("s2", entry.getServletHolder().getName()); } @Test diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java index 44e4e411463..ca6942a810a 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java @@ -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 paths = new ArrayList(); Iterator 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);