Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    *
    * Copyright 1997-2008 Sun Microsystems, Inc. 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.html
   * or glassfish/bootstrap/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 glassfish/bootstrap/legal/LICENSE.txt.
   * Sun designates this particular file as subject to the "Classpath" exception
   * as provided by Sun in the GPL Version 2 section of the License file that
   * accompanied this code.  If applicable, add the following below the License
   * Header, with the fields enclosed by brackets [] replaced by your own
   * identifying information: "Portions Copyrighted [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.
   *
   *
   * This file incorporates work covered by the following copyright and
   * permission notice:
   *
   * Copyright 2004 The Apache Software Foundation
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * 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.tomcat.util.http.mapper;
  
  
  import  org.apache.catalina.core.AlternateDocBase;
  // START GlassFish 1024
  import java.util.HashMap;
  // END GlassFish 1024
  import java.util.List;
Mapper, which implements the servlet API mapping rules (which are derived from the HTTP rules).

Author(s):
Remy Maucherat
  
  public final class Mapper {
  
  
      private static com.sun.org.apache.commons.logging.Log logger =
          com.sun.org.apache.commons.logging.LogFactory.getLog(Mapper.class);
      // ----------------------------------------------------- Instance Variables
  

    
Array containing the virtual hosts definitions.
  
      protected Host[] hosts = new Host[0];


    
Default host name.
  
      protected String defaultHostName = null;

    
Context associated with this wrapper, used for wrapper mapping.
  
     protected Context context = new Context();
 
 
     // START GlassFish 1024
     private HashMap defaultContextPathsMap = new HashMap();
     // END GlassFish 1024
 
    
Indicates whether or not this class handles directory redirection. Set to false, if directory redirection (for requests that aren't / terminated) is handled by the default servlet.
 
     private static boolean handleFolderRedirects = true;
 
     // --------------------------------------------------------- Public Methods
 

    
Get default host.

Returns:
Default host name
 
     public String getDefaultHostName() {
         return ;
     }


    
Set default host.

Parameters:
defaultHostName Default host name
 
     public void setDefaultHostName(String defaultHostName) {
         this. = defaultHostName;
     }

    
Sets whether or not this Mapper redirects directory requests that aren't / terminated.

Parameters:
redirect true if this Mapper should redirect such requests, false if the default servlet handles such requests.
 
     public static void setHandleFolderRedirects(boolean redirect) {
          = redirect;
     }

    
Returns whether or not this Mapper redirects directory requests that aren't / terminated.
 
     public static boolean isHandleFolderRedirects() {
         return ;
     }

    
Add a new host to the mapper.

Parameters:
name Virtual host name
host Host object
 
     public synchronized void addHost(String nameString[] aliases,
                                      Object host) {
 
         Host[] newHosts = new Host[. + 1];
         Host newHost = new Host();
         ContextList contextList = new ContextList();
         // START GlassFish 1024
         Context[] defaultContexts = new Context[1];
         String[] defaultContextPaths = new String[1];
         // END GlassFish 1024
         newHost.name = name;
         newHost.contextList = contextList;
         newHost.object = host;
         // START GlassFish 1024
         newHost.defaultContexts = defaultContexts;
         newHost.defaultContextPaths = defaultContextPaths;
         // END GlassFish 1024
         if (insertMap(newHostsnewHost)) {
              = newHosts;
         }
         for (int i = 0; i < aliases.lengthi++) {
             newHosts = new Host[. + 1];
             newHost = new Host();
             newHost.name = aliases[i];
             newHost.contextList = contextList;
             // START GlassFish 1024
             newHost.defaultContexts = defaultContexts;
             newHost.defaultContextPaths = defaultContextPaths;
             // END GlassFish 1024
             newHost.object = host;
             if (insertMap(newHostsnewHost)) {
                  = newHosts;
             }
         }
 
         // START GlassFish 1024
         String defaultContextPath = (String.get(name);
         if (defaultContextPath != null) {
             newHost.defaultContextPaths[0] = defaultContextPath;
 	}
         // END GlassFish 1024
     }


    
Remove a host from the mapper.

Parameters:
name Virtual host name
 
     public synchronized void removeHost(String name) {
         // Find and remove the old host
         int pos = find(name);
         if (pos < 0) {
             return;
         }
         Object host = [pos].;
         Host[] newHosts = new Host[. - 1];
         if (removeMap(newHostsname)) {
              = newHosts;
         }
         // Remove all aliases (they will map to the same host object)
         for (int i = 0; i < newHosts.lengthi++) {
             if (newHosts[i]. == host) {
                 Host[] newHosts2 = new Host[. - 1];
                 if (removeMap(newHosts2newHosts[i].)) {
                      = newHosts2;
                 }
             }
         }
 
         // START GlassFish 1024
         .remove(name);
         // END GlassFish 1024
     }
 
     public String[] getHosts() {
         String hostN[] = new String[.];
         forint i = 0; i < .i++ ) {
             hostN[i] = [i].;
         }
         return hostN;
     }


    
Set context, used for wrapper mapping (request dispatcher).

Parameters:
welcomeResources Welcome files defined for this context
resources Static resources of the context
 
     public void setContext(String pathString[] welcomeResources,
                            javax.naming.Context resources) {
         . = path;
         . = welcomeResources;
         . = resources;
     }


    
Add a new Context to an existing Host.

Parameters:
hostName Virtual host name this context belongs to
path Context path
context Context object
welcomeResources Welcome files defined for this context
resources Static resources of the context
 
     public void addContext
         (String hostNameString pathObject context,
          String[] welcomeResourcesjavax.naming.Context resources,
          ArrayList<AlternateDocBase> alternateDocBases) {
 
         Host[] hosts = this.;
         int pos = find(hostshostName);
         ifpos <0 ) {
             addHost(hostNamenew String[0], "");
             hosts = this.;
             pos = find(hostshostName);
         }
         if (pos < 0) {
             .error("No host found: " + hostName);
         }
         Host host = hosts[pos];
         if (host.name.equals(hostName)) {
             int slashCount = slashCount(path);
             synchronized (host) {
                 Context[] contexts = host.contextList.contexts;
                 // Update nesting
                 if (slashCount > host.contextList.nesting) {
                     host.contextList.nesting = slashCount;
                 }
                 Context[] newContexts = new Context[contexts.length + 1];
                 Context newContext = new Context();
                 newContext.name = path;
                 newContext.object = context;
                 newContext.welcomeResources = welcomeResources;
                 newContext.resources = resources;
                 newContext.alternateDocBases = alternateDocBases;
                 if (insertMap(contextsnewContextsnewContext)) {
                     host.contextList.contexts = newContexts;
                     // START GlassFish 1024
                     if (path.equals(host.defaultContextPaths[0])) {
                         host.defaultContexts[0] = newContext;
                     }
                     // END GlassFish 1024
                 }
             }
         }
     }


    
Remove a context from an existing host.

Parameters:
hostName Virtual host name this context belongs to
path Context path
 
     public void removeContext(String hostNameString path) {
         Host[] hosts = this.;
         int pos = find(hostshostName);
         if (pos < 0) {
             return;
         }
         Host host = hosts[pos];
         if (host.name.equals(hostName)) {
             synchronized (host) {
                 Context[] contexts = host.contextList.contexts;
                 ifcontexts.length == 0 ){
                     return;
                 }
                 Context[] newContexts = new Context[contexts.length - 1];
                 if (removeMap(contextsnewContextspath)) {
                     host.contextList.contexts = newContexts;
                     // Recalculate nesting
                     host.contextList.nesting = 0;
                     for (int i = 0; i < newContexts.lengthi++) {
                         int slashCount = slashCount(newContexts[i].);
                         if (slashCount > host.contextList.nesting) {
                             host.contextList.nesting = slashCount;
                         }
                     }
                 }
             }
         }
     }


    
Return all contexts, in //HOST/PATH form

Returns:
The context names
 
     public String[] getContextNames() {
         List list=new ArrayList();
         forint i=0; i<.i++ ) {
             forint j=0; j<[i]...lengthj++ ) {
                 String cname=[i]..[j].;
                 list.add("//" + [i]. +
                         (cname.startsWith("/") ? cname : "/"));
             }
         }
         String res[] = new String[list.size()];
         return (String[])list.toArray(res);
     }


    
Add a new Wrapper to an existing Context.

Parameters:
hostName Virtual host name this wrapper belongs to
contextPath Context path this wrapper belongs to
path Wrapper mapping
wrapper Wrapper object
 
     public void addWrapper(String hostNameString contextPathString path,
                            Object wrapper) {
         addWrapper(hostNamecontextPathpathwrapperfalse);
     }
 
 
     public void addWrapper(String hostNameString contextPathString path,
                            Object wrapperboolean jspWildCard) {
         Host[] hosts = this.;
         int pos = find(hostshostName);
         if (pos < 0) {
             return;
         }
         Host host = hosts[pos];
         if (host.name.equals(hostName)) {
             Context[] contexts = host.contextList.contexts;
             int pos2 = find(contextscontextPath);
             ifpos2<0 ) {
                 .error("No context found: " + contextPath );
                 return;
             }
             Context context = contexts[pos2];
             if (context.name.equals(contextPath)) {
                 addWrapper(contextpathwrapperjspWildCard);
             }
         }
     }


    
Add a wrapper to the context associated with this wrapper.

Parameters:
path Wrapper mapping
wrapper The Wrapper object
 
     public void addWrapper(String pathObject wrapper) {
         addWrapper(pathwrapper);
     }
 
 
     public void addWrapper(String pathObject wrapperboolean jspWildCard) {
         addWrapper(pathwrapperjspWildCard);
     }
 
 
     protected void addWrapper(Context contextString pathObject wrapper) {
         addWrapper(contextpathwrapperfalse);
     }


    
Adds a wrapper to the given context.

Parameters:
context The context to which to add the wrapper
path Wrapper mapping
wrapper The Wrapper object
jspWildCard true if the wrapper corresponds to the JspServlet and the mapping path contains a wildcard; false otherwise
 
     protected void addWrapper(Context contextString pathObject wrapper,
                               boolean jspWildCard) {
 
         synchronized (context) {
             Wrapper newWrapper = new Wrapper();
             newWrapper.object = wrapper;
             newWrapper.jspWildCard = jspWildCard;
             if (path.endsWith("/*")) {
                 // Wildcard wrapper
                 newWrapper.name = path.substring(0, path.length() - 2);
                 Wrapper[] oldWrappers = context.wildcardWrappers;
                 Wrapper[] newWrappers =
                     new Wrapper[oldWrappers.length + 1];
                 if (insertMap(oldWrappersnewWrappersnewWrapper)) {
                     context.wildcardWrappers = newWrappers;
                     int slashCount = slashCount(newWrapper.name);
                     if (slashCount > context.nesting) {
                         context.nesting = slashCount;
                     }
                 }
             } else if (path.startsWith("*.")) {
                 // Extension wrapper
                 newWrapper.name = path.substring(2);
                 Wrapper[] oldWrappers = context.extensionWrappers;
                 Wrapper[] newWrappers =
                     new Wrapper[oldWrappers.length + 1];
                 if (insertMap(oldWrappersnewWrappersnewWrapper)) {
                     context.extensionWrappers = newWrappers;
                 }
             } else if (path.equals("/")) {
                 // Default wrapper
                 newWrapper.name = "";
                 context.defaultWrapper = newWrapper;
             } else {
                 // Exact wrapper
                 newWrapper.name = path;
                 Wrapper[] oldWrappers = context.exactWrappers;
                 Wrapper[] newWrappers =
                     new Wrapper[oldWrappers.length + 1];
                 if (insertMap(oldWrappersnewWrappersnewWrapper)) {
                     context.exactWrappers = newWrappers;
                 }
             }
         }
     }


    
Remove a wrapper from the context associated with this wrapper.

Parameters:
path Wrapper mapping
 
     public void removeWrapper(String path) {
         removeWrapper(path);
     }


    
Remove a wrapper from an existing context.

Parameters:
hostName Virtual host name this wrapper belongs to
contextPath Context path this wrapper belongs to
path Wrapper mapping
 
     public void removeWrapper
         (String hostNameString contextPathString path) {
         Host[] hosts = this.;
         int pos = find(hostshostName);
         if (pos < 0) {
             return;
         }
         Host host = hosts[pos];
         if (host.name.equals(hostName)) {
             Context[] contexts = host.contextList.contexts;
             int pos2 = find(contextscontextPath);
             if (pos2 < 0) {
                 return;
             }
             Context context = contexts[pos2];
             if (context.name.equals(contextPath)) {
                 removeWrapper(contextpath);
             }
         }
     }
 
     protected void removeWrapper(Context contextString path) {
         synchronized (context) {
             if (path.endsWith("/*")) {
                 // Wildcard wrapper
                 String name = path.substring(0, path.length() - 2);
                 Wrapper[] oldWrappers = context.wildcardWrappers;
                 Wrapper[] newWrappers =
                     new Wrapper[oldWrappers.length - 1];
                 if (removeMap(oldWrappersnewWrappersname)) {
                     // Recalculate nesting
                     context.nesting = 0;
                     for (int i = 0; i < newWrappers.lengthi++) {
                         int slashCount = slashCount(newWrappers[i].);
                         if (slashCount > context.nesting) {
                             context.nesting = slashCount;
                         }
                     }
                     context.wildcardWrappers = newWrappers;
                 }
             } else if (path.startsWith("*.")) {
                 // Extension wrapper
                 String name = path.substring(2);
                 Wrapper[] oldWrappers = context.extensionWrappers;
                 Wrapper[] newWrappers =
                     new Wrapper[oldWrappers.length - 1];
                 if (removeMap(oldWrappersnewWrappersname)) {
                     context.extensionWrappers = newWrappers;
                 }
             } else if (path.equals("/")) {
                 // Default wrapper
                 context.defaultWrapper = null;
             } else {
                 // Exact wrapper
                 String name = path;
                 Wrapper[] oldWrappers = context.exactWrappers;
                 Wrapper[] newWrappers =
                     new Wrapper[oldWrappers.length - 1];
                 if (removeMap(oldWrappersnewWrappersname)) {
                     context.exactWrappers = newWrappers;
                 }
             }
         }
     }
 
     public String getWrappersStringString hostString context ) {
         String names[]=getWrapperNames(hostcontext);
         StringBuffer sb=new StringBuffer();
         forint i=0; i<names.lengthi++ ) {
             sb.append(names[i]).append(":");
         }
         return sb.toString();
     }
 
     public String[] getWrapperNamesString hostString context ) {
         List list=new ArrayList();
         ifhost==null ) host="";
         ifcontext==null ) context="";
         forint i=0; i<.i++ ) {
             if( ! host.equals[i]. ))
                 continue;
             forint j=0; j<[i]...lengthj++ ) {
                 if( ! context.equals[i]..[j].))
                     continue;
                 // found the context
                 Context ctx=[i]..[j];
                 list.addctx.defaultWrapper.path);
                 forint k=0; k<ctx.exactWrappers.lengthk++ ) {
                     list.addctx.exactWrappers[k].);
                 }
                 forint k=0; k<ctx.wildcardWrappers.lengthk++ ) {
                     list.addctx.wildcardWrappers[k]. + "*");
                 }
                 forint k=0; k<ctx.extensionWrappers.lengthk++ ) {
                     list.add"*." + ctx.extensionWrappers[k].);
                 }
             }
         }
         String res[]=new String[list.size()];
         return (String[])list.toArray(res);
     }
 
 
     // START GlassFish 1024
     
Configures the given virtual server with the given default context path. The given default path corresponds to the context path of one of the web contexts deployed on the virtual server that has been designated as the virtual server's new default-web-module.

Throws:
Exception if there is no web context deployed on the given virtual server that matches the given default context path
 
     public void setDefaultContextPath(String hostName,
                                       String defaultContextPath)
             throws Exception {
 
         if (defaultContextPath != null) {
             .put(hostNamedefaultContextPath);
         }
 
         int pos = find(hostName);
         if (pos < 0) {
             return;
         }
 
         [pos].[0] = defaultContextPath;
 
         if (defaultContextPath != null) {
             addDefaultContext([pos], defaultContextPath);
         } else {
             [pos].[0] = null;
             .remove(hostName);
         }
     }


    
Configures the given virtual server with the given default context path. The given default path corresponds to the context path of one of the web contexts deployed on the virtual server that has been designated as the virtual server's new default-web-module.

Throws:
Exception if there is no web context deployed on the given virtual server that matches the given default context path
 
     private void addDefaultContext(Host hostString defaultContextPath)
             throws Exception {
 
         boolean defaultContextFound = false;
 
         Context[] contexts = host.contextList.contexts;
 
         if (contexts != null) {
             for (int i=0; i<contexts.lengthi++) {
                 if (contexts[i]..equals(defaultContextPath)) {
                     host.defaultContexts[0] = contexts[i];
                     defaultContextFound = true;
                     break;
                 }
             }
         }
 
         if (!defaultContextFound) {
             throw new Exception("No context matching " + defaultContextPath
                                 + " deployed on virtual server "
                                 + host.name);
         }
     }
     // END GlassFish 1024
 

    
Map the specified host name and URI, mutating the given mapping data.

Parameters:
host Virtual host name
uri URI
mappingData This structure will contain the result of the mapping operation
 
     public void map(MessageBytes hostMessageBytes uri,
                     MappingData mappingData)
         throws Exception {
 
         if (host.isNull()) {
             host.getCharChunk().append();
         }
         host.toChars();
         uri.toChars();
         internalMap(host.getCharChunk(), uri.getCharChunk(), mappingData);
 
     }


    
Map the specified URI relative to the context, mutating the given mapping data.

Parameters:
uri URI
mappingData This structure will contain the result of the mapping operation
 
     public void map(MessageBytes uriMappingData mappingData)
         throws Exception {
 
         uri.toChars();
         CharChunk uricc = uri.getCharChunk();
         uricc.setLimit(-1);
         internalMapWrapper(uriccmappingData);
 
     }
 
 
     // -------------------------------------------------------- Private Methods
 

    
Map the specified URI.
 
     private final void internalMap(CharChunk hostCharChunk uri,
                                    MappingData mappingData)
         throws Exception {
 
         uri.setLimit(-1);
 
         Context[] contexts = null;
         Context context = null;
         int nesting = 0;
        
         int hostPos = -1;
 
         // Virtual host mapping
         if (mappingData.host == null) {
             Host[] hosts = this.;
             int pos = findIgnoreCase(hostshost);
             if ((pos != -1) && (host.equalsIgnoreCase(hosts[pos].))) {
                 mappingData.host = hosts[pos].;
                 hostPos = pos;
                 contexts = hosts[pos]..;
                 nesting = hosts[pos]..;
             } else {
                 if ( == null) {
                     return;
                 }
                 pos = find(hosts);
                 if ((pos != -1) && (.equals(hosts[pos].))) {
                     mappingData.host = hosts[pos].;
                     hostPos = pos;
                     contexts = hosts[pos]..;
                     nesting = hosts[pos]..;
                 } else {
                     return;
                 }
             }
         }
 
         // Context mapping
         if (mappingData.context == null) {
 
             // START GlassFish 1024
             boolean found = false;
             // END GlassFish 1024
 
             int pos = find(contextsuri);
             if (pos == -1) {
                 // START GlassFish 1024
                 if ([hostPos].[0] == null) {
                 // END GlassFish 1024
                     return;
                 // START GlassFish 1024
                 }
                 context = [hostPos].[0];
                 mappingData.context = context.object;
                 mappingData.contextPath.setString(context.name);
                 found = true;
                 mappingData.isDefaultContext = true;
                 // END GlassFish 1024
             }
 
             // START GlassFish 1024
             if (!found) {
             // END GlassFish 1024
                 int lastSlash = -1;
                 int uriEnd = uri.getEnd();
                 int length = -1;
                 /* GlassFish 1024
                 boolean found = false;
                 */
                 while (pos >= 0) {
                     if (uri.startsWith(contexts[pos].)) {
                         length = contexts[pos]..length();
                         if (uri.getLength() == length) {
                             found = true;
                             break;
                         } else if (uri.startsWithIgnoreCase("/"length)) {
                             found = true;
                             break;
                         }
                     }
                     if (lastSlash == -1) {
                         lastSlash = nthSlash(urinesting + 1);
                     } else {
                         lastSlash = lastSlash(uri);
                     }
                     uri.setEnd(lastSlash);
                     pos = find(contextsuri);
                 }
                 uri.setEnd(uriEnd);
 
                 if (!found) {
                     if (contexts[0]..equals("")) {
                         context = contexts[0];
                     // START GlassFish 1024
                     } else if ([hostPos].[0] != null) {
                         context = [hostPos].[0];
                         mappingData.isDefaultContext = true;
                     // END GlassFish 1024
                     }     
                 } else {
                     context = contexts[pos];
                 }
                 if (context != null) {
                     mappingData.context = context.object;
                     mappingData.contextPath.setString(context.name);
                 }
             }
         }
 
         // Wrapper mapping
         if ((context != null) && (mappingData.wrapper == null)) {
             internalMapWrapper(contexturimappingData);
         }
 
     }


    
Wrapper mapping.
 
     private final void internalMapWrapper(Context contextCharChunk path,
                                           MappingData mappingData)
         throws Exception {
 
         int pathOffset = path.getOffset();
         int pathEnd = path.getEnd();
         int servletPath = pathOffset;
         boolean noServletPath = false;
 
         // START GlassFish 1024
         if (mappingData.isDefaultContext) {
             servletPath = pathOffset;
         } else {
         // END GlassFish 1024
             int length = context.name.length();
             if (length != (pathEnd - pathOffset)) {
                 servletPath = pathOffset + length;
             } else {
                 noServletPath = true;
                 path.append('/');
                 pathOffset = path.getOffset();
                 pathEnd = path.getEnd();
                 servletPath = pathOffset+length;
             }
         // START GlassFish 1024
         }
         // END GlassFish 1024
 
         path.setOffset(servletPath);
 
         // Rule 1 -- Exact Match
         Wrapper[] exactWrappers = context.exactWrappers;
         internalMapExactWrapper(exactWrapperspathmappingData);
 
         // Rule 2 -- Prefix Match
         boolean checkJspWelcomeFiles = false;
         Wrapper[] wildcardWrappers = context.wildcardWrappers;
         if (mappingData.wrapper == null) {
             internalMapWildcardWrapper(wildcardWrapperscontext.nesting
                                        pathmappingData);
             if (mappingData.wrapper != null && mappingData.jspWildCard) {
                 char[] buf = path.getBuffer();
                 if (buf[pathEnd - 1] == '/') {
                     /*
                      * Path ending in '/' was mapped to JSP servlet based on
                      * wildcard match (e.g., as specified in url-pattern of a
                      * jsp-property-group.
                      * Force the context's welcome files, which are interpreted
                      * as JSP files (since they match the url-pattern), to be
                      * considered. See Bugzilla 27664.
                      */ 
                     mappingData.wrapper = null;
                     checkJspWelcomeFiles = true;
                 } else {
                     // See Bugzilla 27704
                     mappingData.wrapperPath.setChars(bufpath.getStart(),
                                                      path.getLength());
                     mappingData.pathInfo.recycle();
                 }
             }
         }
 
         if(mappingData.wrapper == null && noServletPath) {
             // The path is empty, redirect to "/"
             mappingData.redirectPath.setChars
                 (path.getBuffer(), pathOffsetpathEnd);
             path.setEnd(pathEnd - 1);
             return;
         }
 
         // Rule 3 -- Extension Match
         Wrapper[] extensionWrappers = context.extensionWrappers;
         if (mappingData.wrapper == null && !checkJspWelcomeFiles) {
             internalMapExtensionWrapper(extensionWrapperspathmappingData);
         }
 
         // Rule 4 -- Welcome resources processing for servlets
         if (mappingData.wrapper == null) {
             boolean checkWelcomeFiles = checkJspWelcomeFiles;
             if (!checkWelcomeFiles) {
                 char[] buf = path.getBuffer();
                 checkWelcomeFiles = (buf[pathEnd - 1] == '/');
             }
             if (checkWelcomeFiles) {
                 for (int i = 0; (i < context.welcomeResources.length)
                          && (mappingData.wrapper == null); i++) {
                     path.setOffset(pathOffset);
                     path.setEnd(pathEnd);
                     path.append(context.welcomeResources[i], 0,
                                 context.welcomeResources[i].length());
                     path.setOffset(servletPath);
 
                     // Rule 4a -- Welcome resources processing for exact macth
                     internalMapExactWrapper(exactWrapperspathmappingData);
 
                     // Rule 4b -- Welcome resources processing for prefix match
                     if (mappingData.wrapper == null) {
                         internalMapWildcardWrapper
                             (wildcardWrapperscontext.nesting
                              pathmappingData);
                     }
 
                     // Rule 4c -- Welcome resources processing
                     //            for physical folder
                     if (mappingData.wrapper == null
                             && context.resources != null) {
                         Object file = null;
                         String pathStr = path.toString();
 
                         if (context.alternateDocBases == null
                                 || context.alternateDocBases.isEmpty()) {
                             try {
                                 file = context.resources.lookup(pathStr);
                             } catch(NamingException nex) {
                                 // Swallow not found, since this is normal
                             }
                         } else {
                             AlternateDocBase match = 
                                 AlternateDocBase.findMatch(pathStr,
                                     context.alternateDocBases);
                             if (match != null) {
                                 try {
                                     file = match.getResources().lookup(pathStr);
                                 } catch(NamingException nex) {
                                     // Swallow not found, since this is normal
                                 }
                             } else {
                                 // None of the url patterns for alternate
                                 // docbases matched
                                 try {
                                     file = context.resources.lookup(pathStr);
                                 } catch(NamingException nex) {
                                     // Swallow not found, since this is normal
                                 }
                             }
                         }
 
                         if (file != null && !(file instanceof DirContext) ) {
                             internalMapExtensionWrapper(extensionWrappers,
                                                         pathmappingData);
                             if (mappingData.wrapper == null
                                 && context.defaultWrapper != null) {
                                 mappingData.wrapper =
                                     context.defaultWrapper.object;
                                 mappingData.requestPath.setChars
                                     (path.getBuffer(), path.getStart(), 
                                      path.getLength());
                                 mappingData.wrapperPath.setChars
                                     (path.getBuffer(), path.getStart(), 
                                      path.getLength());
                                 mappingData.requestPath.setString(pathStr);
                                 mappingData.wrapperPath.setString(pathStr);
                             }
                         }
                     }
                 }
 
                 path.setOffset(servletPath);
                 path.setEnd(pathEnd);
             }
                                        
        }
        // Rule 7 -- Default servlet
        if (mappingData.wrapper == null && !checkJspWelcomeFiles) {
            if (context.defaultWrapper != null) {
                mappingData.wrapper = context.defaultWrapper.object;
                mappingData.requestPath.setChars
                    (path.getBuffer(), path.getStart(), path.getLength());
                mappingData.wrapperPath.setChars
                    (path.getBuffer(), path.getStart(), path.getLength());
            }
            // Redirection to a folder
            char[] buf = path.getBuffer();
            if ( && context.resources != null
                    && buf[pathEnd -1 ] != '/') {
                Object file = null;
                String pathStr = path.toString();
                if (context.alternateDocBases == null
                        || context.alternateDocBases.isEmpty()) {
                    try {
                        file = context.resources.lookup(pathStr);
                    } catch(NamingException nex) {
                        // Swallow, since someone else handles the 404
                    }
                } else {
                    AlternateDocBase match = 
                        AlternateDocBase.findMatch(pathStr,
                            context.alternateDocBases);
                    if (match != null) {
                        try {
                            file = match.getResources().lookup(pathStr);
                        } catch(NamingException nex) {
                            // Swallow, since someone else handles the 404
                        }
                    } else {
                        // None of the url patterns for alternate
                        // docbases matched
                        try {
                            file = context.resources.lookup(pathStr);
                        } catch(NamingException nex) {
                            // Swallow, since someone else handles the 404
                        }
                    }
                }
                if (file != null && file instanceof DirContext) {
                    // Note: this mutates the path: do not do any processing 
                    // after this (since we set the redirectPath, there 
                    // shouldn't be any)
                    path.setOffset(pathOffset);
                    path.append('/');
                    mappingData.redirectPath.setChars
                        (path.getBuffer(), path.getStart(), path.getLength());
                } else {
                    mappingData.requestPath.setString(pathStr);
                    mappingData.wrapperPath.setString(pathStr);
                }
            }
        }
        path.setOffset(pathOffset);
        path.setEnd(pathEnd);
    }


    
Exact mapping.
    private final void internalMapExactWrapper
        (Wrapper[] wrappersCharChunk pathMappingData mappingData) {
        int pos = find(wrapperspath);
        if ((pos != -1) && (path.equals(wrappers[pos].))) {
            mappingData.requestPath.setString(wrappers[pos].);
            mappingData.wrapperPath.setString(wrappers[pos].);
            mappingData.wrapper = wrappers[pos].;
        }
    }


    
Wildcard mapping.
    private final void internalMapWildcardWrapper
        (Wrapper[] wrappersint nestingCharChunk path
         MappingData mappingData) {
        int pathEnd = path.getEnd();
        int pathOffset = path.getOffset();
        int lastSlash = -1;
        int length = -1;
        int pos = find(wrapperspath);
        if (pos != -1) {
            boolean found = false;
            while (pos >= 0) {
                if (path.startsWith(wrappers[pos].)) {
                    length = wrappers[pos]..length();
                    if (path.getLength() == length) {
                        found = true;
                        break;
                    } else if (path.startsWithIgnoreCase("/"length)) {
                        found = true;
                        break;
                    }
                }
                if (lastSlash == -1) {
                    lastSlash = nthSlash(pathnesting + 1);
                } else {
                    lastSlash = lastSlash(path);
                }
                path.setEnd(lastSlash);
                pos = find(wrapperspath);
            }
            path.setEnd(pathEnd);
            if (found) {
                mappingData.wrapperPath.setString(wrappers[pos].);
                if (path.getLength() > length) {
                    mappingData.pathInfo.setChars
                        (path.getBuffer(),
                         path.getOffset() + length,
                         path.getLength() - length);
                }
                mappingData.requestPath.setChars
                    (path.getBuffer(), path.getOffset(), path.getLength());
                mappingData.wrapper = wrappers[pos].;
                mappingData.jspWildCard = wrappers[pos].;
            }
        }
    }


    
Extension mappings.
    private final void internalMapExtensionWrapper
        (Wrapper[] wrappersCharChunk pathMappingData mappingData) {
        char[] buf = path.getBuffer();
        int pathEnd = path.getEnd();
        int servletPath = path.getOffset();
        int slash = -1;
        for (int i = pathEnd - 1; i >= servletPathi--) {
            if (buf[i] == '/') {
                slash = i;
                break;
            }
        }
        if (slash >= 0) {
            int period = -1;
            for (int i = pathEnd - 1; i > slashi--) {
                if (buf[i] == '.') {
                    period = i;
                    break;
                }
            }
            if (period >= 0) {
                path.setOffset(period + 1);
                path.setEnd(pathEnd);
                int pos = find(wrapperspath);
                if ((pos != -1)
                    && (path.equals(wrappers[pos].))) {
                    mappingData.wrapperPath.setChars
                        (bufservletPathpathEnd - servletPath);
                    mappingData.requestPath.setChars
                        (bufservletPathpathEnd - servletPath);
                    mappingData.wrapper = wrappers[pos].;
                }
                path.setOffset(servletPath);
                path.setEnd(pathEnd);
            }
        }
    }


    
Find a map elemnt given its name in a sorted array of map elements. This will return the index for the closest inferior or equal item in the given array.
    private static final int find(MapElement[] mapCharChunk name) {
        return find(mapnamename.getStart(), name.getEnd());
    }


    
Find a map elemnt given its name in a sorted array of map elements. This will return the index for the closest inferior or equal item in the given array.
    private static final int find(MapElement[] mapCharChunk name,
                                  int startint end) {
        int a = 0;
        int b = map.length - 1;