001: /*
002: * Copyright 1999,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.catalina.core;
018:
019: import javax.servlet.Servlet;
020: import javax.servlet.ServletRequest;
021: import javax.servlet.http.HttpServletRequest;
022:
023: import org.apache.catalina.Globals;
024: import org.apache.catalina.Request;
025: import org.apache.catalina.Wrapper;
026: import org.apache.catalina.deploy.FilterMap;
027:
028: /**
029: * Factory for the creation and caching of Filters and creationg
030: * of Filter Chains.
031: *
032: * @author Greg Murray
033: * @author Remy Maucherat
034: * @version $Revision: 1.0
035: */
036:
037: public final class ApplicationFilterFactory {
038:
039: // -------------------------------------------------------------- Constants
040:
041: public static final int ERROR = 1;
042: public static final Integer ERROR_INTEGER = new Integer(ERROR);
043: public static final int FORWARD = 2;
044: public static final Integer FORWARD_INTEGER = new Integer(FORWARD);
045: public static final int INCLUDE = 4;
046: public static final Integer INCLUDE_INTEGER = new Integer(INCLUDE);
047: public static final int REQUEST = 8;
048: public static final Integer REQUEST_INTEGER = new Integer(REQUEST);
049:
050: public static final String DISPATCHER_TYPE_ATTR = Globals.DISPATCHER_TYPE_ATTR;
051: public static final String DISPATCHER_REQUEST_PATH_ATTR = Globals.DISPATCHER_REQUEST_PATH_ATTR;
052:
053: private static final SecurityManager securityManager = System
054: .getSecurityManager();
055:
056: private static ApplicationFilterFactory factory = null;;
057:
058: // ----------------------------------------------------------- Constructors
059:
060: /*
061: * Prevent instanciation outside of the getInstanceMethod().
062: */
063: private ApplicationFilterFactory() {
064: }
065:
066: // --------------------------------------------------------- Public Methods
067:
068: /**
069: * Return the fqctory instance.
070: */
071: public static ApplicationFilterFactory getInstance() {
072: if (factory == null) {
073: factory = new ApplicationFilterFactory();
074: }
075: return factory;
076: }
077:
078: /**
079: * Construct and return a FilterChain implementation that will wrap the
080: * execution of the specified servlet instance. If we should not execute
081: * a filter chain at all, return <code>null</code>.
082: *
083: * @param request The servlet request we are processing
084: * @param servlet The servlet instance to be wrapped
085: */
086: public ApplicationFilterChain createFilterChain(
087: ServletRequest request, Wrapper wrapper, Servlet servlet) {
088:
089: // get the dispatcher type
090: int dispatcher = -1;
091: if (request.getAttribute(DISPATCHER_TYPE_ATTR) != null) {
092: Integer dispatcherInt = (Integer) request
093: .getAttribute(DISPATCHER_TYPE_ATTR);
094: dispatcher = dispatcherInt.intValue();
095: }
096: String requestPath = null;
097: Object attribute = request
098: .getAttribute(DISPATCHER_REQUEST_PATH_ATTR);
099:
100: if (attribute != null) {
101: requestPath = attribute.toString();
102: }
103:
104: HttpServletRequest hreq = null;
105: if (request instanceof HttpServletRequest)
106: hreq = (HttpServletRequest) request;
107: // If there is no servlet to execute, return null
108: if (servlet == null)
109: return (null);
110:
111: // Create and initialize a filter chain object
112: ApplicationFilterChain filterChain = null;
113: if ((securityManager == null) && (request instanceof Request)) {
114: Request req = (Request) request;
115: filterChain = (ApplicationFilterChain) req.getFilterChain();
116: if (filterChain == null) {
117: filterChain = new ApplicationFilterChain();
118: req.setFilterChain(filterChain);
119: }
120: } else {
121: // Security: Do not recycle
122: filterChain = new ApplicationFilterChain();
123: }
124:
125: filterChain.setServlet(servlet);
126:
127: filterChain.setSupport(((StandardWrapper) wrapper)
128: .getInstanceSupport());
129:
130: // Acquire the filter mappings for this Context
131: StandardContext context = (StandardContext) wrapper.getParent();
132: FilterMap filterMaps[] = context.findFilterMaps();
133:
134: // If there are no filter mappings, we are done
135: if ((filterMaps == null) || (filterMaps.length == 0))
136: return (filterChain);
137:
138: // Acquire the information we will need to match filter mappings
139: String servletName = wrapper.getName();
140:
141: int n = 0;
142:
143: // Add the relevant path-mapped filters to this filter chain
144: for (int i = 0; i < filterMaps.length; i++) {
145: if (!matchDispatcher(filterMaps[i], dispatcher)) {
146: continue;
147: }
148: if (!matchFiltersURL(filterMaps[i], requestPath))
149: continue;
150: ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context
151: .findFilterConfig(filterMaps[i].getFilterName());
152: if (filterConfig == null) {
153: ; // FIXME - log configuration problem
154: continue;
155: }
156: filterChain.addFilter(filterConfig);
157: n++;
158: }
159:
160: // Add filters that match on servlet name second
161: for (int i = 0; i < filterMaps.length; i++) {
162: if (!matchDispatcher(filterMaps[i], dispatcher)) {
163: continue;
164: }
165: if (!matchFiltersServlet(filterMaps[i], servletName))
166: continue;
167: ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context
168: .findFilterConfig(filterMaps[i].getFilterName());
169: if (filterConfig == null) {
170: ; // FIXME - log configuration problem
171: continue;
172: }
173: filterChain.addFilter(filterConfig);
174: n++;
175: }
176:
177: // Return the completed filter chain
178: return (filterChain);
179:
180: }
181:
182: // -------------------------------------------------------- Private Methods
183:
184: /**
185: * Return <code>true</code> if the context-relative request path
186: * matches the requirements of the specified filter mapping;
187: * otherwise, return <code>null</code>.
188: *
189: * @param filterMap Filter mapping being checked
190: * @param requestPath Context-relative request path of this request
191: */
192: private boolean matchFiltersURL(FilterMap filterMap,
193: String requestPath) {
194:
195: if (requestPath == null)
196: return (false);
197:
198: // Match on context relative request path
199: String testPath = filterMap.getURLPattern();
200: if (testPath == null)
201: return (false);
202:
203: // Case 1 - Exact Match
204: if (testPath.equals(requestPath))
205: return (true);
206:
207: // Case 2 - Path Match ("/.../*")
208: if (testPath.equals("/*"))
209: return (true);
210: if (testPath.endsWith("/*")) {
211: if (testPath.regionMatches(0, requestPath, 0, testPath
212: .length() - 2)) {
213: if (requestPath.length() == (testPath.length() - 2)) {
214: return (true);
215: } else if ('/' == requestPath
216: .charAt(testPath.length() - 2)) {
217: return (true);
218: }
219: }
220: return (false);
221: }
222:
223: // Case 3 - Extension Match
224: if (testPath.startsWith("*.")) {
225: int slash = requestPath.lastIndexOf('/');
226: int period = requestPath.lastIndexOf('.');
227: if ((slash >= 0)
228: && (period > slash)
229: && (period != requestPath.length() - 1)
230: && ((requestPath.length() - period) == (testPath
231: .length() - 1))) {
232: return (testPath.regionMatches(2, requestPath,
233: period + 1, testPath.length() - 2));
234: }
235: }
236:
237: // Case 4 - "Default" Match
238: return (false); // NOTE - Not relevant for selecting filters
239:
240: }
241:
242: /**
243: * Return <code>true</code> if the specified servlet name matches
244: * the requirements of the specified filter mapping; otherwise
245: * return <code>false</code>.
246: *
247: * @param filterMap Filter mapping being checked
248: * @param servletName Servlet name being checked
249: */
250: private boolean matchFiltersServlet(FilterMap filterMap,
251: String servletName) {
252:
253: if (servletName == null) {
254: return (false);
255: } else {
256: if (servletName.equals(filterMap.getServletName())) {
257: return (true);
258: } else {
259: return false;
260: }
261: }
262:
263: }
264:
265: /**
266: * Convienience method which returns true if the dispatcher type
267: * matches the dispatcher types specified in the FilterMap
268: */
269: private boolean matchDispatcher(FilterMap filterMap, int dispatcher) {
270: switch (dispatcher) {
271: case FORWARD: {
272: if (filterMap.getDispatcherMapping() == FilterMap.FORWARD
273: || filterMap.getDispatcherMapping() == FilterMap.FORWARD_ERROR
274: || filterMap.getDispatcherMapping() == FilterMap.INCLUDE_FORWARD
275: || filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR_FORWARD
276: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD
277: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD
278: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD_INCLUDE
279: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD_INCLUDE) {
280: return true;
281: }
282: break;
283: }
284: case INCLUDE: {
285: if (filterMap.getDispatcherMapping() == FilterMap.INCLUDE
286: || filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR
287: || filterMap.getDispatcherMapping() == FilterMap.INCLUDE_FORWARD
288: || filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR_FORWARD
289: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_INCLUDE
290: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_INCLUDE
291: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD_INCLUDE
292: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD_INCLUDE) {
293: return true;
294: }
295: break;
296: }
297: case REQUEST: {
298: if (filterMap.getDispatcherMapping() == FilterMap.REQUEST
299: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR
300: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_INCLUDE
301: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_INCLUDE
302: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD
303: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD
304: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD_INCLUDE
305: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD_INCLUDE) {
306: return true;
307: }
308: break;
309: }
310: case ERROR: {
311: if (filterMap.getDispatcherMapping() == FilterMap.ERROR
312: || filterMap.getDispatcherMapping() == FilterMap.FORWARD_ERROR
313: || filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR
314: || filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR_FORWARD
315: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR
316: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD
317: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD_INCLUDE
318: || filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_INCLUDE) {
319: return true;
320: }
321: break;
322: }
323: }
324: return false;
325: }
326:
327: }
|