KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > core > ApplicationDispatcher


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.catalina.core;
20
21 import java.io.IOException JavaDoc;
22 import java.io.PrintWriter JavaDoc;
23 import java.security.AccessController JavaDoc;
24 import java.security.PrivilegedActionException JavaDoc;
25 import java.security.PrivilegedExceptionAction JavaDoc;
26
27 import javax.servlet.RequestDispatcher JavaDoc;
28 import javax.servlet.Servlet JavaDoc;
29 import javax.servlet.ServletException JavaDoc;
30 import javax.servlet.ServletOutputStream JavaDoc;
31 import javax.servlet.ServletRequest JavaDoc;
32 import javax.servlet.ServletRequestWrapper JavaDoc;
33 import javax.servlet.ServletResponse JavaDoc;
34 import javax.servlet.ServletResponseWrapper JavaDoc;
35 import javax.servlet.UnavailableException JavaDoc;
36 import javax.servlet.http.HttpServletRequest JavaDoc;
37 import javax.servlet.http.HttpServletResponse JavaDoc;
38
39 import org.apache.catalina.Context;
40 import org.apache.catalina.Globals;
41 import org.apache.catalina.InstanceEvent;
42 import org.apache.catalina.Wrapper;
43 import org.apache.catalina.connector.ClientAbortException;
44 import org.apache.catalina.connector.Request;
45 import org.apache.catalina.connector.RequestFacade;
46 import org.apache.catalina.connector.Response;
47 import org.apache.catalina.connector.ResponseFacade;
48 import org.apache.catalina.util.InstanceSupport;
49 import org.apache.catalina.util.StringManager;
50 import org.apache.commons.logging.Log;
51 import org.apache.commons.logging.LogFactory;
52
53 /**
54  * Standard implementation of <code>RequestDispatcher</code> that allows a
55  * request to be forwarded to a different resource to create the ultimate
56  * response, or to include the output of another resource in the response
57  * from this resource. This implementation allows application level servlets
58  * to wrap the request and/or response objects that are passed on to the
59  * called resource, as long as the wrapping classes extend
60  * <code>javax.servlet.ServletRequestWrapper</code> and
61  * <code>javax.servlet.ServletResponseWrapper</code>.
62  *
63  * @author Craig R. McClanahan
64  * @version $Revision: 471281 $ $Date: 2006-11-04 23:35:15 +0100 (sam., 04 nov. 2006) $
65  */

66
67 final class ApplicationDispatcher
68     implements RequestDispatcher JavaDoc {
69
70
71     protected class PrivilegedForward implements PrivilegedExceptionAction JavaDoc {
72         private ServletRequest JavaDoc request;
73         private ServletResponse JavaDoc response;
74
75         PrivilegedForward(ServletRequest JavaDoc request, ServletResponse JavaDoc response)
76         {
77             this.request = request;
78             this.response = response;
79         }
80
81         public Object JavaDoc run() throws java.lang.Exception JavaDoc {
82             doForward(request,response);
83             return null;
84         }
85     }
86
87     protected class PrivilegedInclude implements PrivilegedExceptionAction JavaDoc {
88         private ServletRequest JavaDoc request;
89         private ServletResponse JavaDoc response;
90
91         PrivilegedInclude(ServletRequest JavaDoc request, ServletResponse JavaDoc response)
92         {
93             this.request = request;
94             this.response = response;
95         }
96
97         public Object JavaDoc run() throws ServletException JavaDoc, IOException JavaDoc {
98             doInclude(request,response);
99             return null;
100         }
101     }
102
103     // ----------------------------------------------------------- Constructors
104

105
106     /**
107      * Construct a new instance of this class, configured according to the
108      * specified parameters. If both servletPath and pathInfo are
109      * <code>null</code>, it will be assumed that this RequestDispatcher
110      * was acquired by name, rather than by path.
111      *
112      * @param wrapper The Wrapper associated with the resource that will
113      * be forwarded to or included (required)
114      * @param requestURI The request URI to this resource (if any)
115      * @param servletPath The revised servlet path to this resource (if any)
116      * @param pathInfo The revised extra path information to this resource
117      * (if any)
118      * @param queryString Query string parameters included with this request
119      * (if any)
120      * @param name Servlet name (if a named dispatcher was created)
121      * else <code>null</code>
122      */

123     public ApplicationDispatcher
124         (Wrapper JavaDoc wrapper, String JavaDoc requestURI, String JavaDoc servletPath,
125          String JavaDoc pathInfo, String JavaDoc queryString, String JavaDoc name) {
126
127         super();
128
129         // Save all of our configuration parameters
130
this.wrapper = wrapper;
131         this.context = (Context) wrapper.getParent();
132         this.requestURI = requestURI;
133         this.servletPath = servletPath;
134         this.origServletPath = servletPath;
135         this.pathInfo = pathInfo;
136         this.queryString = queryString;
137         this.name = name;
138         if (wrapper instanceof StandardWrapper)
139             this.support = ((StandardWrapper) wrapper).getInstanceSupport();
140         else
141             this.support = new InstanceSupport(wrapper);
142
143         if ( log.isDebugEnabled() )
144             log.debug("servletPath=" + this.servletPath + ", pathInfo=" +
145                 this.pathInfo + ", queryString=" + queryString +
146                 ", name=" + this.name);
147
148     }
149
150
151     // ----------------------------------------------------- Instance Variables
152

153     private static Log log = LogFactory.getLog(ApplicationDispatcher.class);
154
155     /**
156      * The request specified by the dispatching application.
157      */

158     private ServletRequest JavaDoc appRequest = null;
159
160
161     /**
162      * The response specified by the dispatching application.
163      */

164     private ServletResponse JavaDoc appResponse = null;
165
166
167     /**
168      * The Context this RequestDispatcher is associated with.
169      */

170     private Context context = null;
171
172
173     /**
174      * Are we performing an include() instead of a forward()?
175      */

176     private boolean including = false;
177
178
179     /**
180      * Descriptive information about this implementation.
181      */

182     private static final String JavaDoc info =
183         "org.apache.catalina.core.ApplicationDispatcher/1.0";
184
185
186     /**
187      * The servlet name for a named dispatcher.
188      */

189     private String JavaDoc name = null;
190
191
192     /**
193      * The outermost request that will be passed on to the invoked servlet.
194      */

195     private ServletRequest JavaDoc outerRequest = null;
196
197
198     /**
199      * The outermost response that will be passed on to the invoked servlet.
200      */

201     private ServletResponse JavaDoc outerResponse = null;
202
203
204     /**
205      * The extra path information for this RequestDispatcher.
206      */

207     private String JavaDoc pathInfo = null;
208
209
210     /**
211      * The query string parameters for this RequestDispatcher.
212      */

213     private String JavaDoc queryString = null;
214
215
216     /**
217      * The request URI for this RequestDispatcher.
218      */

219     private String JavaDoc requestURI = null;
220
221     /**
222      * The servlet path for this RequestDispatcher.
223      */

224     private String JavaDoc servletPath = null;
225
226     private String JavaDoc origServletPath = null;
227     
228     /**
229      * The StringManager for this package.
230      */

231     private static final StringManager sm =
232       StringManager.getManager(Constants.Package);
233
234
235     /**
236      * The InstanceSupport instance associated with our Wrapper (used to
237      * send "before dispatch" and "after dispatch" events.
238      */

239     private InstanceSupport support = null;
240
241
242     /**
243      * The Wrapper associated with the resource that will be forwarded to
244      * or included.
245      */

246     private Wrapper JavaDoc wrapper = null;
247
248
249     /**
250      * The request wrapper we have created and installed (if any).
251      */

252     private ServletRequest JavaDoc wrapRequest = null;
253
254
255     /**
256      * The response wrapper we have created and installed (if any).
257      */

258     private ServletResponse JavaDoc wrapResponse = null;
259
260
261     // ------------------------------------------------------------- Properties
262

263
264     /**
265      * Return the descriptive information about this implementation.
266      */

267     public String JavaDoc getInfo() {
268
269         return (info);
270
271     }
272
273
274     // --------------------------------------------------------- Public Methods
275

276
277     /**
278      * Forward this request and response to another resource for processing.
279      * Any runtime exception, IOException, or ServletException thrown by the
280      * called servlet will be propogated to the caller.
281      *
282      * @param request The servlet request to be forwarded
283      * @param response The servlet response to be forwarded
284      *
285      * @exception IOException if an input/output error occurs
286      * @exception ServletException if a servlet exception occurs
287      */

288     public void forward(ServletRequest JavaDoc request, ServletResponse JavaDoc response)
289         throws ServletException JavaDoc, IOException JavaDoc
290     {
291         if (System.getSecurityManager() != null) {
292             try {
293                 PrivilegedForward dp = new PrivilegedForward(request,response);
294                 AccessController.doPrivileged(dp);
295             } catch (PrivilegedActionException JavaDoc pe) {
296                 Exception JavaDoc e = pe.getException();
297                 if (e instanceof ServletException JavaDoc)
298                     throw (ServletException JavaDoc) e;
299                 throw (IOException JavaDoc) e;
300             }
301         } else {
302             doForward(request,response);
303         }
304     }
305
306     private void doForward(ServletRequest JavaDoc request, ServletResponse JavaDoc response)
307         throws ServletException JavaDoc, IOException JavaDoc
308     {
309         
310         // Reset any output that has been buffered, but keep headers/cookies
311
if (response.isCommitted()) {
312             if ( log.isDebugEnabled() )
313                 log.debug(" Forward on committed response --> ISE");
314             throw new IllegalStateException JavaDoc
315                 (sm.getString("applicationDispatcher.forward.ise"));
316         }
317         try {
318             response.resetBuffer();
319         } catch (IllegalStateException JavaDoc e) {
320             if ( log.isDebugEnabled() )
321                 log.debug(" Forward resetBuffer() returned ISE: " + e);
322             throw e;
323         }
324
325         // Set up to handle the specified request and response
326
setup(request, response, false);
327
328         if (Globals.STRICT_SERVLET_COMPLIANCE) {
329             // Check SRV.8.2 / SRV.14.2.5.1 compliance
330
checkSameObjects();
331         }
332
333         // Identify the HTTP-specific request and response objects (if any)
334
HttpServletRequest JavaDoc hrequest = null;
335         if (request instanceof HttpServletRequest JavaDoc)
336             hrequest = (HttpServletRequest JavaDoc) request;
337         HttpServletResponse JavaDoc hresponse = null;
338         if (response instanceof HttpServletResponse JavaDoc)
339             hresponse = (HttpServletResponse JavaDoc) response;
340
341         // Handle a non-HTTP forward by passing the existing request/response
342
if ((hrequest == null) || (hresponse == null)) {
343
344             if ( log.isDebugEnabled() )
345                 log.debug(" Non-HTTP Forward");
346             
347             processRequest(hrequest,hresponse);
348
349         }
350
351         // Handle an HTTP named dispatcher forward
352
else if ((servletPath == null) && (pathInfo == null)) {
353
354             if ( log.isDebugEnabled() )
355                 log.debug(" Named Dispatcher Forward");
356             
357             ApplicationHttpRequest wrequest =
358                 (ApplicationHttpRequest) wrapRequest();
359             wrequest.setRequestURI(hrequest.getRequestURI());
360             wrequest.setContextPath(hrequest.getContextPath());
361             wrequest.setServletPath(hrequest.getServletPath());
362             wrequest.setPathInfo(hrequest.getPathInfo());
363             wrequest.setQueryString(hrequest.getQueryString());
364
365             processRequest(request,response);
366
367             wrequest.recycle();
368             unwrapRequest();
369
370         }
371
372         // Handle an HTTP path-based forward
373
else {
374
375             if ( log.isDebugEnabled() )
376                 log.debug(" Path Based Forward");
377
378             ApplicationHttpRequest wrequest =
379                 (ApplicationHttpRequest) wrapRequest();
380             String JavaDoc contextPath = context.getPath();
381
382             if (hrequest.getAttribute(Globals.FORWARD_REQUEST_URI_ATTR) == null) {
383                 wrequest.setAttribute(Globals.FORWARD_REQUEST_URI_ATTR,
384                                       hrequest.getRequestURI());
385                 wrequest.setAttribute(Globals.FORWARD_CONTEXT_PATH_ATTR,
386                                       hrequest.getContextPath());
387                 wrequest.setAttribute(Globals.FORWARD_SERVLET_PATH_ATTR,
388                                       hrequest.getServletPath());
389                 wrequest.setAttribute(Globals.FORWARD_PATH_INFO_ATTR,
390                                       hrequest.getPathInfo());
391                 wrequest.setAttribute(Globals.FORWARD_QUERY_STRING_ATTR,
392                                       hrequest.getQueryString());
393             }
394  
395             wrequest.setContextPath(contextPath);
396             wrequest.setRequestURI(requestURI);
397             wrequest.setServletPath(servletPath);
398             wrequest.setPathInfo(pathInfo);
399             if (queryString != null) {
400                 wrequest.setQueryString(queryString);
401                 wrequest.setQueryParams(queryString);
402             }
403
404             processRequest(request,response);
405
406             wrequest.recycle();
407             unwrapRequest();
408
409         }
410
411         // This is not a real close in order to support error processing
412
if ( log.isDebugEnabled() )
413             log.debug(" Disabling the response for futher output");
414
415         if (response instanceof ResponseFacade) {
416             ((ResponseFacade) response).finish();
417         } else {
418             // Servlet SRV.6.2.2. The Resquest/Response may have been wrapped
419
// and may no longer be instance of RequestFacade
420
if (log.isDebugEnabled()){
421                 log.debug( " The Response is vehiculed using a wrapper: "
422                            + response.getClass().getName() );
423             }
424
425             // Close anyway
426
try {
427                 PrintWriter JavaDoc writer = response.getWriter();
428                 writer.close();
429             } catch (IllegalStateException JavaDoc e) {
430                 try {
431                     ServletOutputStream JavaDoc stream = response.getOutputStream();
432                     stream.close();
433                 } catch (IllegalStateException JavaDoc f) {
434                     ;
435                 } catch (IOException JavaDoc f) {
436                     ;
437                 }
438             } catch (IOException JavaDoc e) {
439                 ;
440             }
441         }
442
443     }
444
445     
446
447     /**
448      * Prepare the request based on the filter configuration.
449      * @param request The servlet request we are processing
450      * @param response The servlet response we are creating
451      *
452      * @exception IOException if an input/output error occurs
453      * @exception ServletException if a servlet error occurs
454      */

455     private void processRequest(ServletRequest JavaDoc request,
456                                 ServletResponse JavaDoc response)
457         throws IOException JavaDoc, ServletException JavaDoc {
458                 
459         Integer JavaDoc disInt = (Integer JavaDoc) request.getAttribute
460             (ApplicationFilterFactory.DISPATCHER_TYPE_ATTR);
461         if (disInt != null) {
462             if (disInt.intValue() != ApplicationFilterFactory.ERROR) {
463                 outerRequest.setAttribute
464                     (ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
465                      origServletPath);
466                 outerRequest.setAttribute
467                     (ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
468                      Integer.valueOf(ApplicationFilterFactory.FORWARD));
469                 invoke(outerRequest, response);
470             } else {
471                 invoke(outerRequest, response);
472             }
473         }
474
475     }
476     
477     
478     
479     /**
480      * Include the response from another resource in the current response.
481      * Any runtime exception, IOException, or ServletException thrown by the
482      * called servlet will be propogated to the caller.
483      *
484      * @param request The servlet request that is including this one
485      * @param response The servlet response to be appended to
486      *
487      * @exception IOException if an input/output error occurs
488      * @exception ServletException if a servlet exception occurs
489      */

490     public void include(ServletRequest JavaDoc request, ServletResponse JavaDoc response)
491         throws ServletException JavaDoc, IOException JavaDoc
492     {
493         if (System.getSecurityManager() != null) {
494             try {
495                 PrivilegedInclude dp = new PrivilegedInclude(request,response);
496                 AccessController.doPrivileged(dp);
497             } catch (PrivilegedActionException JavaDoc pe) {
498                 Exception JavaDoc e = pe.getException();
499
500                 if (e instanceof ServletException JavaDoc)
501                     throw (ServletException JavaDoc) e;
502                 throw (IOException JavaDoc) e;
503             }
504         } else {
505             doInclude(request,response);
506         }
507     }
508
509     private void doInclude(ServletRequest JavaDoc request, ServletResponse JavaDoc response)
510         throws ServletException JavaDoc, IOException JavaDoc
511     {
512         // Set up to handle the specified request and response
513
setup(request, response, true);
514
515         if (Globals.STRICT_SERVLET_COMPLIANCE) {
516             // Check SRV.8.2 / SRV.14.2.5.1 compliance
517
checkSameObjects();
518         }
519         
520         // Create a wrapped response to use for this request
521
// ServletResponse wresponse = null;
522
ServletResponse JavaDoc wresponse = wrapResponse();
523
524         // Handle a non-HTTP include
525
if (!(request instanceof HttpServletRequest JavaDoc) ||
526             !(response instanceof HttpServletResponse JavaDoc)) {
527
528             if ( log.isDebugEnabled() )
529                 log.debug(" Non-HTTP Include");
530             request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
531                     Integer.valueOf(ApplicationFilterFactory.INCLUDE));
532             request.setAttribute(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR, origServletPath);
533             invoke(request, outerResponse);
534         }
535
536         // Handle an HTTP named dispatcher include
537
else if (name != null) {
538
539             if ( log.isDebugEnabled() )
540                 log.debug(" Named Dispatcher Include");
541
542             ApplicationHttpRequest wrequest =
543                 (ApplicationHttpRequest) wrapRequest();
544             wrequest.setAttribute(Globals.NAMED_DISPATCHER_ATTR, name);
545             if (servletPath != null)
546                 wrequest.setServletPath(servletPath);
547             wrequest.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
548                     Integer.valueOf(ApplicationFilterFactory.INCLUDE));
549             wrequest.setAttribute(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR, origServletPath);
550             invoke(outerRequest, outerResponse);
551
552             wrequest.recycle();
553         }
554
555         // Handle an HTTP path based include
556
else {
557
558             if ( log.isDebugEnabled() )
559                 log.debug(" Path Based Include");
560
561             ApplicationHttpRequest wrequest =
562                 (ApplicationHttpRequest) wrapRequest();
563             String JavaDoc contextPath = context.getPath();
564             if (requestURI != null)
565                 wrequest.setAttribute(Globals.INCLUDE_REQUEST_URI_ATTR,
566                                       requestURI);
567             if (contextPath != null)
568                 wrequest.setAttribute(Globals.INCLUDE_CONTEXT_PATH_ATTR,
569                                       contextPath);
570             if (servletPath != null)
571                 wrequest.setAttribute(Globals.INCLUDE_SERVLET_PATH_ATTR,
572                                       servletPath);
573             if (pathInfo != null)
574                 wrequest.setAttribute(Globals.INCLUDE_PATH_INFO_ATTR,
575                                       pathInfo);
576             if (queryString != null) {
577                 wrequest.setAttribute(Globals.INCLUDE_QUERY_STRING_ATTR,
578                                       queryString);
579                 wrequest.setQueryParams(queryString);
580             }
581             
582             wrequest.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
583                     Integer.valueOf(ApplicationFilterFactory.INCLUDE));
584             wrequest.setAttribute(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR, origServletPath);
585             invoke(outerRequest, outerResponse);
586
587             wrequest.recycle();
588         }
589
590     }
591
592
593     // -------------------------------------------------------- Private Methods
594

595
596     /**
597      * Ask the resource represented by this RequestDispatcher to process
598      * the associated request, and create (or append to) the associated
599      * response.
600      * <p>
601      * <strong>IMPLEMENTATION NOTE</strong>: This implementation assumes
602      * that no filters are applied to a forwarded or included resource,
603      * because they were already done for the original request.
604      *
605      * @param request The servlet request we are processing
606      * @param response The servlet response we are creating
607      *
608      * @exception IOException if an input/output error occurs
609      * @exception ServletException if a servlet error occurs
610      */

611     private void invoke(ServletRequest JavaDoc request, ServletResponse JavaDoc response)
612             throws IOException JavaDoc, ServletException JavaDoc {
613
614         // Checking to see if the context classloader is the current context
615
// classloader. If it's not, we're saving it, and setting the context
616
// classloader to the Context classloader
617
ClassLoader JavaDoc oldCCL = Thread.currentThread().getContextClassLoader();
618         ClassLoader JavaDoc contextClassLoader = context.getLoader().getClassLoader();
619
620         if (oldCCL != contextClassLoader) {
621             Thread.currentThread().setContextClassLoader(contextClassLoader);
622         } else {
623             oldCCL = null;
624         }
625
626         // Initialize local variables we may need
627
HttpServletRequest JavaDoc hrequest = (HttpServletRequest JavaDoc) request;
628         HttpServletResponse JavaDoc hresponse = (HttpServletResponse JavaDoc) response;
629         Servlet JavaDoc servlet = null;
630         IOException JavaDoc ioException = null;
631         ServletException JavaDoc servletException = null;
632         RuntimeException JavaDoc runtimeException = null;
633         boolean unavailable = false;
634
635         // Check for the servlet being marked unavailable
636
if (wrapper.isUnavailable()) {
637             wrapper.getLogger().warn(
638                     sm.getString("applicationDispatcher.isUnavailable",
639                     wrapper.getName()));
640             long available = wrapper.getAvailable();
641             if ((available > 0L) && (available < Long.MAX_VALUE))
642                 hresponse.setDateHeader("Retry-After", available);
643             hresponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm
644                     .getString("applicationDispatcher.isUnavailable", wrapper
645                             .getName()));
646             unavailable = true;
647         }
648
649         // Allocate a servlet instance to process this request
650
try {
651             if (!unavailable) {
652                 servlet = wrapper.allocate();
653             }
654         } catch (ServletException JavaDoc e) {
655             wrapper.getLogger().error(sm.getString("applicationDispatcher.allocateException",
656                              wrapper.getName()), StandardWrapper.getRootCause(e));
657             servletException = e;
658             servlet = null;
659         } catch (Throwable JavaDoc e) {
660             wrapper.getLogger().error(sm.getString("applicationDispatcher.allocateException",
661                              wrapper.getName()), e);
662             servletException = new ServletException JavaDoc
663                 (sm.getString("applicationDispatcher.allocateException",
664                               wrapper.getName()), e);
665             servlet = null;
666         }
667                 
668         // Get the FilterChain Here
669
ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();
670         ApplicationFilterChain filterChain = factory.createFilterChain(request,
671                                                                 wrapper,servlet);
672         // Call the service() method for the allocated servlet instance
673
try {
674             String JavaDoc jspFile = wrapper.getJspFile();
675             if (jspFile != null)
676                 request.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
677             else
678                 request.removeAttribute(Globals.JSP_FILE_ATTR);
679             support.fireInstanceEvent(InstanceEvent.BEFORE_DISPATCH_EVENT,
680                                       servlet, request, response);
681             // for includes/forwards
682
if ((servlet != null) && (filterChain != null)) {
683                filterChain.doFilter(request, response);
684              }
685             // Servlet Service Method is called by the FilterChain
686
request.removeAttribute(Globals.JSP_FILE_ATTR);
687             support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
688                                       servlet, request, response);
689         } catch (ClientAbortException e) {
690             request.removeAttribute(Globals.JSP_FILE_ATTR);
691             support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
692                                       servlet, request, response);
693             ioException = e;
694         } catch (IOException JavaDoc e) {
695             request.removeAttribute(Globals.JSP_FILE_ATTR);
696             support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
697                                       servlet, request, response);
698             wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",
699                              wrapper.getName()), e);
700             ioException = e;
701         } catch (UnavailableException JavaDoc e) {
702             request.removeAttribute(Globals.JSP_FILE_ATTR);
703             support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
704                                       servlet, request, response);
705             wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",
706                              wrapper.getName()), e);
707             servletException = e;
708             wrapper.unavailable(e);
709         } catch (ServletException JavaDoc e) {
710             request.removeAttribute(Globals.JSP_FILE_ATTR);
711             support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
712                                       servlet, request, response);
713             Throwable JavaDoc rootCause = StandardWrapper.getRootCause(e);
714             if (!(rootCause instanceof ClientAbortException)) {
715                 wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",
716                         wrapper.getName()), rootCause);
717             }
718             servletException = e;
719         } catch (RuntimeException JavaDoc e) {
720             request.removeAttribute(Globals.JSP_FILE_ATTR);
721             support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
722                                       servlet, request, response);
723             wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",
724                              wrapper.getName()), e);
725             runtimeException = e;
726         }
727
728         // Release the filter chain (if any) for this request
729
try {
730             if (filterChain != null)
731                 filterChain.release();
732         } catch (Throwable JavaDoc e) {
733             log.error(sm.getString("standardWrapper.releaseFilters",
734                              wrapper.getName()), e);
735           //FIXME Exception handling needs to be simpiler to what is in the StandardWrapperValue
736
}
737
738         // Deallocate the allocated servlet instance
739
try {
740             if (servlet != null) {
741                 wrapper.deallocate(servlet);
742             }
743         } catch (ServletException JavaDoc e) {
744             wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException",
745                              wrapper.getName()), e);
746             servletException = e;
747         } catch (Throwable JavaDoc e) {
748             wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException",
749                              wrapper.getName()), e);
750             servletException = new ServletException JavaDoc
751                 (sm.getString("applicationDispatcher.deallocateException",
752                               wrapper.getName()), e);
753         }
754
755         // Reset the old context class loader
756
if (oldCCL != null)
757             Thread.currentThread().setContextClassLoader(oldCCL);
758         
759         // Unwrap request/response if needed
760
// See Bugzilla 30949
761
unwrapRequest();
762         unwrapResponse();
763
764         // Rethrow an exception if one was thrown by the invoked servlet
765
if (ioException != null)
766             throw ioException;
767         if (servletException != null)
768             throw servletException;
769         if (runtimeException != null)
770             throw runtimeException;
771
772     }
773
774
775     /**
776      * Set up to handle the specified request and response
777      *
778      * @param request The servlet request specified by the caller
779      * @param response The servlet response specified by the caller
780      * @param including Are we performing an include() as opposed to
781      * a forward()?
782      */

783     private void setup(ServletRequest JavaDoc request, ServletResponse JavaDoc response,
784                        boolean including) {
785
786         this.appRequest = request;
787         this.appResponse = response;
788         this.outerRequest = request;
789         this.outerResponse = response;
790         this.including = including;
791
792     }
793
794
795     /**
796      * Unwrap the request if we have wrapped it.
797      */

798     private void unwrapRequest() {
799
800         if (wrapRequest == null)
801             return;
802
803         ServletRequest JavaDoc previous = null;
804         ServletRequest JavaDoc current = outerRequest;
805         while (current != null) {
806
807             // If we run into the container request we are done
808
if ((current instanceof Request JavaDoc)
809                 || (current instanceof RequestFacade))
810                 break;
811
812             // Remove the current request if it is our wrapper
813
if (current == wrapRequest) {
814                 ServletRequest JavaDoc next =
815                   ((ServletRequestWrapper JavaDoc) current).getRequest();
816                 if (previous == null)
817                     outerRequest = next;
818                 else
819                     ((ServletRequestWrapper JavaDoc) previous).setRequest(next);
820                 break;
821             }
822
823             // Advance to the next request in the chain
824
previous = current;
825             current = ((ServletRequestWrapper JavaDoc) current).getRequest();
826
827         }
828
829     }
830
831
832     /**
833      * Unwrap the response if we have wrapped it.
834      */

835     private void unwrapResponse() {
836
837         if (wrapResponse == null)
838             return;
839
840         ServletResponse JavaDoc previous = null;
841         ServletResponse JavaDoc current = outerResponse;
842         while (current != null) {
843
844             // If we run into the container response we are done
845
if ((current instanceof Response JavaDoc)
846                 || (current instanceof ResponseFacade))
847                 break;
848
849             // Remove the current response if it is our wrapper
850
if (current == wrapResponse) {
851                 ServletResponse JavaDoc next =
852                   ((ServletResponseWrapper JavaDoc) current).getResponse();
853                 if (previous == null)
854                     outerResponse = next;
855                 else
856                     ((ServletResponseWrapper JavaDoc) previous).setResponse(next);
857                 break;
858             }
859
860             // Advance to the next response in the chain
861
previous = current;
862             current = ((ServletResponseWrapper JavaDoc) current).getResponse();
863
864         }
865
866     }
867
868
869     /**
870      * Create and return a request wrapper that has been inserted in the
871      * appropriate spot in the request chain.
872      */

873     private ServletRequest JavaDoc wrapRequest() {
874
875         // Locate the request we should insert in front of
876
ServletRequest JavaDoc previous = null;
877         ServletRequest JavaDoc current = outerRequest;
878         while (current != null) {
879             if ("org.apache.catalina.servlets.InvokerHttpRequest".
880                 equals(current.getClass().getName()))
881                 break; // KLUDGE - Make nested RD.forward() using invoker work
882
if (!(current instanceof ServletRequestWrapper JavaDoc))
883                 break;
884             if (current instanceof ApplicationHttpRequest)
885                 break;
886             if (current instanceof ApplicationRequest)
887                 break;
888             if (current instanceof Request JavaDoc)
889                 break;
890             previous = current;
891             current = ((ServletRequestWrapper JavaDoc) current).getRequest();
892         }
893
894         // Instantiate a new wrapper at this point and insert it in the chain
895
ServletRequest JavaDoc wrapper = null;
896         if ((current instanceof ApplicationHttpRequest) ||
897             (current instanceof Request JavaDoc) ||
898             (current instanceof HttpServletRequest JavaDoc)) {
899             // Compute a crossContext flag
900
HttpServletRequest JavaDoc hcurrent = (HttpServletRequest JavaDoc) current;
901             boolean crossContext = false;
902             if ((outerRequest instanceof ApplicationHttpRequest) ||
903                 (outerRequest instanceof Request JavaDoc) ||
904                 (outerRequest instanceof HttpServletRequest JavaDoc)) {
905                 HttpServletRequest JavaDoc houterRequest =
906                     (HttpServletRequest JavaDoc) outerRequest;
907                 Object JavaDoc contextPath = houterRequest.getAttribute
908                     (Globals.INCLUDE_CONTEXT_PATH_ATTR);
909                 if (contextPath == null) {
910                     // Forward
911
contextPath = houterRequest.getContextPath();
912                 }
913                 crossContext = !(context.getPath().equals(contextPath));
914             }
915             wrapper = new ApplicationHttpRequest
916                 (hcurrent, context, crossContext);
917         } else {
918             wrapper = new ApplicationRequest(current);
919         }
920         if (previous == null)
921             outerRequest = wrapper;
922         else
923             ((ServletRequestWrapper JavaDoc) previous).setRequest(wrapper);
924         wrapRequest = wrapper;
925         return (wrapper);
926
927     }
928
929
930     /**
931      * Create and return a response wrapper that has been inserted in the
932      * appropriate spot in the response chain.
933      */

934     private ServletResponse JavaDoc wrapResponse() {
935
936         // Locate the response we should insert in front of
937
ServletResponse JavaDoc previous = null;
938         ServletResponse JavaDoc current = outerResponse;
939         while (current != null) {
940             if (!(current instanceof ServletResponseWrapper JavaDoc))
941                 break;
942             if (current instanceof ApplicationHttpResponse)
943                 break;
944             if (current instanceof ApplicationResponse)
945                 break;
946             if (current instanceof Response JavaDoc)
947                 break;
948             previous = current;
949             current = ((ServletResponseWrapper JavaDoc) current).getResponse();
950         }
951
952         // Instantiate a new wrapper at this point and insert it in the chain
953
ServletResponse JavaDoc wrapper = null;
954         if ((current instanceof ApplicationHttpResponse) ||
955             (current instanceof Response JavaDoc) ||
956             (current instanceof HttpServletResponse JavaDoc))
957             wrapper =
958                 new ApplicationHttpResponse((HttpServletResponse JavaDoc) current,
959                                             including);
960         else
961             wrapper = new ApplicationResponse(current, including);
962         if (previous == null)
963             outerResponse = wrapper;
964         else
965             ((ServletResponseWrapper JavaDoc) previous).setResponse(wrapper);
966         wrapResponse = wrapper;
967         return (wrapper);
968
969     }
970
971     private void checkSameObjects() throws ServletException JavaDoc {
972         ServletRequest JavaDoc originalRequest =
973             ApplicationFilterChain.getLastServicedRequest();
974         ServletResponse JavaDoc originalResponse =
975             ApplicationFilterChain.getLastServicedResponse();
976         
977         // Some forwards, eg from valves will not set original values
978
if (originalRequest == null || originalResponse == null) {
979             return;
980         }
981         
982         boolean same = false;
983         ServletRequest JavaDoc dispatchedRequest = appRequest;
984         
985         while (!same) {
986             if (originalRequest.equals(dispatchedRequest)) {
987                 same = true;
988             }
989             if (!same && dispatchedRequest instanceof ServletRequestWrapper JavaDoc) {
990                 dispatchedRequest =
991                     ((ServletRequestWrapper JavaDoc) dispatchedRequest).getRequest();
992             } else {
993                 break;
994             }
995         }
996         if (!same) {
997             throw new ServletException JavaDoc(sm.getString(
998                     "applicationDispatcher.specViolation.request"));
999         }
1000        
1001        same = false;
1002        ServletResponse JavaDoc dispatchedResponse = appResponse;
1003        
1004        while (!same) {
1005            if (originalResponse.equals(dispatchedResponse)) {
1006                same = true;
1007            }
1008            
1009            if (!same && dispatchedResponse instanceof ServletResponseWrapper JavaDoc) {
1010                dispatchedResponse =
1011                    ((ServletResponseWrapper JavaDoc) dispatchedResponse).getResponse();
1012            } else {
1013                break;
1014            }
1015        }
1016
1017        if (!same) {
1018            throw new ServletException JavaDoc(sm.getString(
1019                    "applicationDispatcher.specViolation.response"));
1020        }
1021    }
1022}
1023
Popular Tags