Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    *  Licensed to the Apache Software Foundation (ASF) under one or more
    *  contributor license agreements.  See the NOTICE file distributed with
    *  this work for additional information regarding copyright ownership.
    *  The ASF licenses this file to You 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 static org.jboss.web.CoyoteMessages.MESSAGES;
  
  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 {
  
  
      // ----------------------------------------------------- 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();


    
Listeners for lazy loading of web applications.
  
      protected final List<OnDemandContextMappingListenerlazyLoadListeners = 
          new ArrayList<OnDemandContextMappingListener>();
      
      
      // --------------------------------------------------------- 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;
      }

    
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();
         newHost.name = name;
         newHost.contextList = contextList;
         newHost.object = host;
         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;
             newHost.object = host;
             if (insertMap(newHostsnewHost)) {
                  = newHosts;
             }
         }
     }


    
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;
                 }
             }
         }
     }
 
     public String[] getHosts() {
         String hostN[] = new String[.];
         forint i = 0; i < .i++ ) {
             hostN[i] = [i].;
         }
         return hostN;
     }


    
Add an alias to an existing host.

Parameters:
name The name of the host
alias The alias to add
 
     public synchronized void addHostAlias(String nameString alias) {
         int pos = find(name);
         if (pos < 0) {
             // Should not be adding an alias for a host that doesn't exist but
             // just in case...
             return;
         }
         Host realHost = [pos];
         
         Host[] newHosts = new Host[. + 1];
         Host newHost = new Host();
         newHost.name = alias;
         newHost.contextList = realHost.contextList;
         newHost.object = realHost;
         if (insertMap(newHostsnewHost)) {
              = newHosts;
         }
     }

    
Remove a host alias

Parameters:
alias The alias to remove
 
     public synchronized void removeHostAlias(String alias) {
         // Find and remove the alias
         int pos = find(alias);
         if (pos < 0) {
             return;
         }
         Host[] newHosts = new Host[. - 1];
         if (removeMap(newHostsalias)) {
              = newHosts;
         }
 
     }

    
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 undeployed Context to an existing Host.

Parameters:
hostName Virtual host name this context belongs to
path Context path
 
     public void addOnDemandContext(String hostNameString path) {
 
         Host[] hosts = this.;
         int pos = find(hostshostName);
         ifpos <0 ) {
             addHost(hostNamenew String[0], "");
             hosts = this.;
             pos = find(hostshostName);
         }
         if (pos < 0) {
             throw .mapperHostNotFound(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;
                 if (insertMap(contextsnewContextsnewContext)) {
                     host.contextList.contexts = newContexts;
                 }
             }
         }
 
     }


    
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) {
 
         Host[] hosts = this.;
         int pos = find(hostshostName);
         ifpos <0 ) {
             addHost(hostNamenew String[0], "");
             hosts = this.;
             pos = find(hostshostName);
         }
         if (pos < 0) {
             throw .mapperHostNotFound(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;
                 if (insertMap(contextsnewContextsnewContext)) {
                     host.contextList.contexts = newContexts;
                 } else {
                     newContexts = new Context[contexts.length];
                     if (insertLazyLoadedContext(contextsnewContextsnewContext)) {
                         host.contextList.contexts = newContexts;
                     }
                 }
             }
         }
 
     }


    
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<Stringlist = new ArrayList<String>();
         for (int i = 0; i < .i++) {
             for (int j = 0; j < [i]...lengthj++) {
                 String cname = [i]..[j].;
                 list.add("//" + [i].
                         + (cname.startsWith("/") ? cname : "/"));
             }
         }
         return list.toArray(new String[list.size()]);
     }

    
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 ) {
                 throw .mapperContextNotFound(contextPath);
             }
             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 if (path.equals("")) {
                 // Root wrapper
                 newWrapper.name = "";
                 context.rootWrapper = 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 if (path.equals("")) {
                 // Root wrapper
                 context.rootWrapper = 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);
         StringBuilder sb=new StringBuilder();
         forint i=0; i<names.lengthi++ ) {
             sb.append(names[i]).append(":");
         }
         return sb.toString();
     }
 
     public String[] getWrapperNames(String hostString context) {
         List<Stringlist = new ArrayList<String>();
         if (host == null)
             host = "";
         if (context == null)
             context = "";
         for (int i = 0; i < .i++) {
             if (!host.equals([i].))
                 continue;
             for (int j = 0; j < [i]...lengthj++) {
                 if (!context.equals([i]..[j].))
                     continue;
                 // found the context
                 Context ctx = [i]..[j];
                 list.add(ctx.defaultWrapper.name);
                 for (int k = 0; k < ctx.exactWrappers.lengthk++) {
                     list.add(ctx.exactWrappers[k].);
                 }
                 for (int k = 0; k < ctx.wildcardWrappers.lengthk++) {
                     list.add(ctx.wildcardWrappers[k]. + "*");
                 }
                 for (int k = 0; k < ctx.extensionWrappers.lengthk++) {
                     list.add("*." + ctx.extensionWrappers[k].);
                 }
             }
         }
         return list.toArray(new String[list.size()]);
     }


    
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);
 
     }
 
 
         if (listener != null) {
             synchronized () {
                 .add(listener);
             }
         }
     }
 
         if (listener != null) {
             synchronized () {
                 .remove(listener);
             }
         }
     }
 
 
     // -------------------------------------------------------- Private Methods
 

    
Map the specified URI.
 
     private final void internalMap(CharChunk hostCharChunk uri,
                                    MappingData mappingData)
         throws Exception {
 
         uri.setLimit(-1);
 
         Context[] contexts = null;
         Host mappedHost = null;
         Context context = null;
         int nesting = 0;
 
         // Virtual host mapping
         if (mappingData.host == null) {
             Host[] hosts = this.;
             int pos = findIgnoreCase(hostshost);
             if ((pos != -1) && (host.equalsIgnoreCase(hosts[pos].))) {
                 mappedHost = hosts[pos];
                 mappingData.host = mappedHost.object;
                 contexts = mappedHost.contextList.contexts;
                 nesting = mappedHost.contextList.nesting;
             } else {
                 if ( == null) {
                     return;
                 }
                 pos = find(hosts);
                 if ((pos != -1) && (.equals(hosts[pos].))) {
                     mappedHost = hosts[pos];
                     mappingData.host = mappedHost.object;
                     contexts = mappedHost.contextList.contexts;
                     nesting = mappedHost.contextList.nesting;
                 } else {
                     return;
                 }
             }
         }
 
         // Context mapping
         if (mappingData.context == null) {
             context = findContext(uricontextsnesting);
             if (context != null) {
                 if (context.object == null) {
                     notifyLazyLoadContextMappingListeners(mappedHostcontext);
                     // See if the notification resulted in deploying the context
                     // First reestablish refs to the host fields as adding
                     // the real context will have changed them
                     contexts = mappedHost.contextList.contexts;
                     nesting = mappedHost.contextList.nesting;
                     context = findContext(uricontextsnesting);
                     if (context != null && context.object == null) {
                         // notification did not result in deployment 
                         // don't map to the unloaded context
                         context = null;
                     }
                 }
                 if (context != null) {
                     mappingData.context = context.object;
                     mappingData.contextPath.setString(context.name);
                 }
             }
         }
 
         // Wrapper mapping
         if ((context != null) && (mappingData.wrapper == null)) {
             internalMapWrapper(contexturimappingData);
         }
 
     }
 
 
     private void notifyLazyLoadContextMappingListeners(Host mappedHostContext context) {
         synchronized (context) {
             if (context.replaced)
                 return;
             synchronized () {
                 for (OnDemandContextMappingListener listener : )
                     listener.onDemandContextMapped(mappedHost.namecontext.name);
             }
         }
 
     }
 
 
     private Context findContext(CharChunk uriContext[] contextsint nesting) {
         int pos = find(contextsuri);
         if (pos == -1) {
             return null;
         }
 
         Context foundContext = null;
 
         int lastSlash = -1;
         int uriEnd = uri.getEnd();
         int length = -1;
         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("")) {
                 foundContext = contexts[0];
             }
         } else {
             foundContext = contexts[pos];
         }
         return foundContext;
     }


    
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;
 
         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;
         }
 
         path.setOffset(servletPath);
 
         // Rule 1 -- Exact Match
         Wrapper[] exactWrappers = context.exactWrappers;
         if (!noServletPath && (pathEnd - servletPath) == 1 && context.rootWrapper != null) {
             mappingData.requestPath.setString("/");
             mappingData.wrapperPath.setString("");
             mappingData.pathInfo.setString("/");
             mappingData.wrapper = context.rootWrapper.object;
         } else {
             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 - pathOffset);
             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();
                         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();
                 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 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 element 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;
        // Special cases: -1 and 0
        if (b == -1) {
            return -1;
        }
        
        if (compare(namestartendmap[0].) < 0 ) {
            return -1;
        }         
        if (b == 0) {
            return 0;
        }
        int i = 0;
        while (true) {
            i = (b + a) / 2;
            int result = compare(namestartendmap[i].);
            if (result == 1) {
                a = i;
            } else if (result == 0) {
                return i;
            } else {
                b = i;
            }
            if ((b - a) == 1) {
                int result2 = compare(namestartendmap[b].);
                if (result2 < 0) {
                    return a;
                } else {
                    return b;
                }
            }
        }
    }

    
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 findIgnoreCase(MapElement[] mapCharChunk name) {
        return findIgnoreCase(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 findIgnoreCase(MapElement[] mapCharChunk name,
                                  int startint end) {
        int a = 0;
        int b = map.length - 1;
        // Special cases: -1 and 0
        if (b == -1) {
            return -1;
        }
        if (compareIgnoreCase(namestartendmap[0].) < 0 ) {
            return -1;
        }         
        if (b == 0) {
            return 0;
        }
        int i = 0;
        while (true) {