You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2006/06/20 23:45:28 UTC
svn commit: r415818 [3/3] - in /tomcat/sandbox:
java/org/apache/coyote/servlet/ java/org/apache/coyote/servlet/mapper/
java/org/apache/coyote/servlet/servlets/
java/org/apache/coyote/servlet/util/ java/org/apache/coyote/servlet/webxml/
java/org/apache/...
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: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org