001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.catalina.core;
019:
020: import java.io.IOException;
021: import java.security.Principal;
022: import java.security.PrivilegedActionException;
023:
024: import javax.servlet.Filter;
025: import javax.servlet.FilterChain;
026: import javax.servlet.Servlet;
027: import javax.servlet.ServletException;
028: import javax.servlet.ServletRequest;
029: import javax.servlet.ServletResponse;
030: import javax.servlet.http.HttpServletRequest;
031: import javax.servlet.http.HttpServletResponse;
032:
033: import org.apache.catalina.CometEvent;
034: import org.apache.catalina.CometFilter;
035: import org.apache.catalina.CometFilterChain;
036: import org.apache.catalina.CometProcessor;
037: import org.apache.catalina.Globals;
038: import org.apache.catalina.InstanceEvent;
039: import org.apache.catalina.security.SecurityUtil;
040: import org.apache.catalina.util.InstanceSupport;
041: import org.apache.catalina.util.StringManager;
042:
043: /**
044: * Implementation of <code>javax.servlet.FilterChain</code> used to manage
045: * the execution of a set of filters for a particular request. When the
046: * set of defined filters has all been executed, the next call to
047: * <code>doFilter()</code> will execute the servlet's <code>service()</code>
048: * method itself.
049: *
050: * @author Craig R. McClanahan
051: * @version $Revision: 505593 $ $Date: 2007-02-10 01:54:56 +0100 (sam., 10 févr. 2007) $
052: */
053:
054: final class ApplicationFilterChain implements FilterChain,
055: CometFilterChain {
056:
057: // Used to enforce requirements of SRV.8.2 / SRV.14.2.5.1
058: private final static ThreadLocal lastServicedRequest;
059: private final static ThreadLocal lastServicedResponse;
060:
061: static {
062: if (Globals.STRICT_SERVLET_COMPLIANCE) {
063: lastServicedRequest = new ThreadLocal();
064: lastServicedResponse = new ThreadLocal();
065: } else {
066: lastServicedRequest = null;
067: lastServicedResponse = null;
068: }
069: }
070:
071: // -------------------------------------------------------------- Constants
072:
073: public static final int INCREMENT = 10;
074:
075: // ----------------------------------------------------------- Constructors
076:
077: /**
078: * Construct a new chain instance with no defined filters.
079: */
080: public ApplicationFilterChain() {
081:
082: super ();
083:
084: }
085:
086: // ----------------------------------------------------- Instance Variables
087:
088: /**
089: * Filters.
090: */
091: private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
092:
093: /**
094: * The int which is used to maintain the current position
095: * in the filter chain.
096: */
097: private int pos = 0;
098:
099: /**
100: * The int which gives the current number of filters in the chain.
101: */
102: private int n = 0;
103:
104: /**
105: * The servlet instance to be executed by this chain.
106: */
107: private Servlet servlet = null;
108:
109: /**
110: * The string manager for our package.
111: */
112: private static final StringManager sm = StringManager
113: .getManager(Constants.Package);
114:
115: /**
116: * The InstanceSupport instance associated with our Wrapper (used to
117: * send "before filter" and "after filter" events.
118: */
119: private InstanceSupport support = null;
120:
121: /**
122: * Static class array used when the SecurityManager is turned on and
123: * <code>doFilter</code> is invoked.
124: */
125: private static Class[] classType = new Class[] {
126: ServletRequest.class, ServletResponse.class,
127: FilterChain.class };
128:
129: /**
130: * Static class array used when the SecurityManager is turned on and
131: * <code>service</code> is invoked.
132: */
133: private static Class[] classTypeUsedInService = new Class[] {
134: ServletRequest.class, ServletResponse.class };
135:
136: /**
137: * Static class array used when the SecurityManager is turned on and
138: * <code>doFilterEvent</code> is invoked.
139: */
140: private static Class[] cometClassType = new Class[] {
141: CometEvent.class, CometFilterChain.class };
142:
143: /**
144: * Static class array used when the SecurityManager is turned on and
145: * <code>event</code> is invoked.
146: */
147: private static Class[] classTypeUsedInEvent = new Class[] { CometEvent.class };
148:
149: // ---------------------------------------------------- FilterChain Methods
150:
151: /**
152: * Invoke the next filter in this chain, passing the specified request
153: * and response. If there are no more filters in this chain, invoke
154: * the <code>service()</code> method of the servlet itself.
155: *
156: * @param request The servlet request we are processing
157: * @param response The servlet response we are creating
158: *
159: * @exception IOException if an input/output error occurs
160: * @exception ServletException if a servlet exception occurs
161: */
162: public void doFilter(ServletRequest request,
163: ServletResponse response) throws IOException,
164: ServletException {
165:
166: if (Globals.IS_SECURITY_ENABLED) {
167: final ServletRequest req = request;
168: final ServletResponse res = response;
169: try {
170: java.security.AccessController
171: .doPrivileged(new java.security.PrivilegedExceptionAction() {
172: public Object run()
173: throws ServletException,
174: IOException {
175: internalDoFilter(req, res);
176: return null;
177: }
178: });
179: } catch (PrivilegedActionException pe) {
180: Exception e = pe.getException();
181: if (e instanceof ServletException)
182: throw (ServletException) e;
183: else if (e instanceof IOException)
184: throw (IOException) e;
185: else if (e instanceof RuntimeException)
186: throw (RuntimeException) e;
187: else
188: throw new ServletException(e.getMessage(), e);
189: }
190: } else {
191: internalDoFilter(request, response);
192: }
193: }
194:
195: private void internalDoFilter(ServletRequest request,
196: ServletResponse response) throws IOException,
197: ServletException {
198:
199: // Call the next filter if there is one
200: if (pos < n) {
201: ApplicationFilterConfig filterConfig = filters[pos++];
202: Filter filter = null;
203: try {
204: filter = filterConfig.getFilter();
205: support.fireInstanceEvent(
206: InstanceEvent.BEFORE_FILTER_EVENT, filter,
207: request, response);
208:
209: if (Globals.IS_SECURITY_ENABLED) {
210: final ServletRequest req = request;
211: final ServletResponse res = response;
212: Principal principal = ((HttpServletRequest) req)
213: .getUserPrincipal();
214:
215: Object[] args = new Object[] { req, res, this };
216: SecurityUtil.doAsPrivilege("doFilter", filter,
217: classType, args);
218:
219: args = null;
220: } else {
221: filter.doFilter(request, response, this );
222: }
223:
224: support.fireInstanceEvent(
225: InstanceEvent.AFTER_FILTER_EVENT, filter,
226: request, response);
227: } catch (IOException e) {
228: if (filter != null)
229: support.fireInstanceEvent(
230: InstanceEvent.AFTER_FILTER_EVENT, filter,
231: request, response, e);
232: throw e;
233: } catch (ServletException e) {
234: if (filter != null)
235: support.fireInstanceEvent(
236: InstanceEvent.AFTER_FILTER_EVENT, filter,
237: request, response, e);
238: throw e;
239: } catch (RuntimeException e) {
240: if (filter != null)
241: support.fireInstanceEvent(
242: InstanceEvent.AFTER_FILTER_EVENT, filter,
243: request, response, e);
244: throw e;
245: } catch (Throwable e) {
246: if (filter != null)
247: support.fireInstanceEvent(
248: InstanceEvent.AFTER_FILTER_EVENT, filter,
249: request, response, e);
250: throw new ServletException(sm
251: .getString("filterChain.filter"), e);
252: }
253: return;
254: }
255:
256: // We fell off the end of the chain -- call the servlet instance
257: try {
258: if (Globals.STRICT_SERVLET_COMPLIANCE) {
259: lastServicedRequest.set(request);
260: lastServicedResponse.set(response);
261: }
262:
263: support.fireInstanceEvent(
264: InstanceEvent.BEFORE_SERVICE_EVENT, servlet,
265: request, response);
266: if ((request instanceof HttpServletRequest)
267: && (response instanceof HttpServletResponse)) {
268:
269: if (Globals.IS_SECURITY_ENABLED) {
270: final ServletRequest req = request;
271: final ServletResponse res = response;
272: Principal principal = ((HttpServletRequest) req)
273: .getUserPrincipal();
274: Object[] args = new Object[] { req, res };
275: SecurityUtil.doAsPrivilege("service", servlet,
276: classTypeUsedInService, args, principal);
277: args = null;
278: } else {
279: servlet.service((HttpServletRequest) request,
280: (HttpServletResponse) response);
281: }
282: } else {
283: servlet.service(request, response);
284: }
285: support.fireInstanceEvent(
286: InstanceEvent.AFTER_SERVICE_EVENT, servlet,
287: request, response);
288: } catch (IOException e) {
289: support.fireInstanceEvent(
290: InstanceEvent.AFTER_SERVICE_EVENT, servlet,
291: request, response, e);
292: throw e;
293: } catch (ServletException e) {
294: support.fireInstanceEvent(
295: InstanceEvent.AFTER_SERVICE_EVENT, servlet,
296: request, response, e);
297: throw e;
298: } catch (RuntimeException e) {
299: support.fireInstanceEvent(
300: InstanceEvent.AFTER_SERVICE_EVENT, servlet,
301: request, response, e);
302: throw e;
303: } catch (Throwable e) {
304: support.fireInstanceEvent(
305: InstanceEvent.AFTER_SERVICE_EVENT, servlet,
306: request, response, e);
307: throw new ServletException(sm
308: .getString("filterChain.servlet"), e);
309: } finally {
310: if (Globals.STRICT_SERVLET_COMPLIANCE) {
311: lastServicedRequest.set(null);
312: lastServicedResponse.set(null);
313: }
314: }
315:
316: }
317:
318: /**
319: * Invoke the next filter in this chain, passing the specified request
320: * and response. If there are no more filters in this chain, invoke
321: * the <code>service()</code> method of the servlet itself.
322: *
323: * @param request The servlet request we are processing
324: * @param response The servlet response we are creating
325: *
326: * @exception IOException if an input/output error occurs
327: * @exception ServletException if a servlet exception occurs
328: */
329: public void doFilterEvent(CometEvent event) throws IOException,
330: ServletException {
331:
332: if (Globals.IS_SECURITY_ENABLED) {
333: final CometEvent ev = event;
334: try {
335: java.security.AccessController
336: .doPrivileged(new java.security.PrivilegedExceptionAction() {
337: public Object run()
338: throws ServletException,
339: IOException {
340: internalDoFilterEvent(ev);
341: return null;
342: }
343: });
344: } catch (PrivilegedActionException pe) {
345: Exception e = pe.getException();
346: if (e instanceof ServletException)
347: throw (ServletException) e;
348: else if (e instanceof IOException)
349: throw (IOException) e;
350: else if (e instanceof RuntimeException)
351: throw (RuntimeException) e;
352: else
353: throw new ServletException(e.getMessage(), e);
354: }
355: } else {
356: internalDoFilterEvent(event);
357: }
358: }
359:
360: /**
361: * The last request passed to a servlet for servicing from the current
362: * thread.
363: *
364: * @return The last request to be serviced.
365: */
366: public static ServletRequest getLastServicedRequest() {
367: return (ServletRequest) lastServicedRequest.get();
368: }
369:
370: /**
371: * The last response passed to a servlet for servicing from the current
372: * thread.
373: *
374: * @return The last response to be serviced.
375: */
376: public static ServletResponse getLastServicedResponse() {
377: return (ServletResponse) lastServicedResponse.get();
378: }
379:
380: private void internalDoFilterEvent(CometEvent event)
381: throws IOException, ServletException {
382:
383: // Call the next filter if there is one
384: if (pos < n) {
385: ApplicationFilterConfig filterConfig = filters[pos++];
386: CometFilter filter = null;
387: try {
388: filter = (CometFilter) filterConfig.getFilter();
389: // FIXME: No instance listener processing for events for now
390: /*
391: support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
392: filter, event);
393: */
394:
395: if (Globals.IS_SECURITY_ENABLED) {
396: final CometEvent ev = event;
397: Principal principal = ev.getHttpServletRequest()
398: .getUserPrincipal();
399:
400: Object[] args = new Object[] { ev, this };
401: SecurityUtil.doAsPrivilege("doFilterEvent",
402: (Filter) filter, cometClassType, args);
403:
404: args = null;
405: } else {
406: filter.doFilterEvent(event, this );
407: }
408:
409: /*support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
410: filter, event);*/
411: } catch (IOException e) {
412: /*
413: if (filter != null)
414: support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
415: filter, event, e);
416: */
417: throw e;
418: } catch (ServletException e) {
419: /*
420: if (filter != null)
421: support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
422: filter, event, e);
423: */
424: throw e;
425: } catch (RuntimeException e) {
426: /*
427: if (filter != null)
428: support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
429: filter, event, e);
430: */
431: throw e;
432: } catch (Throwable e) {
433: /*if (filter != null)
434: support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
435: filter, event, e);*/
436: throw new ServletException(sm
437: .getString("filterChain.filter"), e);
438: }
439: return;
440: }
441:
442: // We fell off the end of the chain -- call the servlet instance
443: try {
444: /*
445: support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
446: servlet, request, response);
447: */
448: if (Globals.IS_SECURITY_ENABLED) {
449: final CometEvent ev = event;
450: Principal principal = ev.getHttpServletRequest()
451: .getUserPrincipal();
452: Object[] args = new Object[] { ev };
453: SecurityUtil.doAsPrivilege("event", servlet,
454: classTypeUsedInEvent, args, principal);
455: args = null;
456: } else {
457: ((CometProcessor) servlet).event(event);
458: }
459: /*
460: support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
461: servlet, request, response);*/
462: } catch (IOException e) {
463: /*
464: support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
465: servlet, request, response, e);
466: */
467: throw e;
468: } catch (ServletException e) {
469: /*
470: support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
471: servlet, request, response, e);
472: */
473: throw e;
474: } catch (RuntimeException e) {
475: /*
476: support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
477: servlet, request, response, e);
478: */
479: throw e;
480: } catch (Throwable e) {
481: /*
482: support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
483: servlet, request, response, e);
484: */
485: throw new ServletException(sm
486: .getString("filterChain.servlet"), e);
487: }
488:
489: }
490:
491: // -------------------------------------------------------- Package Methods
492:
493: /**
494: * Add a filter to the set of filters that will be executed in this chain.
495: *
496: * @param filterConfig The FilterConfig for the servlet to be executed
497: */
498: void addFilter(ApplicationFilterConfig filterConfig) {
499:
500: if (n == filters.length) {
501: ApplicationFilterConfig[] newFilters = new ApplicationFilterConfig[n
502: + INCREMENT];
503: System.arraycopy(filters, 0, newFilters, 0, n);
504: filters = newFilters;
505: }
506: filters[n++] = filterConfig;
507:
508: }
509:
510: /**
511: * Release references to the filters and wrapper executed by this chain.
512: */
513: void release() {
514:
515: for (int i = 0; i < n; i++) {
516: filters[i] = null;
517: }
518: n = 0;
519: pos = 0;
520: servlet = null;
521: support = null;
522:
523: }
524:
525: /**
526: * Prepare for reuse of the filters and wrapper executed by this chain.
527: */
528: void reuse() {
529: pos = 0;
530: }
531:
532: /**
533: * Set the servlet that will be executed at the end of this chain.
534: *
535: * @param servlet The Wrapper for the servlet to be executed
536: */
537: void setServlet(Servlet servlet) {
538:
539: this .servlet = servlet;
540:
541: }
542:
543: /**
544: * Set the InstanceSupport object used for event notifications
545: * for this filter chain.
546: *
547: * @param support The InstanceSupport object for our Wrapper
548: */
549: void setSupport(InstanceSupport support) {
550:
551: this.support = support;
552:
553: }
554:
555: }
|