001: /*
002: * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java,v 1.30 2002/06/09 05:45:04 remm Exp $
003: * $Revision: 1.30 $
004: * $Date: 2002/06/09 05:45:04 $
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 java.io.IOException;
067: import java.io.PrintWriter;
068: import java.security.AccessController;
069: import java.security.PrivilegedExceptionAction;
070: import java.security.PrivilegedActionException;
071: import javax.servlet.RequestDispatcher;
072: import javax.servlet.Servlet;
073: import javax.servlet.ServletException;
074: import javax.servlet.ServletOutputStream;
075: import javax.servlet.ServletRequest;
076: import javax.servlet.ServletRequestWrapper;
077: import javax.servlet.ServletResponse;
078: import javax.servlet.ServletResponseWrapper;
079: import javax.servlet.UnavailableException;
080: import javax.servlet.http.HttpServlet;
081: import javax.servlet.http.HttpServletRequest;
082: import javax.servlet.http.HttpServletRequestWrapper;
083: import javax.servlet.http.HttpServletResponse;
084: import javax.servlet.http.HttpServletResponseWrapper;
085: import org.apache.catalina.Context;
086: import org.apache.catalina.Globals;
087: import org.apache.catalina.HttpRequest;
088: import org.apache.catalina.HttpResponse;
089: import org.apache.catalina.InstanceEvent;
090: import org.apache.catalina.Logger;
091: import org.apache.catalina.Request;
092: import org.apache.catalina.Response;
093: import org.apache.catalina.Wrapper;
094: import org.apache.catalina.connector.RequestFacade;
095: import org.apache.catalina.connector.ResponseFacade;
096: import org.apache.catalina.core.StandardWrapper;
097: import org.apache.catalina.util.InstanceSupport;
098: import org.apache.catalina.util.StringManager;
099:
100: /**
101: * Standard implementation of <code>RequestDispatcher</code> that allows a
102: * request to be forwarded to a different resource to create the ultimate
103: * response, or to include the output of another resource in the response
104: * from this resource. This implementation allows application level servlets
105: * to wrap the request and/or response objects that are passed on to the
106: * called resource, as long as the wrapping classes extend
107: * <code>javax.servlet.ServletRequestWrapper</code> and
108: * <code>javax.servlet.ServletResponseWrapper</code>.
109: *
110: * @author Craig R. McClanahan
111: * @version $Revision: 1.30 $ $Date: 2002/06/09 05:45:04 $
112: */
113:
114: final class ApplicationDispatcher implements RequestDispatcher {
115:
116: protected class PrivilegedForward implements
117: PrivilegedExceptionAction {
118: private ServletRequest request;
119: private ServletResponse response;
120:
121: PrivilegedForward(ServletRequest request,
122: ServletResponse response) {
123: this .request = request;
124: this .response = response;
125: }
126:
127: public Object run() throws ServletException, IOException {
128: doForward(request, response);
129: return null;
130: }
131: }
132:
133: protected class PrivilegedInclude implements
134: PrivilegedExceptionAction {
135: private ServletRequest request;
136: private ServletResponse response;
137:
138: PrivilegedInclude(ServletRequest request,
139: ServletResponse response) {
140: this .request = request;
141: this .response = response;
142: }
143:
144: public Object run() throws ServletException, IOException {
145: doInclude(request, response);
146: return null;
147: }
148: }
149:
150: // ----------------------------------------------------------- Constructors
151:
152: /**
153: * Construct a new instance of this class, configured according to the
154: * specified parameters. If both servletPath and pathInfo are
155: * <code>null</code>, it will be assumed that this RequestDispatcher
156: * was acquired by name, rather than by path.
157: *
158: * @param wrapper The Wrapper associated with the resource that will
159: * be forwarded to or included (required)
160: * @param servletPath The revised servlet path to this resource (if any)
161: * @param pathInfo The revised extra path information to this resource
162: * (if any)
163: * @param queryString Query string parameters included with this request
164: * (if any)
165: * @param name Servlet name (if a named dispatcher was created)
166: * else <code>null</code>
167: */
168: public ApplicationDispatcher(Wrapper wrapper, String servletPath,
169: String pathInfo, String queryString, String name) {
170:
171: super ();
172:
173: // Save all of our configuration parameters
174: this .wrapper = wrapper;
175: this .context = (Context) wrapper.getParent();
176: this .servletPath = servletPath;
177: this .pathInfo = pathInfo;
178: this .queryString = queryString;
179: this .name = name;
180: if (wrapper instanceof StandardWrapper)
181: this .support = ((StandardWrapper) wrapper)
182: .getInstanceSupport();
183: else
184: this .support = new InstanceSupport(wrapper);
185:
186: if (debug >= 1)
187: log("servletPath=" + this .servletPath + ", pathInfo="
188: + this .pathInfo + ", queryString=" + queryString
189: + ", name=" + this .name);
190:
191: // If this is a wrapper for a JSP page (<jsp-file>), tweak
192: // the request parameters appropriately
193: String jspFile = wrapper.getJspFile();
194: if (jspFile != null) {
195: if (debug >= 1)
196: log("-->servletPath=" + jspFile);
197: this .servletPath = jspFile;
198: }
199:
200: }
201:
202: // ----------------------------------------------------- Instance Variables
203:
204: /**
205: * The request specified by the dispatching application.
206: */
207: private ServletRequest appRequest = null;
208:
209: /**
210: * The response specified by the dispatching application.
211: */
212: private ServletResponse appResponse = null;
213:
214: /**
215: * The Context this RequestDispatcher is associated with.
216: */
217: private Context context = null;
218:
219: /**
220: * The debugging detail level for this component.
221: */
222: private int debug = 0;
223:
224: /**
225: * Are we performing an include() instead of a forward()?
226: */
227: private boolean including = false;
228:
229: /**
230: * Descriptive information about this implementation.
231: */
232: private static final String info = "org.apache.catalina.core.ApplicationDispatcher/1.0";
233:
234: /**
235: * The servlet name for a named dispatcher.
236: */
237: private String name = null;
238:
239: /**
240: * The outermost request that will be passed on to the invoked servlet.
241: */
242: private ServletRequest outerRequest = null;
243:
244: /**
245: * The outermost response that will be passed on to the invoked servlet.
246: */
247: private ServletResponse outerResponse = null;
248:
249: /**
250: * The extra path information for this RequestDispatcher.
251: */
252: private String pathInfo = null;
253:
254: /**
255: * The query string parameters for this RequestDispatcher.
256: */
257: private String queryString = null;
258:
259: /**
260: * The servlet path for this RequestDispatcher.
261: */
262: private String servletPath = null;
263:
264: /**
265: * The StringManager for this package.
266: */
267: private static final StringManager sm = StringManager
268: .getManager(Constants.Package);
269:
270: /**
271: * The InstanceSupport instance associated with our Wrapper (used to
272: * send "before dispatch" and "after dispatch" events.
273: */
274: private InstanceSupport support = null;
275:
276: /**
277: * The Wrapper associated with the resource that will be forwarded to
278: * or included.
279: */
280: private Wrapper wrapper = null;
281:
282: /**
283: * The request wrapper we have created and installed (if any).
284: */
285: private ServletRequest wrapRequest = null;
286:
287: /**
288: * The response wrapper we have created and installed (if any).
289: */
290: private ServletResponse wrapResponse = null;
291:
292: // ------------------------------------------------------------- Properties
293:
294: /**
295: * Return the descriptive information about this implementation.
296: */
297: public String getInfo() {
298:
299: return (this .info);
300:
301: }
302:
303: // --------------------------------------------------------- Public Methods
304:
305: /**
306: * Forward this request and response to another resource for processing.
307: * Any runtime exception, IOException, or ServletException thrown by the
308: * called servlet will be propogated to the caller.
309: *
310: * @param request The servlet request to be forwarded
311: * @param response The servlet response to be forwarded
312: *
313: * @exception IOException if an input/output error occurs
314: * @exception ServletException if a servlet exception occurs
315: */
316: public void forward(ServletRequest request, ServletResponse response)
317: throws ServletException, IOException {
318: if (System.getSecurityManager() != null) {
319: try {
320: PrivilegedForward dp = new PrivilegedForward(request,
321: response);
322: AccessController.doPrivileged(dp);
323: } catch (PrivilegedActionException pe) {
324: Exception e = pe.getException();
325: if (e instanceof ServletException)
326: throw (ServletException) e;
327: throw (IOException) e;
328: }
329: } else {
330: doForward(request, response);
331: }
332: }
333:
334: private void doForward(ServletRequest request,
335: ServletResponse response) throws ServletException,
336: IOException {
337:
338: // Reset any output that has been buffered, but keep headers/cookies
339: if (response.isCommitted()) {
340: if (debug >= 1)
341: log(" Forward on committed response --> ISE");
342: throw new IllegalStateException(sm
343: .getString("applicationDispatcher.forward.ise"));
344: }
345: try {
346: response.resetBuffer();
347: } catch (IllegalStateException e) {
348: if (debug >= 1)
349: log(" Forward resetBuffer() returned ISE: " + e);
350: throw e;
351: }
352:
353: // Set up to handle the specified request and response
354: setup(request, response, false);
355:
356: // Identify the HTTP-specific request and response objects (if any)
357: HttpServletRequest hrequest = null;
358: if (request instanceof HttpServletRequest)
359: hrequest = (HttpServletRequest) request;
360: HttpServletResponse hresponse = null;
361: if (response instanceof HttpServletResponse)
362: hresponse = (HttpServletResponse) response;
363:
364: // Handle a non-HTTP forward by passing the existing request/response
365: if ((hrequest == null) || (hresponse == null)) {
366:
367: if (debug >= 1)
368: log(" Non-HTTP Forward");
369: invoke(request, response);
370:
371: }
372:
373: // Handle an HTTP named dispatcher forward
374: else if ((servletPath == null) && (pathInfo == null)) {
375:
376: if (debug >= 1)
377: log(" Named Dispatcher Forward");
378: invoke(request, response);
379:
380: }
381:
382: // Handle an HTTP path-based forward
383: else {
384:
385: if (debug >= 1)
386: log(" Path Based Forward");
387:
388: ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest();
389: StringBuffer sb = new StringBuffer();
390: String contextPath = context.getPath();
391: if (contextPath != null)
392: sb.append(contextPath);
393: if (servletPath != null)
394: sb.append(servletPath);
395: if (pathInfo != null)
396: sb.append(pathInfo);
397: wrequest.setContextPath(contextPath);
398: wrequest.setRequestURI(sb.toString());
399: wrequest.setServletPath(servletPath);
400: wrequest.setPathInfo(pathInfo);
401: if (queryString != null) {
402: wrequest.setQueryString(queryString);
403: wrequest.mergeParameters(queryString);
404: }
405: invoke(outerRequest, response);
406: unwrapRequest();
407:
408: }
409:
410: // Commit and close the response before we return
411: if (debug >= 1)
412: log(" Committing and closing response");
413:
414: if (response instanceof ResponseFacade) {
415: ((ResponseFacade) response).finish();
416: } else {
417: // Close anyway
418: try {
419: response.flushBuffer();
420: } catch (IllegalStateException f) {
421: ;
422: }
423: try {
424: PrintWriter writer = response.getWriter();
425: writer.flush();
426: writer.close();
427: } catch (IllegalStateException e) {
428: try {
429: ServletOutputStream stream = response
430: .getOutputStream();
431: stream.flush();
432: stream.close();
433: } catch (IllegalStateException f) {
434: ;
435: } catch (IOException f) {
436: ;
437: }
438: } catch (IOException e) {
439: ;
440: }
441: }
442:
443: }
444:
445: /**
446: * Include the response from another resource in the current response.
447: * Any runtime exception, IOException, or ServletException thrown by the
448: * called servlet will be propogated to the caller.
449: *
450: * @param request The servlet request that is including this one
451: * @param response The servlet response to be appended to
452: *
453: * @exception IOException if an input/output error occurs
454: * @exception ServletException if a servlet exception occurs
455: */
456: public void include(ServletRequest request, ServletResponse response)
457: throws ServletException, IOException {
458: if (System.getSecurityManager() != null) {
459: try {
460: PrivilegedInclude dp = new PrivilegedInclude(request,
461: response);
462: AccessController.doPrivileged(dp);
463: } catch (PrivilegedActionException pe) {
464: Exception e = pe.getException();
465: pe.printStackTrace();
466: if (e instanceof ServletException)
467: throw (ServletException) e;
468: throw (IOException) e;
469: }
470: } else {
471: doInclude(request, response);
472: }
473: }
474:
475: private void doInclude(ServletRequest request,
476: ServletResponse response) throws ServletException,
477: IOException {
478:
479: // Set up to handle the specified request and response
480: setup(request, response, true);
481:
482: // Create a wrapped response to use for this request
483: // ServletResponse wresponse = null;
484: ServletResponse wresponse = wrapResponse();
485:
486: // Handle a non-HTTP include
487: if (!(request instanceof HttpServletRequest)
488: || !(response instanceof HttpServletResponse)) {
489:
490: if (debug >= 1)
491: log(" Non-HTTP Include");
492: invoke(request, outerResponse);
493: unwrapResponse();
494:
495: }
496:
497: // Handle an HTTP named dispatcher include
498: else if (name != null) {
499:
500: if (debug >= 1)
501: log(" Named Dispatcher Include");
502:
503: ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest();
504: wrequest.setAttribute(Globals.NAMED_DISPATCHER_ATTR, name);
505: if (servletPath != null)
506: wrequest.setServletPath(servletPath);
507: invoke(outerRequest, outerResponse);
508: unwrapRequest();
509: unwrapResponse();
510:
511: }
512:
513: // Handle an HTTP path based include
514: else {
515:
516: if (debug >= 1)
517: log(" Path Based Include");
518:
519: ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest();
520: StringBuffer sb = new StringBuffer();
521: String contextPath = context.getPath();
522: if (contextPath != null)
523: sb.append(contextPath);
524: if (servletPath != null)
525: sb.append(servletPath);
526: if (pathInfo != null)
527: sb.append(pathInfo);
528: if (sb.length() > 0)
529: wrequest.setAttribute(Globals.REQUEST_URI_ATTR, sb
530: .toString());
531: if (contextPath != null)
532: wrequest.setAttribute(Globals.CONTEXT_PATH_ATTR,
533: contextPath);
534: if (servletPath != null)
535: wrequest.setAttribute(Globals.SERVLET_PATH_ATTR,
536: servletPath);
537: if (pathInfo != null)
538: wrequest.setAttribute(Globals.PATH_INFO_ATTR, pathInfo);
539: if (queryString != null) {
540: wrequest.setAttribute(Globals.QUERY_STRING_ATTR,
541: queryString);
542: wrequest.mergeParameters(queryString);
543: }
544: // invoke(wrequest, wresponse);
545: invoke(outerRequest, outerResponse);
546: unwrapRequest();
547: unwrapResponse();
548:
549: }
550:
551: }
552:
553: // -------------------------------------------------------- Private Methods
554:
555: /**
556: * Ask the resource represented by this RequestDispatcher to process
557: * the associated request, and create (or append to) the associated
558: * response.
559: * <p>
560: * <strong>IMPLEMENTATION NOTE</strong>: This implementation assumes
561: * that no filters are applied to a forwarded or included resource,
562: * because they were already done for the original request.
563: *
564: * @param request The servlet request we are processing
565: * @param response The servlet response we are creating
566: *
567: * @exception IOException if an input/output error occurs
568: * @exception ServletException if a servlet error occurs
569: */
570: private void invoke(ServletRequest request, ServletResponse response)
571: throws IOException, ServletException {
572:
573: // Checking to see if the context classloader is the current context
574: // classloader. If it's not, we're saving it, and setting the context
575: // classloader to the Context classloader
576: ClassLoader oldCCL = Thread.currentThread()
577: .getContextClassLoader();
578: ClassLoader contextClassLoader = context.getLoader()
579: .getClassLoader();
580:
581: if (oldCCL != contextClassLoader) {
582: Thread.currentThread().setContextClassLoader(
583: contextClassLoader);
584: } else {
585: oldCCL = null;
586: }
587:
588: // Initialize local variables we may need
589: HttpServletRequest hrequest = null;
590: if (request instanceof HttpServletRequest)
591: hrequest = (HttpServletRequest) request;
592: HttpServletResponse hresponse = null;
593: if (response instanceof HttpServletResponse)
594: hresponse = (HttpServletResponse) response;
595: Servlet servlet = null;
596: IOException ioException = null;
597: ServletException servletException = null;
598: RuntimeException runtimeException = null;
599: boolean unavailable = false;
600:
601: // Check for the servlet being marked unavailable
602: if (wrapper.isUnavailable()) {
603: log(sm.getString("applicationDispatcher.isUnavailable",
604: wrapper.getName()));
605: if (hresponse == null) {
606: ; // NOTE - Not much we can do generically
607: } else {
608: long available = wrapper.getAvailable();
609: if ((available > 0L) && (available < Long.MAX_VALUE))
610: hresponse.setDateHeader("Retry-After", available);
611: hresponse.sendError(
612: HttpServletResponse.SC_SERVICE_UNAVAILABLE,
613: sm.getString(
614: "applicationDispatcher.isUnavailable",
615: wrapper.getName()));
616: }
617: unavailable = true;
618: }
619:
620: // Allocate a servlet instance to process this request
621: try {
622: if (!unavailable) {
623: // if (debug >= 2)
624: // log(" Allocating servlet instance");
625: servlet = wrapper.allocate();
626: // if ((debug >= 2) && (servlet == null))
627: // log(" No servlet instance returned!");
628: }
629: } catch (ServletException e) {
630: log(sm.getString("applicationDispatcher.allocateException",
631: wrapper.getName()), e);
632: servletException = e;
633: servlet = null;
634: } catch (Throwable e) {
635: log(sm.getString("applicationDispatcher.allocateException",
636: wrapper.getName()), e);
637: servletException = new ServletException(sm.getString(
638: "applicationDispatcher.allocateException", wrapper
639: .getName()), e);
640: servlet = null;
641: }
642:
643: // Call the service() method for the allocated servlet instance
644: try {
645: String jspFile = wrapper.getJspFile();
646: if (jspFile != null)
647: request.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
648: else
649: request.removeAttribute(Globals.JSP_FILE_ATTR);
650: support.fireInstanceEvent(
651: InstanceEvent.BEFORE_DISPATCH_EVENT, servlet,
652: request, response);
653: if (servlet != null) {
654: // if (debug >= 2)
655: // log(" Calling service(), jspFile=" + jspFile);
656: if ((hrequest != null) && (hresponse != null)) {
657: servlet.service((HttpServletRequest) request,
658: (HttpServletResponse) response);
659: } else {
660: servlet.service(request, response);
661: }
662: }
663: request.removeAttribute(Globals.JSP_FILE_ATTR);
664: support.fireInstanceEvent(
665: InstanceEvent.AFTER_DISPATCH_EVENT, servlet,
666: request, response);
667: } catch (IOException e) {
668: request.removeAttribute(Globals.JSP_FILE_ATTR);
669: support.fireInstanceEvent(
670: InstanceEvent.AFTER_DISPATCH_EVENT, servlet,
671: request, response);
672: log(sm.getString("applicationDispatcher.serviceException",
673: wrapper.getName()), e);
674: ioException = e;
675: } catch (UnavailableException e) {
676: request.removeAttribute(Globals.JSP_FILE_ATTR);
677: support.fireInstanceEvent(
678: InstanceEvent.AFTER_DISPATCH_EVENT, servlet,
679: request, response);
680: log(sm.getString("applicationDispatcher.serviceException",
681: wrapper.getName()), e);
682: servletException = e;
683: wrapper.unavailable(e);
684: } catch (ServletException e) {
685: request.removeAttribute(Globals.JSP_FILE_ATTR);
686: support.fireInstanceEvent(
687: InstanceEvent.AFTER_DISPATCH_EVENT, servlet,
688: request, response);
689: log(sm.getString("applicationDispatcher.serviceException",
690: wrapper.getName()), e);
691: servletException = e;
692: } catch (RuntimeException e) {
693: request.removeAttribute(Globals.JSP_FILE_ATTR);
694: support.fireInstanceEvent(
695: InstanceEvent.AFTER_DISPATCH_EVENT, servlet,
696: request, response);
697: log(sm.getString("applicationDispatcher.serviceException",
698: wrapper.getName()), e);
699: runtimeException = e;
700: }
701:
702: // Deallocate the allocated servlet instance
703: try {
704: if (servlet != null) {
705: // if (debug >= 2)
706: // log(" Deallocating servlet instance");
707: wrapper.deallocate(servlet);
708: }
709: } catch (ServletException e) {
710: log(sm.getString(
711: "applicationDispatcher.deallocateException",
712: wrapper.getName()), e);
713: servletException = e;
714: } catch (Throwable e) {
715: log(sm.getString(
716: "applicationDispatcher.deallocateException",
717: wrapper.getName()), e);
718: servletException = new ServletException(sm.getString(
719: "applicationDispatcher.deallocateException",
720: wrapper.getName()), e);
721: }
722:
723: // Reset the old context class loader
724: if (oldCCL != null)
725: Thread.currentThread().setContextClassLoader(oldCCL);
726:
727: // Rethrow an exception if one was thrown by the invoked servlet
728: if (ioException != null)
729: throw ioException;
730: if (servletException != null)
731: throw servletException;
732: if (runtimeException != null)
733: throw runtimeException;
734:
735: }
736:
737: /**
738: * Log a message on the Logger associated with our Context (if any)
739: *
740: * @param message Message to be logged
741: */
742: private void log(String message) {
743:
744: Logger logger = context.getLogger();
745: if (logger != null)
746: logger.log("ApplicationDispatcher[" + context.getPath()
747: + "]: " + message);
748: else
749: System.out.println("ApplicationDispatcher["
750: + context.getPath() + "]: " + message);
751:
752: }
753:
754: /**
755: * Log a message on the Logger associated with our Container (if any)
756: *
757: * @param message Message to be logged
758: * @param throwable Associated exception
759: */
760: private void log(String message, Throwable throwable) {
761:
762: Logger logger = context.getLogger();
763: if (logger != null)
764: logger.log("ApplicationDispatcher[" + context.getPath()
765: + "] " + message, throwable);
766: else {
767: System.out.println("ApplicationDispatcher["
768: + context.getPath() + "]: " + message);
769: throwable.printStackTrace(System.out);
770: }
771:
772: }
773:
774: /**
775: * Set up to handle the specified request and response
776: *
777: * @param request The servlet request specified by the caller
778: * @param response The servlet response specified by the caller
779: * @param including Are we performing an include() as opposed to
780: * a forward()?
781: */
782: private void setup(ServletRequest request,
783: ServletResponse response, boolean including) {
784:
785: this .appRequest = request;
786: this .appResponse = response;
787: this .outerRequest = request;
788: this .outerResponse = response;
789: this .including = including;
790:
791: }
792:
793: /**
794: * Unwrap the request if we have wrapped it.
795: */
796: private void unwrapRequest() {
797:
798: if (wrapRequest == null)
799: return;
800:
801: ServletRequest previous = null;
802: ServletRequest current = outerRequest;
803: while (current != null) {
804:
805: // If we run into the container request we are done
806: if ((current instanceof Request)
807: || (current instanceof RequestFacade))
808: break;
809:
810: // Remove the current request if it is our wrapper
811: if (current == wrapRequest) {
812: ServletRequest next = ((ServletRequestWrapper) current)
813: .getRequest();
814: if (previous == null)
815: outerRequest = next;
816: else
817: ((ServletRequestWrapper) previous).setRequest(next);
818: break;
819: }
820:
821: // Advance to the next request in the chain
822: previous = current;
823: current = ((ServletRequestWrapper) current).getRequest();
824:
825: }
826:
827: }
828:
829: /**
830: * Unwrap the response if we have wrapped it.
831: */
832: private void unwrapResponse() {
833:
834: if (wrapResponse == null)
835: return;
836:
837: ServletResponse previous = null;
838: ServletResponse current = outerResponse;
839: while (current != null) {
840:
841: // If we run into the container response we are done
842: if ((current instanceof Response)
843: || (current instanceof ResponseFacade))
844: break;
845:
846: // Remove the current response if it is our wrapper
847: if (current == wrapResponse) {
848: ServletResponse next = ((ServletResponseWrapper) current)
849: .getResponse();
850: if (previous == null)
851: outerResponse = next;
852: else
853: ((ServletResponseWrapper) previous)
854: .setResponse(next);
855: break;
856: }
857:
858: // Advance to the next response in the chain
859: previous = current;
860: current = ((ServletResponseWrapper) current).getResponse();
861:
862: }
863:
864: }
865:
866: /**
867: * Create and return a request wrapper that has been inserted in the
868: * appropriate spot in the request chain.
869: */
870: private ServletRequest wrapRequest() {
871:
872: // Locate the request we should insert in front of
873: ServletRequest previous = null;
874: ServletRequest current = outerRequest;
875: while (current != null) {
876: if ("org.apache.catalina.servlets.InvokerHttpRequest"
877: .equals(current.getClass().getName()))
878: break; // KLUDGE - Make nested RD.forward() using invoker work
879: if (!(current instanceof ServletRequestWrapper))
880: break;
881: if (current instanceof ApplicationHttpRequest)
882: break;
883: if (current instanceof ApplicationRequest)
884: break;
885: if (current instanceof Request)
886: break;
887: previous = current;
888: current = ((ServletRequestWrapper) current).getRequest();
889: }
890:
891: // Instantiate a new wrapper at this point and insert it in the chain
892: ServletRequest wrapper = null;
893: if ((current instanceof ApplicationHttpRequest)
894: || (current instanceof HttpRequest)
895: || (current instanceof HttpServletRequest))
896: wrapper = new ApplicationHttpRequest(
897: (HttpServletRequest) current);
898: else
899: wrapper = new ApplicationRequest(current);
900: if (previous == null)
901: outerRequest = wrapper;
902: else
903: ((ServletRequestWrapper) previous).setRequest(wrapper);
904: wrapRequest = wrapper;
905: return (wrapper);
906:
907: }
908:
909: /**
910: * Create and return a response wrapper that has been inserted in the
911: * appropriate spot in the response chain.
912: */
913: private ServletResponse wrapResponse() {
914:
915: // Locate the response we should insert in front of
916: ServletResponse previous = null;
917: ServletResponse current = outerResponse;
918: while (current != null) {
919: if (!(current instanceof ServletResponseWrapper))
920: break;
921: if (current instanceof ApplicationHttpResponse)
922: break;
923: if (current instanceof ApplicationResponse)
924: break;
925: if (current instanceof Response)
926: break;
927: previous = current;
928: current = ((ServletResponseWrapper) current).getResponse();
929: }
930:
931: // Instantiate a new wrapper at this point and insert it in the chain
932: ServletResponse wrapper = null;
933: if ((current instanceof ApplicationHttpResponse)
934: || (current instanceof HttpResponse)
935: || (current instanceof HttpServletResponse))
936: wrapper = new ApplicationHttpResponse(
937: (HttpServletResponse) current, including);
938: else
939: wrapper = new ApplicationResponse(current, including);
940: if (previous == null)
941: outerResponse = wrapper;
942: else
943: ((ServletResponseWrapper) previous).setResponse(wrapper);
944: wrapResponse = wrapper;
945: return (wrapper);
946:
947: }
948:
949: }
|