remm 2003/08/07 06:55:56 Modified: util/java/org/apache/tomcat/util/http/mapper Mapper.java Log: - Fix bug 22192: The context mapping algorithm actually needs to be similar to the algorithm used for widcard wrapper mapping. The idea is that problems happen rarely for context mappng, as the situation is usually much simpler. - Also use the opportunity to optimize wildcard mapping: as the amount of nesting the mapping have is known, some mapping operations can be avoided. Revision Changes Path 1.27 +103 -21 jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/mapper/Mapper.java Index: Mapper.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/mapper/Mapper.java,v retrieving revision 1.26 retrieving revision 1.27 diff -u -r1.26 -r1.27 --- Mapper.java 29 Jul 2003 12:15:47 -0000 1.26 +++ Mapper.java 7 Aug 2003 13:55:56 -0000 1.27 @@ -210,12 +210,17 @@ hosts = this.hosts; pos = find(hosts, hostName); } - if( pos <0 ) { - System.out.println("No host found " + hostName); // XXX log + if (pos < 0) { + logger.error("No host found: " + hostName); } Host host = hosts[pos]; if (host.name.equals(hostName)) { Context[] contexts = host.contextList.contexts; + // Update nesting + int slashCount = slashCount(path); + if (slashCount > host.contextList.nesting) { + host.contextList.nesting = slashCount; + } synchronized (host) { Context[] newContexts = new Context[contexts.length + 1]; Context newContext = new Context(); @@ -254,6 +259,14 @@ Context[] newContexts = new Context[contexts.length - 1]; if (removeMap(contexts, newContexts, path)) { host.contextList.contexts = newContexts; + // Recalculate nesting + host.contextList.nesting = 0; + for (int i = 0; i < newContexts.length; i++) { + int slashCount = slashCount(newContexts[i].name); + if (slashCount > host.contextList.nesting) { + host.contextList.nesting = slashCount; + } + } } } } @@ -299,7 +312,7 @@ Context[] contexts = host.contextList.contexts; int pos2 = find(contexts, contextPath); if( pos2<0 ) { - logger.error("Can't find context " + contextPath ); + logger.error("No context found: " + contextPath ); return; } Context context = contexts[pos2]; @@ -332,6 +345,10 @@ new Wrapper[oldWrappers.length + 1]; if (insertMap(oldWrappers, newWrappers, newWrapper)) { context.wildcardWrappers = newWrappers; + int slashCount = slashCount(newWrapper.name); + if (slashCount > context.nesting) { + context.nesting = slashCount; + } } } else if (path.startsWith("*.")) { // Extension wrapper @@ -407,6 +424,14 @@ Wrapper[] newWrappers = new Wrapper[oldWrappers.length - 1]; if (removeMap(oldWrappers, newWrappers, name)) { + // Recalculate nesting + context.nesting = 0; + for (int i = 0; i < newWrappers.length; i++) { + int slashCount = slashCount(newWrappers[i].name); + if (slashCount > context.nesting) { + context.nesting = slashCount; + } + } context.wildcardWrappers = newWrappers; } } else if (path.startsWith("*.")) { @@ -527,6 +552,7 @@ Context[] contexts = null; Context context = null; + int nesting = 0; // Virtual host mapping if (mappingData.host == null) { @@ -535,6 +561,7 @@ if ((pos != -1) && (host.equals(hosts[pos].name))) { mappingData.host = hosts[pos].object; contexts = hosts[pos].contextList.contexts; + nesting = hosts[pos].contextList.nesting; } else { if (defaultHostName == null) { return; @@ -543,6 +570,7 @@ if ((pos != -1) && (defaultHostName.equals(hosts[pos].name))) { mappingData.host = hosts[pos].object; contexts = hosts[pos].contextList.contexts; + nesting = hosts[pos].contextList.nesting; } else { return; } @@ -555,21 +583,32 @@ if (pos == -1) { return; } + + int lastSlash = -1; + int uriEnd = uri.getEnd(); + int length = -1; boolean found = false; - while (uri.startsWith(contexts[pos].name)) { - int length = contexts[pos].name.length(); - if (uri.getLength() == length) { - found = true; - break; - } else if (uri.startsWithIgnoreCase("/", length)) { - found = true; - break; + while (pos >= 0) { + if (uri.startsWith(contexts[pos].name)) { + length = contexts[pos].name.length(); + if (uri.getLength() == length) { + found = true; + break; + } else if (uri.startsWithIgnoreCase("/", length)) { + found = true; + break; + } } - pos--; - if (pos < 0) { - break; + if (lastSlash == -1) { + lastSlash = nthSlash(uri, nesting + 1); + } else { + lastSlash = lastSlash(uri); } + uri.setEnd(lastSlash); + pos = find(contexts, uri); } + uri.setEnd(uriEnd); + if (!found) { if (contexts[0].name.equals("")) { context = contexts[0]; @@ -623,7 +662,8 @@ // Rule 2 -- Prefix Match Wrapper[] wildcardWrappers = context.wildcardWrappers; if (mappingData.wrapper == null) { - internalMapWildcardWrapper(wildcardWrappers, path, mappingData); + internalMapWildcardWrapper(wildcardWrappers, context.nesting, + path, mappingData); } // Rule 3 -- Extension Match @@ -650,7 +690,8 @@ // Rule 4b -- Welcome resources processing for prefix match if (mappingData.wrapper == null) { internalMapWildcardWrapper - (wildcardWrappers, path, mappingData); + (wildcardWrappers, context.nesting, + path, mappingData); } // Rule 4c -- Welcome resources processing @@ -664,8 +705,6 @@ // Swallow not found, since this is normal } if (file != null && !(file instanceof DirContext) ) { - if(logger.isTraceEnabled()) - logger.trace("Found welcome-file: " + path); internalMapExtensionWrapper(extensionWrappers, path, mappingData); if(mappingData.wrapper == null) { @@ -738,15 +777,16 @@ * Wildcard mapping. */ private final void internalMapWildcardWrapper - (Wrapper[] wrappers, CharChunk path, MappingData mappingData) { + (Wrapper[] wrappers, int nesting, CharChunk path, + MappingData mappingData) { int pathEnd = path.getEnd(); int pathOffset = path.getOffset(); + int lastSlash = -1; int length = -1; int pos = find(wrappers, path); if (pos != -1) { - int lastSlash = pathEnd; boolean found = false; while (pos >= 0) { if (path.startsWith(wrappers[pos].name)) { @@ -759,7 +799,11 @@ break; } } - lastSlash = lastSlash(path); + if (lastSlash == -1) { + lastSlash = nthSlash(path, nesting + 1); + } else { + lastSlash = lastSlash(path); + } path.setEnd(lastSlash); pos = find(wrappers, path); } @@ -975,6 +1019,42 @@ /** + * Find the position of the nth slash, in the given char chunk. + */ + private static final int nthSlash(CharChunk name, int n) { + + char[] c = name.getBuffer(); + int end = name.getEnd(); + int start = name.getStart(); + int pos = start; + int count = 0; + + while (pos < end) { + if ((c[pos++] == '/') && ((++count) == n)) { + pos--; + break; + } + } + + return (pos); + + } + + + /** + * Return the slash count in a given string. + */ + private static final int slashCount(String name) { + int pos = -1; + int count = 0; + while ((pos = name.indexOf('/', pos + 1)) != -1) { + count++; + } + return count; + } + + + /** * Insert into the right place in a sorted MapElement array, and prevent * duplicates. */ @@ -1036,6 +1116,7 @@ protected final class ContextList { public Context[] contexts = new Context[0]; + public int nesting = 0; } @@ -1053,6 +1134,7 @@ public Wrapper[] exactWrappers = new Wrapper[0]; public Wrapper[] wildcardWrappers = new Wrapper[0]; public Wrapper[] extensionWrappers = new Wrapper[0]; + public int nesting = 0; }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]