001: /*
002: * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/StandardContextMapper.java,v 1.8 2002/03/14 20:58:24 remm Exp $
003: * $Revision: 1.8 $
004: * $Date: 2002/03/14 20:58:24 $
005: *
006: * ====================================================================
007: *
008: * The Apache Software License, Version 1.1
009: *
010: * Copyright (c) 1999 The Apache Software Foundation. All rights
011: * reserved.
012: *
013: * Redistribution and use in source and binary forms, with or without
014: * modification, are permitted provided that the following conditions
015: * are met:
016: *
017: * 1. Redistributions of source code must retain the above copyright
018: * notice, this list of conditions and the following disclaimer.
019: *
020: * 2. Redistributions in binary form must reproduce the above copyright
021: * notice, this list of conditions and the following disclaimer in
022: * the documentation and/or other materials provided with the
023: * distribution.
024: *
025: * 3. The end-user documentation included with the redistribution, if
026: * any, must include the following acknowlegement:
027: * "This product includes software developed by the
028: * Apache Software Foundation (http://www.apache.org/)."
029: * Alternately, this acknowlegement may appear in the software itself,
030: * if and wherever such third-party acknowlegements normally appear.
031: *
032: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
033: * Foundation" must not be used to endorse or promote products derived
034: * from this software without prior written permission. For written
035: * permission, please contact apache@apache.org.
036: *
037: * 5. Products derived from this software may not be called "Apache"
038: * nor may "Apache" appear in their names without prior written
039: * permission of the Apache Group.
040: *
041: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
042: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
043: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
044: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
045: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
046: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
047: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
048: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
049: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
050: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
051: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
052: * SUCH DAMAGE.
053: * ====================================================================
054: *
055: * This software consists of voluntary contributions made by many
056: * individuals on behalf of the Apache Software Foundation. For more
057: * information on the Apache Software Foundation, please see
058: * <http://www.apache.org/>.
059: *
060: * [Additional notices, if required by prior licensing conditions]
061: *
062: */
063:
064: package org.apache.catalina.core;
065:
066: import javax.servlet.http.HttpServletRequest;
067: import org.apache.catalina.Container;
068: import org.apache.catalina.Context;
069: import org.apache.catalina.HttpRequest;
070: import org.apache.catalina.Mapper;
071: import org.apache.catalina.Request;
072: import org.apache.catalina.Wrapper;
073: import org.apache.catalina.util.RequestUtil;
074: import org.apache.catalina.util.StringManager;
075:
076: /**
077: * Implementation of <code>Mapper</code> for a <code>Context</code>,
078: * designed to process HTTP requests. This mapper selects an appropriate
079: * <code>Wrapper</code> based on the request URI included in the request.
080: * <p>
081: * <b>IMPLEMENTATION NOTE</b>: This Mapper only works with a
082: * <code>StandardContext</code>, because it relies on internal APIs.
083: *
084: * @author Craig R. McClanahan
085: * @version $Revision: 1.8 $ $Date: 2002/03/14 20:58:24 $
086: */
087:
088: public final class StandardContextMapper implements Mapper {
089:
090: // ----------------------------------------------------- Instance Variables
091:
092: /**
093: * The Container with which this Mapper is associated.
094: */
095: private StandardContext context = null;
096:
097: /**
098: * The protocol with which this Mapper is associated.
099: */
100: private String protocol = null;
101:
102: /**
103: * The string manager for this package.
104: */
105: private static final StringManager sm = StringManager
106: .getManager(Constants.Package);
107:
108: // ------------------------------------------------------------- Properties
109:
110: /**
111: * Return the Container with which this Mapper is associated.
112: */
113: public Container getContainer() {
114:
115: return (context);
116:
117: }
118:
119: /**
120: * Set the Container with which this Mapper is associated.
121: *
122: * @param container The newly associated Container
123: *
124: * @exception IllegalArgumentException if this Container is not
125: * acceptable to this Mapper
126: */
127: public void setContainer(Container container) {
128:
129: if (!(container instanceof StandardContext))
130: throw new IllegalArgumentException(sm
131: .getString("httpContextMapper.container"));
132: context = (StandardContext) container;
133:
134: }
135:
136: /**
137: * Return the protocol for which this Mapper is responsible.
138: */
139: public String getProtocol() {
140:
141: return (this .protocol);
142:
143: }
144:
145: /**
146: * Set the protocol for which this Mapper is responsible.
147: *
148: * @param protocol The newly associated protocol
149: */
150: public void setProtocol(String protocol) {
151:
152: this .protocol = protocol;
153:
154: }
155:
156: // --------------------------------------------------------- Public Methods
157:
158: /**
159: * Return the child Container that should be used to process this Request,
160: * based upon its characteristics. If no such child Container can be
161: * identified, return <code>null</code> instead.
162: *
163: * @param request Request being processed
164: * @param update Update the Request to reflect the mapping selection?
165: *
166: * @exception IllegalArgumentException if the relative portion of the
167: * path cannot be URL decoded
168: */
169: public Container map(Request request, boolean update) {
170:
171: int debug = context.getDebug();
172:
173: // Has this request already been mapped?
174: if (update && (request.getWrapper() != null))
175: return (request.getWrapper());
176:
177: // Identify the context-relative URI to be mapped
178: String contextPath = ((HttpServletRequest) request.getRequest())
179: .getContextPath();
180: String requestURI = ((HttpRequest) request)
181: .getDecodedRequestURI();
182: String relativeURI = requestURI.substring(contextPath.length());
183: if (debug >= 1)
184: context.log("Mapping contextPath='" + contextPath
185: + "' with requestURI='" + requestURI
186: + "' and relativeURI='" + relativeURI + "'");
187:
188: // Apply the standard request URI mapping rules from the specification
189: Wrapper wrapper = null;
190: String servletPath = relativeURI;
191: String pathInfo = null;
192: String name = null;
193:
194: // Rule 1 -- Exact Match
195: if (wrapper == null) {
196: if (debug >= 2)
197: context.log(" Trying exact match");
198: if (!(relativeURI.equals("/")))
199: name = context.findServletMapping(relativeURI);
200: if (name != null)
201: wrapper = (Wrapper) context.findChild(name);
202: if (wrapper != null) {
203: servletPath = relativeURI;
204: pathInfo = null;
205: }
206: }
207:
208: // Rule 2 -- Prefix Match
209: if (wrapper == null) {
210: if (debug >= 2)
211: context.log(" Trying prefix match");
212: servletPath = relativeURI;
213: while (true) {
214: name = context.findServletMapping(servletPath + "/*");
215: if (name != null)
216: wrapper = (Wrapper) context.findChild(name);
217: if (wrapper != null) {
218: pathInfo = relativeURI.substring(servletPath
219: .length());
220: if (pathInfo.length() == 0)
221: pathInfo = null;
222: break;
223: }
224: int slash = servletPath.lastIndexOf('/');
225: if (slash < 0)
226: break;
227: servletPath = servletPath.substring(0, slash);
228: }
229: }
230:
231: // Rule 3 -- Extension Match
232: if (wrapper == null) {
233: if (debug >= 2)
234: context.log(" Trying extension match");
235: int slash = relativeURI.lastIndexOf('/');
236: if (slash >= 0) {
237: String last = relativeURI.substring(slash);
238: int period = last.lastIndexOf('.');
239: if (period >= 0) {
240: String pattern = "*" + last.substring(period);
241: name = context.findServletMapping(pattern);
242: if (name != null)
243: wrapper = (Wrapper) context.findChild(name);
244: if (wrapper != null) {
245: servletPath = relativeURI;
246: pathInfo = null;
247: }
248: }
249: }
250: }
251:
252: // Rule 4 -- Default Match
253: if (wrapper == null) {
254: if (debug >= 2)
255: context.log(" Trying default match");
256: name = context.findServletMapping("/");
257: if (name != null)
258: wrapper = (Wrapper) context.findChild(name);
259: if (wrapper != null) {
260: servletPath = relativeURI;
261: pathInfo = null;
262: }
263: }
264:
265: // Update the Request (if requested) and return this Wrapper
266: if ((debug >= 1) && (wrapper != null))
267: context.log(" Mapped to servlet '" + wrapper.getName()
268: + "' with servlet path '" + servletPath
269: + "' and path info '" + pathInfo + "' and update="
270: + update);
271: if (update) {
272: request.setWrapper(wrapper);
273: ((HttpRequest) request).setServletPath(servletPath);
274: ((HttpRequest) request).setPathInfo(pathInfo);
275: }
276: return (wrapper);
277:
278: }
279:
280: }
|