Added: tomcat/sandbox/java/org/apache/coyote/servlet/WebappServletMapper.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/coyote/servlet/WebappServletMapper.java?rev=415818&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/coyote/servlet/WebappServletMapper.java (added) +++ tomcat/sandbox/java/org/apache/coyote/servlet/WebappServletMapper.java Tue Jun 20 14:45:26 2006 @@ -0,0 +1,855 @@ +/* + * Copyright 1999-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.coyote.servlet; + +import java.io.File; + +import org.apache.coyote.servlet.util.MappingData; +import org.apache.tomcat.util.buf.Ascii; +import org.apache.tomcat.util.buf.CharChunk; +import org.apache.tomcat.util.buf.MessageBytes; + +/** + * Mapper, which implements the servlet API mapping rules (which are derived + * from the HTTP rules). + * + * Based on catalina mapper - but simplified. All host and context mappings + * is done in HostMapper - this is just dealing with web.xml. + * + * For corner cases ( very large number of rules, dynamic rules, etc ) you + * can override the mapper for a context with a class extending this. + */ +public class WebappServletMapper { + + + private static org.apache.commons.logging.Log logger = + org.apache.commons.logging.LogFactory.getLog(WebappServletMapper.class); + // ----------------------------------------------------- Instance Variables + + /** + * Context associated with this wrapper, used for wrapper mapping. + */ + public ContextMapElement contextMapElement = new ContextMapElement(); + + + // --------------------------------------------------------- Public Methods + + public WebappServletMapper(ServletContextImpl impl) { + contextMapElement.object = impl; + contextMapElement.name = impl.getContextPath(); + } + + + /** Set context, used for wrapper mapping (request dispatcher). + * + * @param welcomeResources Welcome files defined for this context + * @param resources Static resources of the context + */ + public void setContext(String path, String[] welcomeResources, + File resources) { + contextMapElement.name = path; + contextMapElement.welcomeResources = welcomeResources; + contextMapElement.resources = resources; + } + + + /** + * Add a wrapper to the context associated with this wrapper. + * + * @param path Wrapper mapping + * @param wrapper The Wrapper object + */ + public void addWrapper(String path, Object wrapper) { + addWrapper(contextMapElement, path, wrapper); + } + + + public void addWrapper(String path, Object wrapper, boolean jspWildCard) { + addWrapper(contextMapElement, path, wrapper, jspWildCard); + } + + + public void addWrapper(ContextMapElement context, String path, Object wrapper) { + addWrapper(context, path, wrapper, false); + } + + + /** + * Adds a wrapper to the given context. + * + * @param context The context to which to add the wrapper + * @param path Wrapper mapping + * @param wrapper The Wrapper object + * @param jspWildCard true if the wrapper corresponds to the JspServlet + * and the mapping path contains a wildcard; false otherwise + */ + protected void addWrapper(ContextMapElement context, String path, Object wrapper, + boolean jspWildCard) { + + synchronized (context) { + WrapperMapElement newWrapper = new WrapperMapElement(); + newWrapper.object = wrapper; + newWrapper.jspWildCard = jspWildCard; + if (path.endsWith("/*")) { + // Wildcard wrapper + newWrapper.name = path.substring(0, path.length() - 2); + WrapperMapElement[] oldWrappers = context.wildcardWrappers; + WrapperMapElement[] newWrappers = + new WrapperMapElement[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 + newWrapper.name = path.substring(2); + WrapperMapElement[] oldWrappers = context.extensionWrappers; + WrapperMapElement[] newWrappers = + new WrapperMapElement[oldWrappers.length + 1]; + if (insertMap(oldWrappers, newWrappers, newWrapper)) { + context.extensionWrappers = newWrappers; + } + } else if (path.equals("/")) { + // Default wrapper + newWrapper.name = ""; + context.defaultWrapper = newWrapper; + } else { + // Exact wrapper + newWrapper.name = path; + WrapperMapElement[] oldWrappers = context.exactWrappers; + WrapperMapElement[] newWrappers = + new WrapperMapElement[oldWrappers.length + 1]; + if (insertMap(oldWrappers, newWrappers, newWrapper)) { + context.exactWrappers = newWrappers; + } + } + } + } + + + /** + * Remove a wrapper from the context associated with this wrapper. + * + * @param path Wrapper mapping + */ + public void removeWrapper(String path) { + removeWrapper(contextMapElement, path); + } + + + protected void removeWrapper(ContextMapElement context, String path) { + synchronized (context) { + if (path.endsWith("/*")) { + // Wildcard wrapper + String name = path.substring(0, path.length() - 2); + WrapperMapElement[] oldWrappers = context.wildcardWrappers; + WrapperMapElement[] newWrappers = + new WrapperMapElement[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("*.")) { + // Extension wrapper + String name = path.substring(2); + WrapperMapElement[] oldWrappers = context.extensionWrappers; + WrapperMapElement[] newWrappers = + new WrapperMapElement[oldWrappers.length - 1]; + if (removeMap(oldWrappers, newWrappers, name)) { + context.extensionWrappers = newWrappers; + } + } else if (path.equals("/")) { + // Default wrapper + context.defaultWrapper = null; + } else { + // Exact wrapper + String name = path; + WrapperMapElement[] oldWrappers = context.exactWrappers; + WrapperMapElement[] newWrappers = + new WrapperMapElement[oldWrappers.length - 1]; + if (removeMap(oldWrappers, newWrappers, name)) { + context.exactWrappers = newWrappers; + } + } + } + } + + /** + * Map the specified URI relative to the context, + * mutating the given mapping data. + * + * @param uri URI + * @param mappingData This structure will contain the result of the mapping + * operation + */ + public void map(MessageBytes uri, MappingData mappingData) + throws Exception { + + uri.toChars(); + CharChunk uricc = uri.getCharChunk(); + uricc.setLimit(-1); + internalMapWrapper(contextMapElement, uricc, mappingData); + + } + + + // -------------------------------------------------------- Private Methods + + + /** + * Wrapper mapping. + */ + private final void internalMapWrapper(ContextMapElement context, CharChunk 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 + WrapperMapElement[] exactWrappers = context.exactWrappers; + internalMapExactWrapper(exactWrappers, path, mappingData); + + // Rule 2 -- Prefix Match + boolean checkJspWelcomeFiles = false; + WrapperMapElement[] wildcardWrappers = context.wildcardWrappers; + if (mappingData.wrapper == null) { + internalMapWildcardWrapper(wildcardWrappers, context.nesting, + path, mappingData); + 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(buf, path.getStart(), + path.getLength()); + mappingData.pathInfo.recycle(); + } + } + } + + if(mappingData.wrapper == null && noServletPath) { + // The path is empty, redirect to "/" + mappingData.redirectPath.setChars + (path.getBuffer(), pathOffset, pathEnd); + path.setEnd(pathEnd - 1); + return; + } + + // Rule 3 -- Extension Match + WrapperMapElement[] extensionWrappers = context.extensionWrappers; + if (mappingData.wrapper == null && !checkJspWelcomeFiles) { + internalMapExtensionWrapper(extensionWrappers, path, mappingData); + } + + File file = null; + // 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(exactWrappers, path, mappingData); + + // Rule 4b -- Welcome resources processing for prefix match + if (mappingData.wrapper == null) { + internalMapWildcardWrapper + (wildcardWrappers, context.nesting, + path, mappingData); + } + + // Rule 4c -- Welcome resources processing + // for physical folder + if (mappingData.wrapper == null + && context.resources != null) { + // Default servlet: check if it's file or dir to apply + // welcome files rules. + // TODO: Save the File in attributes, + // to avoid duplication in DefaultServlet. + + String pathStr = path.toString(); + file = new File(context.resources, pathStr); + if (file.exists() && !(file.isDirectory()) ) { + + internalMapExtensionWrapper(extensionWrappers, + path, mappingData); + 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 ] != '/') { + String pathStr = path.toString(); + file = new File( context.resources, pathStr); + if (file.exists() && file.isDirectory()) { + // 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 + (WrapperMapElement[] wrappers, CharChunk path, MappingData mappingData) { + int pos = find(wrappers, path); + if ((pos != -1) && (path.equals(wrappers[pos].name))) { + mappingData.requestPath.setString(wrappers[pos].name); + mappingData.wrapperPath.setString(wrappers[pos].name); + mappingData.wrapper = wrappers[pos].object; + } + } + + + /** + * Wildcard mapping. + */ + private final void internalMapWildcardWrapper + (WrapperMapElement[] 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) { + boolean found = false; + while (pos >= 0) { + if (path.startsWith(wrappers[pos].name)) { + length = wrappers[pos].name.length(); + if (path.getLength() == length) { + found = true; + break; + } else if (path.startsWithIgnoreCase("/", length)) { + found = true; + break; + } + } + if (lastSlash == -1) { + lastSlash = nthSlash(path, nesting + 1); + } else { + lastSlash = lastSlash(path); + } + path.setEnd(lastSlash); + pos = find(wrappers, path); + } + path.setEnd(pathEnd); + if (found) { + mappingData.wrapperPath.setString(wrappers[pos].name); + 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].object; + mappingData.jspWildCard = wrappers[pos].jspWildCard; + } + } + } + + + /** + * Extension mappings. + */ + private final void internalMapExtensionWrapper + (WrapperMapElement[] wrappers, CharChunk path, MappingData mappingData) { + char[] buf = path.getBuffer(); + int pathEnd = path.getEnd(); + int servletPath = path.getOffset(); + int slash = -1; + for (int i = pathEnd - 1; i >= servletPath; i--) { + if (buf[i] == '/') { + slash = i; + break; + } + } + if (slash >= 0) { + int period = -1; + for (int i = pathEnd - 1; i > slash; i--) { + if (buf[i] == '.') { + period = i; + break; + } + } + if (period >= 0) { + path.setOffset(period + 1); + path.setEnd(pathEnd); + int pos = find(wrappers, path); + if ((pos != -1) + && (path.equals(wrappers[pos].name))) { + mappingData.wrapperPath.setChars + (buf, servletPath, pathEnd - servletPath); + mappingData.requestPath.setChars + (buf, servletPath, pathEnd - servletPath); + mappingData.wrapper = wrappers[pos].object; + } + 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. + */ + public static final int find(MapElement[] map, CharChunk name) { + return find(map, name, name.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[] map, CharChunk name, + int start, int end) { + + int a = 0; + int b = map.length - 1; + + // Special cases: -1 and 0 + if (b == -1) { + return -1; + } + + if (compare(name, start, end, map[0].name) < 0 ) { + return -1; + } + if (b == 0) { + return 0; + } + + int i = 0; + while (true) { + i = (b + a) / 2; + int result = compare(name, start, end, map[i].name); + if (result == 1) { + a = i; + } else if (result == 0) { + return i; + } else { + b = i; + } + if ((b - a) == 1) { + int result2 = compare(name, start, end, map[b].name); + 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[] map, CharChunk name) { + return findIgnoreCase(map, name, name.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[] map, CharChunk name, + int start, int end) { + + int a = 0; + int b = map.length - 1; + + // Special cases: -1 and 0 + if (b == -1) { + return -1; + } + if (compareIgnoreCase(name, start, end, map[0].name) < 0 ) { + return -1; + } + if (b == 0) { + return 0; + } + + int i = 0; + while (true) { + i = (b + a) / 2; + int result = compareIgnoreCase(name, start, end, map[i].name); + if (result == 1) { + a = i; + } else if (result == 0) { + return i; + } else { + b = i; + } + if ((b - a) == 1) { + int result2 = compareIgnoreCase(name, start, end, map[b].name); + 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. + */ + public static final int find(MapElement[] map, String name) { + + int a = 0; + int b = map.length - 1; + + // Special cases: -1 and 0 + if (b == -1) { + return -1; + } + + if (name.compareTo(map[0].name) < 0) { + return -1; + } + if (b == 0) { + return 0; + } + + int i = 0; + while (true) { + i = (b + a) / 2; + int result = name.compareTo(map[i].name); + if (result > 0) { + a = i; + } else if (result == 0) { + return i; + } else { + b = i; + } + if ((b - a) == 1) { + int result2 = name.compareTo(map[b].name); + if (result2 < 0) { + return a; + } else { + return b; + } + } + } + + } + + + /** + * Compare given char chunk with String. + * Return -1, 0 or +1 if inferior, equal, or superior to the String. + */ + private static final int compare(CharChunk name, int start, int end, + String compareTo) { + int result = 0; + char[] c = name.getBuffer(); + int len = compareTo.length(); + if ((end - start) < len) { + len = end - start; + } + for (int i = 0; (i < len) && (result == 0); i++) { + if (c[i + start] > compareTo.charAt(i)) { + result = 1; + } else if (c[i + start] < compareTo.charAt(i)) { + result = -1; + } + } + if (result == 0) { + if (compareTo.length() > (end - start)) { + result = -1; + } else if (compareTo.length() < (end - start)) { + result = 1; + } + } + return result; + } + + + /** + * Compare given char chunk with String ignoring case. + * Return -1, 0 or +1 if inferior, equal, or superior to the String. + */ + private static final int compareIgnoreCase(CharChunk name, int start, int end, + String compareTo) { + int result = 0; + char[] c = name.getBuffer(); + int len = compareTo.length(); + if ((end - start) < len) { + len = end - start; + } + for (int i = 0; (i < len) && (result == 0); i++) { + if (Ascii.toLower(c[i + start]) > Ascii.toLower(compareTo.charAt(i))) { + result = 1; + } else if (Ascii.toLower(c[i + start]) < Ascii.toLower(compareTo.charAt(i))) { + result = -1; + } + } + if (result == 0) { + if (compareTo.length() > (end - start)) { + result = -1; + } else if (compareTo.length() < (end - start)) { + result = 1; + } + } + return result; + } + + + /** + * Find the position of the last slash in the given char chunk. + */ + public static final int lastSlash(CharChunk name) { + + char[] c = name.getBuffer(); + int end = name.getEnd(); + int start = name.getStart(); + int pos = end; + + while (pos > start) { + if (c[--pos] == '/') { + break; + } + } + + return (pos); + + } + + + /** + * Find the position of the nth slash, in the given char chunk. + */ + public 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. + */ + public 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. + */ + public static final boolean insertMap + (MapElement[] oldMap, MapElement[] newMap, MapElement newElement) { + int pos = find(oldMap, newElement.name); + if ((pos != -1) && (newElement.name.equals(oldMap[pos].name))) { + return false; + } + System.arraycopy(oldMap, 0, newMap, 0, pos + 1); + newMap[pos + 1] = newElement; + System.arraycopy + (oldMap, pos + 1, newMap, pos + 2, oldMap.length - pos - 1); + return true; + } + + + /** + * Insert into the right place in a sorted MapElement array. + */ + public static final boolean removeMap + (MapElement[] oldMap, MapElement[] newMap, String name) { + int pos = find(oldMap, name); + if ((pos != -1) && (name.equals(oldMap[pos].name))) { + System.arraycopy(oldMap, 0, newMap, 0, pos); + System.arraycopy(oldMap, pos + 1, newMap, pos, + oldMap.length - pos - 1); + return true; + } + return false; + } + + + // ------------------------------------------------- MapElement Inner Class + + + protected static abstract class MapElement { + /** hostname or path + */ + public String name = null; + public Object object = null; + + } + + + // ---------------------------------------------------- Context Inner Class + + + public static final class ContextMapElement + extends MapElement { + + public ContextMapElement() { + System.err.println("XXX"); + } + public String path = null; + public String[] welcomeResources = new String[0]; + public File resources = null; + public WrapperMapElement defaultWrapper = null; + public WrapperMapElement[] exactWrappers = new WrapperMapElement[0]; + public WrapperMapElement[] wildcardWrappers = new WrapperMapElement[0]; + public WrapperMapElement[] extensionWrappers = new WrapperMapElement[0]; + public int nesting = 0; + + } + + + // ---------------------------------------------------- Wrapper Inner Class + + + public static class WrapperMapElement + extends MapElement { + + public String path = null; + public boolean jspWildCard = false; + } + +}
Copied: tomcat/sandbox/java/org/apache/coyote/servlet/WebappSessionManager.java (from r410655, tomcat/sandbox/java/org/apache/coyote/servlet/SessionManager.java) URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/coyote/servlet/WebappSessionManager.java?p2=tomcat/sandbox/java/org/apache/coyote/servlet/WebappSessionManager.java&p1=tomcat/sandbox/java/org/apache/coyote/servlet/SessionManager.java&r1=410655&r2=415818&rev=415818&view=diff ============================================================================== --- tomcat/sandbox/java/org/apache/coyote/servlet/SessionManager.java (original) +++ tomcat/sandbox/java/org/apache/coyote/servlet/WebappSessionManager.java Tue Jun 20 14:45:26 2006 @@ -54,8 +54,8 @@ * @version $Revision: 303871 $ $Date: 2005-04-19 05:15:51 -0700 (Tue, 19 Apr 2005) $ */ -public class SessionManager { - protected Log log = LogFactory.getLog(SessionManager.class); +public class WebappSessionManager { + protected Log log = LogFactory.getLog(WebappSessionManager.class); // ----------------------------------------------------- Instance Variables Added: tomcat/sandbox/java/org/apache/coyote/servlet/servlets/ReloadServlet.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/coyote/servlet/servlets/ReloadServlet.java?rev=415818&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/coyote/servlet/servlets/ReloadServlet.java (added) +++ tomcat/sandbox/java/org/apache/coyote/servlet/servlets/ReloadServlet.java Tue Jun 20 14:45:26 2006 @@ -0,0 +1,23 @@ +package org.apache.coyote.servlet.servlets; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.coyote.servlet.CoyoteServletFacade; + +public class ReloadServlet extends HttpServlet { + + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + + CoyoteServletFacade servletImpl = CoyoteServletFacade.getServletImpl(); + servletImpl.reloadServletContext(getServletContext()); + + } + + +} Added: tomcat/sandbox/java/org/apache/coyote/servlet/util/MappingData.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/coyote/servlet/util/MappingData.java?rev=415818&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/coyote/servlet/util/MappingData.java (added) +++ tomcat/sandbox/java/org/apache/coyote/servlet/util/MappingData.java Tue Jun 20 14:45:26 2006 @@ -0,0 +1,52 @@ +/* + * Copyright 1999-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.coyote.servlet.util; + +import org.apache.tomcat.util.buf.MessageBytes; + +/** + * Mapping data. + * + * @author Remy Maucherat + */ +public class MappingData { + + public Object host = null; + public Object context = null; + public Object wrapper = null; + public boolean jspWildCard = false; + + public MessageBytes contextPath = MessageBytes.newInstance(); + public MessageBytes requestPath = MessageBytes.newInstance(); + public MessageBytes wrapperPath = MessageBytes.newInstance(); + public MessageBytes pathInfo = MessageBytes.newInstance(); + + public MessageBytes redirectPath = MessageBytes.newInstance(); + + public void recycle() { + host = null; + context = null; + wrapper = null; + pathInfo.recycle(); + requestPath.recycle(); + wrapperPath.recycle(); + contextPath.recycle(); + redirectPath.recycle(); + jspWildCard = false; + } + +} Modified: tomcat/sandbox/java/org/apache/coyote/servlet/util/MessageWriter.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/coyote/servlet/util/MessageWriter.java?rev=415818&r1=415817&r2=415818&view=diff ============================================================================== --- tomcat/sandbox/java/org/apache/coyote/servlet/util/MessageWriter.java (original) +++ tomcat/sandbox/java/org/apache/coyote/servlet/util/MessageWriter.java Tue Jun 20 14:45:26 2006 @@ -52,7 +52,7 @@ implements ByteChunk.ByteOutputChannel, CharChunk.CharOutputChannel { // used in getWriter, until a method is added to res. - private static final int WRITER_NOTE = 3; + private static final int WRITER_NOTE = 9; // -------------------------------------------------------------- Constants Added: tomcat/sandbox/java/org/apache/coyote/servlet/webxml/WebXml.java URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/coyote/servlet/webxml/WebXml.java?rev=415818&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/coyote/servlet/webxml/WebXml.java (added) +++ tomcat/sandbox/java/org/apache/coyote/servlet/webxml/WebXml.java Tue Jun 20 14:45:26 2006 @@ -0,0 +1,237 @@ +/* + */ +package org.apache.coyote.servlet.webxml; + +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.HashMap; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.apache.coyote.servlet.CoyoteServletFacade; +import org.apache.coyote.servlet.ServletConfigImpl; +import org.apache.coyote.servlet.ServletContextImpl; +import org.apache.tomcat.util.DomUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +public class WebXml { + ServletContextImpl ctx; + CoyoteServletFacade facade = CoyoteServletFacade.getServletImpl(); + + public WebXml(ServletContext sctx) { + ctx = (ServletContextImpl) sctx; + } + + public void readWebXml(String baseDir) throws ServletException { + try { + File webXmlFile = new File( baseDir + "/WEB-INF/web.xml"); + if (!webXmlFile.exists()) { + return; + } + FileInputStream fileInputStream = new FileInputStream(webXmlFile); + Document document = + DomUtil.readXml(fileInputStream); + + Node webappNode = DomUtil.getChild(document, "web-app"); + + Node confNode = DomUtil.getChild(webappNode, "filter"); + while (confNode != null ) { + processFilter(confNode); + confNode = DomUtil.getNext(confNode); + } + + confNode = DomUtil.getChild(webappNode, "filter-mapping"); + while (confNode != null ) { + processFilterMapping(confNode); + confNode = DomUtil.getNext(confNode); + } + + confNode = DomUtil.getChild(webappNode, "context-param"); + while (confNode != null ) { + processContextParam(confNode); + confNode = DomUtil.getNext(confNode); + } + + confNode = DomUtil.getChild(webappNode, "mime-mapping"); + while (confNode != null ) { + processFilterMapping(confNode); + confNode = DomUtil.getNext(confNode); + } + + confNode = DomUtil.getChild(webappNode, "error-page"); + while (confNode != null ) { + processFilterMapping(confNode); + confNode = DomUtil.getNext(confNode); + } + + confNode = DomUtil.getChild(webappNode, "jsp-config"); + while (confNode != null ) { + processFilterMapping(confNode); + confNode = DomUtil.getNext(confNode); + } + + confNode = DomUtil.getChild(webappNode, "servlet"); + while (confNode != null ) { + processServlet(confNode); + confNode = DomUtil.getNext(confNode); + } + + confNode = DomUtil.getChild(webappNode, "servlet-mapping"); + while (confNode != null ) { + processServletMapping(confNode); + confNode = DomUtil.getNext(confNode); + } + + confNode = DomUtil.getChild(webappNode, "listener"); + while (confNode != null ) { + processListener(confNode); + confNode = DomUtil.getNext(confNode); + } + + confNode = DomUtil.getChild(webappNode, "security-constraint"); + while (confNode != null ) { + processListener(confNode); + confNode = DomUtil.getNext(confNode); + } + + confNode = DomUtil.getChild(webappNode, "login-config"); + while (confNode != null ) { + processListener(confNode); + confNode = DomUtil.getNext(confNode); + if (confNode != null) + throw new ServletException("Multiple login-config"); + } + + confNode = DomUtil.getChild(webappNode, "session-config"); + while (confNode != null ) { + processListener(confNode); + confNode = DomUtil.getNext(confNode); + if (confNode != null) + throw new ServletException("Multiple session-config"); + } + + confNode = DomUtil.getChild(webappNode, "security-role"); + while (confNode != null ) { + processListener(confNode); + confNode = DomUtil.getNext(confNode); + } + + + confNode = DomUtil.getChild(webappNode, "env-entry"); + while (confNode != null ) { + processListener(confNode); + confNode = DomUtil.getNext(confNode); + } + + // concatenate + confNode = DomUtil.getChild(webappNode, "welcome-file-list"); + while (confNode != null ) { + processListener(confNode); + confNode = DomUtil.getNext(confNode); + } + + // concatenate + confNode = DomUtil.getChild(webappNode, "locale-encoding-mapping-list"); + while (confNode != null ) { + processListener(confNode); + confNode = DomUtil.getNext(confNode); + } + + // TODO: warning about uniqueness of servlet name, filter name + + } catch (Exception e) { + e.printStackTrace(); + throw new ServletException(e); + } + } + + private void processContextParam(Node confNode) { + ctx.getContextParameters().put("", ""); + } + + + /** Process anotations. + */ + private void processMetadata() { + + } + + private void processListener(Node confNode) { + String lClass = DomUtil.getChildContent(confNode, "listener-class"); + ctx.getListenersClassName().add(lClass); + } + + private void processServlet(Node confNode) throws ServletException { + String name = DomUtil.getChildContent(confNode,"servlet-name"); + String sclass = DomUtil.getChildContent(confNode,"servlet-class"); + + HashMap initParams = new HashMap(); + processInitParams(confNode, initParams); + + ServletConfigImpl wrapper = (ServletConfigImpl) + facade.createServletWrapper(ctx, name, sclass, initParams); + + ctx.addServletConfig((ServletConfigImpl) wrapper); + } + + private void processInitParams(Node confNode, HashMap initParams) { + Node initN = DomUtil.getChild(confNode, "init-param"); + while (initN != null ) { + String n = DomUtil.getChildContent(initN, "param-name"); + String v = DomUtil.getChildContent(initN, "param-value"); + initParams.put(n, v); + confNode = DomUtil.getNext(initN); + } + } + + private void processServletMapping(Node confNode) { + String name = DomUtil.getChildContent(confNode,"servlet-name"); + String path = DomUtil.getChildContent(confNode,"url-pattern"); + + ServletConfigImpl wrapper = ctx.getServletConfig(name); + facade.addMapping(path, wrapper); + } + + private void processFilterMapping(Node confNode) { + String name = DomUtil.getChildContent(confNode,"filter-name"); + // multiple + ArrayList dispatchers = new ArrayList(); + Node dataN = DomUtil.getChild(confNode, "dispatcher"); + while (dataN != null ) { + String d = DomUtil.getContent(dataN); + dispatchers.add(d); + dataN = DomUtil.getNext(dataN); + } + String[] dispA = new String[ dispatchers.size() ]; + if (dispA.length > 0) { + dispatchers.toArray(dispA); + } + + dataN = DomUtil.getChild(confNode, "url-pattern"); + while (dataN != null ) { + String path = DomUtil.getContent(dataN); + dataN = DomUtil.getNext(dataN); + ctx.getFilterMapper().addMapping(name, path, null, dispA); + } + dataN = DomUtil.getChild(confNode, "servlet-name"); + while (dataN != null ) { + String sn = DomUtil.getContent(dataN); + dataN = DomUtil.getNext(dataN); + ctx.getFilterMapper().addMapping(name, null, sn, dispA); + } + } + + private void processFilter(Node confNode) { + String name = DomUtil.getChildContent(confNode,"filter-name"); + String sclass = DomUtil.getChildContent(confNode,"filter-class"); + + HashMap initParams = new HashMap(); + processInitParams(confNode, initParams); + + ctx.addFilter(name, sclass, initParams); + } + +} Added: tomcat/sandbox/resources/coyote-servlet.MF URL: http://svn.apache.org/viewvc/tomcat/sandbox/resources/coyote-servlet.MF?rev=415818&view=auto ============================================================================== --- tomcat/sandbox/resources/coyote-servlet.MF (added) +++ tomcat/sandbox/resources/coyote-servlet.MF Tue Jun 20 14:45:26 2006 @@ -0,0 +1,2 @@ +Manifest-version: 1.0 +Main-Class: org.apache.coyote.servlet.Main Propchange: tomcat/sandbox/resources/coyote-servlet.MF ------------------------------------------------------------------------------ svn:executable = * --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]