Source code: org/apache/catalina/core/ApplicationFilterChain.java
1 /*
2 * Copyright 1999,2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 package org.apache.catalina.core;
19
20
21 import java.io.IOException;
22 import java.security.Principal;
23 import java.security.PrivilegedActionException;
24
25 import javax.servlet.Filter;
26 import javax.servlet.FilterChain;
27 import javax.servlet.Servlet;
28 import javax.servlet.ServletException;
29 import javax.servlet.ServletRequest;
30 import javax.servlet.ServletResponse;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33
34 import org.apache.catalina.InstanceEvent;
35 import org.apache.catalina.security.SecurityUtil;
36 import org.apache.catalina.util.InstanceSupport;
37 import org.apache.catalina.util.StringManager;
38
39 /**
40 * Implementation of <code>javax.servlet.FilterChain</code> used to manage
41 * the execution of a set of filters for a particular request. When the
42 * set of defined filters has all been executed, the next call to
43 * <code>doFilter()</code> will execute the servlet's <code>service()</code>
44 * method itself.
45 *
46 * @author Craig R. McClanahan
47 * @version $Revision: 303523 $ $Date: 2004-11-22 11:35:18 -0500 (Mon, 22 Nov 2004) $
48 */
49
50 final class ApplicationFilterChain implements FilterChain {
51
52
53 // -------------------------------------------------------------- Constants
54
55
56 public static final int INCREMENT = 10;
57
58
59 // ----------------------------------------------------------- Constructors
60
61
62 /**
63 * Construct a new chain instance with no defined filters.
64 */
65 public ApplicationFilterChain() {
66
67 super();
68
69 }
70
71
72 // ----------------------------------------------------- Instance Variables
73
74
75 /**
76 * Filters.
77 */
78 private ApplicationFilterConfig[] filters =
79 new ApplicationFilterConfig[0];
80
81
82 /**
83 * The int which is used to maintain the current position
84 * in the filter chain.
85 */
86 private int pos = 0;
87
88
89 /**
90 * The int which gives the current number of filters in the chain.
91 */
92 private int n = 0;
93
94
95 /**
96 * The servlet instance to be executed by this chain.
97 */
98 private Servlet servlet = null;
99
100
101 /**
102 * The string manager for our package.
103 */
104 private static final StringManager sm =
105 StringManager.getManager(Constants.Package);
106
107
108 /**
109 * The InstanceSupport instance associated with our Wrapper (used to
110 * send "before filter" and "after filter" events.
111 */
112 private InstanceSupport support = null;
113
114
115 /**
116 * Static class array used when the SecurityManager is turned on and
117 * <code>doFilter</code is invoked.
118 */
119 private static Class[] classType = new Class[]{ServletRequest.class,
120 ServletResponse.class,
121 FilterChain.class};
122
123 /**
124 * Static class array used when the SecurityManager is turned on and
125 * <code>service</code is invoked.
126 */
127 private static Class[] classTypeUsedInService = new Class[]{
128 ServletRequest.class,
129 ServletResponse.class};
130
131 // ---------------------------------------------------- FilterChain Methods
132
133
134 /**
135 * Invoke the next filter in this chain, passing the specified request
136 * and response. If there are no more filters in this chain, invoke
137 * the <code>service()</code> method of the servlet itself.
138 *
139 * @param request The servlet request we are processing
140 * @param response The servlet response we are creating
141 *
142 * @exception IOException if an input/output error occurs
143 * @exception ServletException if a servlet exception occurs
144 */
145 public void doFilter(ServletRequest request, ServletResponse response)
146 throws IOException, ServletException {
147
148 if( System.getSecurityManager() != null ) {
149 final ServletRequest req = request;
150 final ServletResponse res = response;
151 try {
152 java.security.AccessController.doPrivileged(
153 new java.security.PrivilegedExceptionAction() {
154 public Object run()
155 throws ServletException, IOException {
156 internalDoFilter(req,res);
157 return null;
158 }
159 }
160 );
161 } catch( PrivilegedActionException pe) {
162 Exception e = pe.getException();
163 if (e instanceof ServletException)
164 throw (ServletException) e;
165 else if (e instanceof IOException)
166 throw (IOException) e;
167 else if (e instanceof RuntimeException)
168 throw (RuntimeException) e;
169 else
170 throw new ServletException(e.getMessage(), e);
171 }
172 } else {
173 internalDoFilter(request,response);
174 }
175 }
176
177 private void internalDoFilter(ServletRequest request,
178 ServletResponse response)
179 throws IOException, ServletException {
180
181 // Call the next filter if there is one
182 if (pos < n) {
183 ApplicationFilterConfig filterConfig = filters[pos++];
184 Filter filter = null;
185 try {
186 filter = filterConfig.getFilter();
187 support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
188 filter, request, response);
189
190 if( System.getSecurityManager() != null ) {
191 final ServletRequest req = request;
192 final ServletResponse res = response;
193 Principal principal =
194 ((HttpServletRequest) req).getUserPrincipal();
195
196 Object[] args = new Object[]{req, res, this};
197 SecurityUtil.doAsPrivilege
198 ("doFilter", filter, classType, args);
199
200 args = null;
201 } else {
202 filter.doFilter(request, response, this);
203 }
204
205 support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
206 filter, request, response);
207 } catch (IOException e) {
208 if (filter != null)
209 support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
210 filter, request, response, e);
211 throw e;
212 } catch (ServletException e) {
213 if (filter != null)
214 support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
215 filter, request, response, e);
216 throw e;
217 } catch (RuntimeException e) {
218 if (filter != null)
219 support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
220 filter, request, response, e);
221 throw e;
222 } catch (Throwable e) {
223 if (filter != null)
224 support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
225 filter, request, response, e);
226 throw new ServletException
227 (sm.getString("filterChain.filter"), e);
228 }
229 return;
230 }
231
232 // We fell off the end of the chain -- call the servlet instance
233 try {
234 support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
235 servlet, request, response);
236 if ((request instanceof HttpServletRequest) &&
237 (response instanceof HttpServletResponse)) {
238
239 if( System.getSecurityManager() != null ) {
240 final ServletRequest req = request;
241 final ServletResponse res = response;
242 Principal principal =
243 ((HttpServletRequest) req).getUserPrincipal();
244 Object[] args = new Object[]{req, res};
245 SecurityUtil.doAsPrivilege("service",
246 servlet,
247 classTypeUsedInService,
248 args,
249 principal);
250 args = null;
251 } else {
252 servlet.service((HttpServletRequest) request,
253 (HttpServletResponse) response);
254 }
255 } else {
256 servlet.service(request, response);
257 }
258 support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
259 servlet, request, response);
260 } catch (IOException e) {
261 support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
262 servlet, request, response, e);
263 throw e;
264 } catch (ServletException e) {
265 support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
266 servlet, request, response, e);
267 throw e;
268 } catch (RuntimeException e) {
269 support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
270 servlet, request, response, e);
271 throw e;
272 } catch (Throwable e) {
273 support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
274 servlet, request, response, e);
275 throw new ServletException
276 (sm.getString("filterChain.servlet"), e);
277 }
278
279 }
280
281
282 // -------------------------------------------------------- Package Methods
283
284
285
286 /**
287 * Add a filter to the set of filters that will be executed in this chain.
288 *
289 * @param filterConfig The FilterConfig for the servlet to be executed
290 */
291 void addFilter(ApplicationFilterConfig filterConfig) {
292
293 if (n == filters.length) {
294 ApplicationFilterConfig[] newFilters =
295 new ApplicationFilterConfig[n + INCREMENT];
296 System.arraycopy(filters, 0, newFilters, 0, n);
297 filters = newFilters;
298 }
299 filters[n++] = filterConfig;
300
301 }
302
303
304 /**
305 * Release references to the filters and wrapper executed by this chain.
306 */
307 void release() {
308
309 n = 0;
310 pos = 0;
311 servlet = null;
312 support = null;
313
314 }
315
316
317 /**
318 * Set the servlet that will be executed at the end of this chain.
319 *
320 * @param servlet The Wrapper for the servlet to be executed
321 */
322 void setServlet(Servlet servlet) {
323
324 this.servlet = servlet;
325
326 }
327
328
329 /**
330 * Set the InstanceSupport object used for event notifications
331 * for this filter chain.
332 *
333 * @param support The InstanceSupport object for our Wrapper
334 */
335 void setSupport(InstanceSupport support) {
336
337 this.support = support;
338
339 }
340
341
342 }