Index: appserver/security/webintegration/src/main/java/com/sun/web/security/RequestFacadeWrapper.java =================================================================== --- appserver/security/webintegration/src/main/java/com/sun/web/security/RequestFacadeWrapper.java (revision 64736) +++ appserver/security/webintegration/src/main/java/com/sun/web/security/RequestFacadeWrapper.java (working copy) @@ -107,6 +107,11 @@ } @Override + public ServletMapping getServletMapping() { + return servletRequest.getServletMapping(); + } + + @Override public String getPathInfo() { return servletRequest.getPathInfo(); } @@ -402,4 +407,4 @@ return servletRequest.getDispatcherType(); } -} \ No newline at end of file +} Index: appserver/web/web-core/src/main/java/org/apache/catalina/connector/MappingImpl.java =================================================================== --- appserver/web/web-core/src/main/java/org/apache/catalina/connector/MappingImpl.java (nonexistent) +++ appserver/web/web-core/src/main/java/org/apache/catalina/connector/MappingImpl.java (working copy) @@ -0,0 +1,192 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 1997-2017 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.catalina.connector; + +import java.io.Serializable; +import java.util.Objects; +import java.util.ResourceBundle; + +import javax.servlet.http.MappingMatch; +import javax.servlet.http.ServletMapping; + +import org.glassfish.grizzly.http.server.util.MappingData; + +import org.apache.catalina.LogFacade; + +public class MappingImpl implements ServletMapping, Serializable { + + private static final long serialVersionUID = -5134622427867249518L; + + private String matchValue; + + private String pattern; + + private String servletName; + + private MappingMatch mappingMatch; + + private static final ResourceBundle rb = LogFacade.getLogger().getResourceBundle(); + + public MappingImpl(MappingData mappingData) { + if (null == mappingData) { + throw new NullPointerException(rb.getString(LogFacade.MAPPING_ERROR_EXCEPTION)); + } + + // Trim leading "/" + matchValue = (null != mappingData.matchedPath) && + (mappingData.matchedPath.length() >= 2) ? mappingData.matchedPath.substring(1) : ""; + pattern = null != mappingData.descriptorPath ? mappingData.descriptorPath : ""; + servletName = null != mappingData.servletName ? mappingData.servletName : ""; + + switch (mappingData.mappingType) { + case MappingData.CONTEXT_ROOT: + mappingMatch = MappingMatch.CONTEXT_ROOT; + break; + case MappingData.DEFAULT: + mappingMatch = MappingMatch.DEFAULT; + break; + case MappingData.EXACT: + mappingMatch = MappingMatch.EXACT; + break; + case MappingData.EXTENSION: + mappingMatch = MappingMatch.EXTENSION; + // Ensure pattern is valid + if (null != pattern && '*' == pattern.charAt(0)) { + // Mutate matchValue to mean "what * was matched with". + int i = matchValue.indexOf(pattern.substring(1)); + if (-1 != i) { + matchValue = matchValue.substring(0, i); + } + } + break; + case MappingData.PATH: + mappingMatch = MappingMatch.PATH; + // Ensure pattern is valid + if (null != pattern) { + int patternLen = pattern.length(); + if (0 < patternLen && '*' == pattern.charAt(patternLen-1)) { + if (0 <= patternLen - 2) { + // Remove the pattern from the end of matchValue + matchValue = matchValue.substring(patternLen-2); + } + } + } + break; + } + + } + + @Override + public String getMatchValue() { + return matchValue; + } + + @Override + public String getPattern() { + return pattern; + } + + @Override + public String getServletName() { + return servletName; + } + + + + @Override + public MappingMatch getMappingMatch() { + return mappingMatch; + } + + @Override + public int hashCode() { + int hash = 5; + hash = 29 * hash + Objects.hashCode(this.matchValue); + hash = 29 * hash + Objects.hashCode(this.pattern); + hash = 29 * hash + Objects.hashCode(this.servletName); + hash = 29 * hash + Objects.hashCode(this.mappingMatch); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final MappingImpl other = (MappingImpl) obj; + if (!Objects.equals(this.matchValue, other.matchValue)) { + return false; + } + if (!Objects.equals(this.pattern, other.pattern)) { + return false; + } + if (!Objects.equals(this.servletName, other.servletName)) { + return false; + } + if (this.mappingMatch != other.mappingMatch) { + return false; + } + return true; + } + + @Override + public String toString() { + return "MappingImpl{" + "matchValue=" + matchValue + + ", pattern=" + pattern + + ", servletName=" + servletName + + ", mappingMatch=" + mappingMatch + '}'; + } + + + +} Index: appserver/web/web-core/src/main/java/org/apache/catalina/connector/Request.java =================================================================== --- appserver/web/web-core/src/main/java/org/apache/catalina/connector/Request.java (revision 64736) +++ appserver/web/web-core/src/main/java/org/apache/catalina/connector/Request.java (working copy) @@ -103,6 +103,7 @@ import javax.servlet.http.WebConnection; import com.sun.appserv.ProxyHandler; +import javax.servlet.http.MappingMatch; import org.apache.catalina.Context; import org.apache.catalina.LogFacade; import org.apache.catalina.Globals; @@ -143,6 +144,7 @@ import org.glassfish.grizzly.memory.Buffers; import org.glassfish.grizzly.utils.Charsets; import org.glassfish.web.valve.GlassFishValve; +import javax.servlet.http.ServletMapping; /** * Wrapper object for the Coyote request. @@ -817,6 +819,13 @@ return info; } + @Override + public ServletMapping getServletMapping() { + ServletMapping result; + + result = new MappingImpl(mappingData); + return result; + } /** * Return mapping data. */ Index: appserver/web/web-core/src/main/java/org/apache/catalina/connector/RequestFacade.java =================================================================== --- appserver/web/web-core/src/main/java/org/apache/catalina/connector/RequestFacade.java (revision 64736) +++ appserver/web/web-core/src/main/java/org/apache/catalina/connector/RequestFacade.java (working copy) @@ -78,6 +78,7 @@ import java.security.PrivilegedAction; import java.security.SecurityPermission; import java.util.*; +import javax.servlet.http.ServletMapping; /** @@ -431,8 +432,16 @@ return request.getInputStream(); } + + public ServletMapping getServletMapping() { - @Override + if (request == null) { + throw new IllegalStateException(rb.getString(LogFacade.CANNOT_USE_REQUEST_OBJECT_OUTSIDE_SCOPE_EXCEPTION)); + } + + return request.getServletMapping(); + } + public String getParameter(String name) { if (request == null) { Index: appserver/web/web-core/src/main/java/org/apache/catalina/core/ApplicationDispatcher.java =================================================================== --- appserver/web/web-core/src/main/java/org/apache/catalina/core/ApplicationDispatcher.java (revision 64736) +++ appserver/web/web-core/src/main/java/org/apache/catalina/core/ApplicationDispatcher.java (working copy) @@ -76,6 +76,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.text.MessageFormat; +import javax.servlet.http.ServletMapping; import static org.apache.catalina.InstanceEvent.EventType.AFTER_DISPATCH_EVENT; @@ -211,7 +212,7 @@ * else null */ public ApplicationDispatcher - (Wrapper wrapper, String requestURI, String servletPath, + (Wrapper wrapper, ServletMapping mappingForDispatch, String requestURI, String servletPath, String pathInfo, String queryString, String name) { super(); @@ -218,6 +219,7 @@ // Save all of our configuration parameters this.wrapper = wrapper; + this.mappingForDispatch = mappingForDispatch; this.context = (Context) wrapper.getParent(); this.requestURI = requestURI; this.servletPath = servletPath; @@ -282,6 +284,8 @@ * or included. */ private Wrapper wrapper = null; + + private ServletMapping mappingForDispatch; // ------------------------------------------------------------- Properties @@ -1063,7 +1067,7 @@ crossContextFlag = Boolean.valueOf(crossContext); //END OF 6364900 wrapper = new ApplicationHttpRequest - (hcurrent, context, crossContext, state.dispatcherType); + (hcurrent, context, crossContext, mappingForDispatch, state.dispatcherType); } else { wrapper = new ApplicationRequest(current); } Index: appserver/web/web-core/src/main/java/org/apache/catalina/core/ApplicationHttpRequest.java =================================================================== --- appserver/web/web-core/src/main/java/org/apache/catalina/core/ApplicationHttpRequest.java (revision 64736) +++ appserver/web/web-core/src/main/java/org/apache/catalina/core/ApplicationHttpRequest.java (working copy) @@ -76,6 +76,8 @@ import javax.servlet.http.PushBuilder; import java.io.IOException; import java.util.*; +import javax.servlet.http.ServletMapping; +import org.apache.catalina.connector.MappingImpl; // END GlassFish 896 /** @@ -102,16 +104,19 @@ specials.add(RequestDispatcher.INCLUDE_REQUEST_URI); specials.add(RequestDispatcher.INCLUDE_CONTEXT_PATH); specials.add(RequestDispatcher.INCLUDE_SERVLET_PATH); + specials.add(RequestDispatcher.INCLUDE_MAPPING); specials.add(RequestDispatcher.INCLUDE_PATH_INFO); specials.add(RequestDispatcher.INCLUDE_QUERY_STRING); specials.add(RequestDispatcher.FORWARD_REQUEST_URI); specials.add(RequestDispatcher.FORWARD_CONTEXT_PATH); specials.add(RequestDispatcher.FORWARD_SERVLET_PATH); + specials.add(RequestDispatcher.FORWARD_MAPPING); specials.add(RequestDispatcher.FORWARD_PATH_INFO); specials.add(RequestDispatcher.FORWARD_QUERY_STRING); specials.add(AsyncContext.ASYNC_REQUEST_URI); specials.add(AsyncContext.ASYNC_CONTEXT_PATH); specials.add(AsyncContext.ASYNC_SERVLET_PATH); + specials.add(AsyncContext.ASYNC_MAPPING); specials.add(AsyncContext.ASYNC_PATH_INFO); specials.add(AsyncContext.ASYNC_QUERY_STRING); } @@ -131,10 +136,12 @@ public ApplicationHttpRequest(HttpServletRequest request, Context context, boolean crossContext, + ServletMapping mappingForDispatch, DispatcherType dispatcherType) { super(request); this.context = context; this.crossContext = crossContext; + this.mappingForDispatch = mappingForDispatch; this.dispatcherType = dispatcherType; setRequest(request); @@ -171,6 +178,8 @@ * behavior. */ protected boolean crossContext = false; + + private ServletMapping mappingForDispatch; /** * The dispatcher type. @@ -526,6 +535,26 @@ return (url); } + @Override + public ServletMapping getServletMapping() { + ServletMapping result = null; + switch (dispatcherType) { + case INCLUDE: + // Safe to cast because we received this in the ctor + // as an HttpServletRequest. + result = ((HttpServletRequest)getRequest()).getServletMapping(); + break; + case ASYNC: + case FORWARD: + case ERROR: + result = mappingForDispatch; + break; + default: // REQUEST + break; + } + + return result; + } /** * Override the getServletPath() method of the wrapped @@ -845,6 +874,7 @@ String pathInfo, String queryString) { specialAttributes = new HashMap(5); + ServletMapping originalMapping; switch (dispatcherType) { case INCLUDE: @@ -854,6 +884,8 @@ contextPath); specialAttributes.put(RequestDispatcher.INCLUDE_SERVLET_PATH, servletPath); + specialAttributes.put(RequestDispatcher.INCLUDE_MAPPING, + mappingForDispatch); specialAttributes.put(RequestDispatcher.INCLUDE_PATH_INFO, pathInfo); specialAttributes.put(RequestDispatcher.INCLUDE_QUERY_STRING, @@ -871,6 +903,9 @@ pathInfo); specialAttributes.put(RequestDispatcher.FORWARD_QUERY_STRING, queryString); + // Safe to cast because we received it in the ctor as HttpServletRequest + originalMapping = ((HttpServletRequest)getRequest()).getServletMapping(); + specialAttributes.put(RequestDispatcher.FORWARD_MAPPING, originalMapping); break; case ASYNC: specialAttributes.put(AsyncContext.ASYNC_REQUEST_URI, @@ -879,6 +914,10 @@ contextPath); specialAttributes.put(AsyncContext.ASYNC_SERVLET_PATH, servletPath); + // Safe to cast because we received it in the ctor as HttpServletRequest + originalMapping = ((HttpServletRequest)getRequest()).getServletMapping(); + specialAttributes.put(AsyncContext.ASYNC_MAPPING, + originalMapping); specialAttributes.put(AsyncContext.ASYNC_PATH_INFO, pathInfo); specialAttributes.put(AsyncContext.ASYNC_QUERY_STRING, Index: appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardContext.java =================================================================== --- appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardContext.java (revision 64736) +++ appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardContext.java (working copy) @@ -61,7 +61,6 @@ import org.glassfish.grizzly.http.server.util.AlternateDocBase; import org.glassfish.grizzly.http.server.util.Mapper; import org.glassfish.grizzly.http.server.util.MappingData; -import org.glassfish.pfl.basic.logex.Log; import org.apache.catalina.*; import org.apache.catalina.deploy.*; import org.apache.catalina.loader.WebappLoader; @@ -98,7 +97,6 @@ import java.io.*; import java.net.MalformedURLException; import java.net.URLDecoder; -import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; import java.text.MessageFormat; @@ -107,7 +105,8 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; -import java.util.logging.Logger; +import javax.servlet.http.ServletMapping; +import org.apache.catalina.connector.MappingImpl; import org.glassfish.grizzly.http.util.CharChunk; import org.glassfish.grizzly.http.util.MessageBytes; @@ -6998,7 +6997,7 @@ if (wrapper == null) return (null); - return new ApplicationDispatcher(wrapper, null, null, null, null, name); + return new ApplicationDispatcher(wrapper, null, null, null, null, null, name); } @@ -7400,12 +7399,13 @@ Wrapper wrapper = (Wrapper) mappingData.wrapper; String wrapperPath = mappingData.wrapperPath.toString(); String pathInfo = mappingData.pathInfo.toString(); + ServletMapping mappingForDispatch = new MappingImpl(mappingData); mappingData.recycle(); // Construct a RequestDispatcher to process this request return new ApplicationDispatcher - (wrapper, uriCC.toString(), wrapperPath, pathInfo, + (wrapper, mappingForDispatch, uriCC.toString(), wrapperPath, pathInfo, queryString, null); } Index: appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardWrapper.java =================================================================== --- appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardWrapper.java (revision 64736) +++ appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardWrapper.java (working copy) @@ -264,8 +264,7 @@ * Are we unloading our servlet instance at the moment? */ private boolean unloading = false; - - + /** * Maximum number of STM instances. */ @@ -746,8 +745,7 @@ } else return (true); } - - + /** * Gets the names of the methods supported by the underlying servlet. *