1
17 package org.apache.catalina.core;
18
19 import java.io.IOException;
20 import java.io.PrintWriter;
21 import java.security.AccessController;
22 import java.security.PrivilegedActionException;
23 import java.security.PrivilegedExceptionAction;
24
25 import javax.servlet.AsyncContext;
26 import javax.servlet.DispatcherType;
27 import javax.servlet.RequestDispatcher;
28 import javax.servlet.Servlet;
29 import javax.servlet.ServletException;
30 import javax.servlet.ServletOutputStream;
31 import javax.servlet.ServletRequest;
32 import javax.servlet.ServletRequestWrapper;
33 import javax.servlet.ServletResponse;
34 import javax.servlet.ServletResponseWrapper;
35 import javax.servlet.UnavailableException;
36 import javax.servlet.http.HttpServletMapping;
37 import javax.servlet.http.HttpServletRequest;
38 import javax.servlet.http.HttpServletResponse;
39
40 import org.apache.catalina.AsyncDispatcher;
41 import org.apache.catalina.Context;
42 import org.apache.catalina.Globals;
43 import org.apache.catalina.Wrapper;
44 import org.apache.catalina.connector.ClientAbortException;
45 import org.apache.catalina.connector.Request;
46 import org.apache.catalina.connector.RequestFacade;
47 import org.apache.catalina.connector.Response;
48 import org.apache.catalina.connector.ResponseFacade;
49 import org.apache.tomcat.util.ExceptionUtils;
50 import org.apache.tomcat.util.res.StringManager;
51
52
64 final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher {
65
66 static final boolean STRICT_SERVLET_COMPLIANCE;
67
68 static final boolean WRAP_SAME_OBJECT;
69
70
71 static {
72 STRICT_SERVLET_COMPLIANCE = Globals.STRICT_SERVLET_COMPLIANCE;
73
74 String wrapSameObject = System.getProperty(
75 "org.apache.catalina.core.ApplicationDispatcher.WRAP_SAME_OBJECT");
76 if (wrapSameObject == null) {
77 WRAP_SAME_OBJECT = STRICT_SERVLET_COMPLIANCE;
78 } else {
79 WRAP_SAME_OBJECT = Boolean.parseBoolean(wrapSameObject);
80 }
81 }
82
83
84 protected class PrivilegedForward
85 implements PrivilegedExceptionAction<Void> {
86 private final ServletRequest request;
87 private final ServletResponse response;
88
89 PrivilegedForward(ServletRequest request, ServletResponse response) {
90 this.request = request;
91 this.response = response;
92 }
93
94 @Override
95 public Void run() throws java.lang.Exception {
96 doForward(request,response);
97 return null;
98 }
99 }
100
101 protected class PrivilegedInclude implements
102 PrivilegedExceptionAction<Void> {
103 private final ServletRequest request;
104 private final ServletResponse response;
105
106 PrivilegedInclude(ServletRequest request, ServletResponse response) {
107 this.request = request;
108 this.response = response;
109 }
110
111 @Override
112 public Void run() throws ServletException, IOException {
113 doInclude(request, response);
114 return null;
115 }
116 }
117
118 protected class PrivilegedDispatch implements
119 PrivilegedExceptionAction<Void> {
120 private final ServletRequest request;
121 private final ServletResponse response;
122
123 PrivilegedDispatch(ServletRequest request, ServletResponse response) {
124 this.request = request;
125 this.response = response;
126 }
127
128 @Override
129 public Void run() throws ServletException, IOException {
130 doDispatch(request, response);
131 return null;
132 }
133 }
134
135
136
141 private static class State {
142 State(ServletRequest request, ServletResponse response,
143 boolean including) {
144 this.outerRequest = request;
145 this.outerResponse = response;
146 this.including = including;
147 }
148
149
152 ServletRequest outerRequest = null;
153
154
155
158 ServletResponse outerResponse = null;
159
160
163 ServletRequest wrapRequest = null;
164
165
166
169 ServletResponse wrapResponse = null;
170
171
174 boolean including = false;
175
176
179 HttpServletRequest hrequest = null;
180
181
184 HttpServletResponse hresponse = null;
185 }
186
187
188
189
190
208 public ApplicationDispatcher
209 (Wrapper wrapper, String requestURI, String servletPath,
210 String pathInfo, String queryString, HttpServletMapping mapping, String name) {
211
212 super();
213
214
215 this.wrapper = wrapper;
216 this.context = (Context) wrapper.getParent();
217 this.requestURI = requestURI;
218 this.servletPath = servletPath;
219 this.pathInfo = pathInfo;
220 this.queryString = queryString;
221 this.mapping = mapping;
222 this.name = name;
223 }
224
225
226
227
228
231 private final Context context;
232
233
234
237 private final String name;
238
239
240
243 private final String pathInfo;
244
245
246
249 private final String queryString;
250
251
252
255 private final String requestURI;
256
257
258
261 private final String servletPath;
262
263
264
267 private final HttpServletMapping mapping;
268
269
270
273 private static final StringManager sm = StringManager.getManager(Constants.Package);
274
275
276
280 private final Wrapper wrapper;
281
282
283
284
285
286
297 @Override
298 public void forward(ServletRequest request, ServletResponse response)
299 throws ServletException, IOException
300 {
301 if (Globals.IS_SECURITY_ENABLED) {
302 try {
303 PrivilegedForward dp = new PrivilegedForward(request,response);
304 AccessController.doPrivileged(dp);
305 } catch (PrivilegedActionException pe) {
306 Exception e = pe.getException();
307 if (e instanceof ServletException)
308 throw (ServletException) e;
309 throw (IOException) e;
310 }
311 } else {
312 doForward(request,response);
313 }
314 }
315
316 private void doForward(ServletRequest request, ServletResponse response)
317 throws ServletException, IOException
318 {
319
320
321 if (response.isCommitted()) {
322 throw new IllegalStateException
323 (sm.getString("applicationDispatcher.forward.ise"));
324 }
325 try {
326 response.resetBuffer();
327 } catch (IllegalStateException e) {
328 throw e;
329 }
330
331
332 State state = new State(request, response, false);
333
334 if (WRAP_SAME_OBJECT) {
335
336 checkSameObjects(request, response);
337 }
338
339 wrapResponse(state);
340
341 if ((servletPath == null) && (pathInfo == null)) {
342
343 ApplicationHttpRequest wrequest =
344 (ApplicationHttpRequest) wrapRequest(state);
345 HttpServletRequest hrequest = state.hrequest;
346 wrequest.setRequestURI(hrequest.getRequestURI());
347 wrequest.setContextPath(hrequest.getContextPath());
348 wrequest.setServletPath(hrequest.getServletPath());
349 wrequest.setPathInfo(hrequest.getPathInfo());
350 wrequest.setQueryString(hrequest.getQueryString());
351
352 processRequest(request,response,state);
353 }
354
355
356 else {
357
358 ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest(state);
359 HttpServletRequest hrequest = state.hrequest;
360 if (hrequest.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI) == null) {
361 wrequest.setAttribute(RequestDispatcher.FORWARD_REQUEST_URI,
362 hrequest.getRequestURI());
363 wrequest.setAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH,
364 hrequest.getContextPath());
365 wrequest.setAttribute(RequestDispatcher.FORWARD_SERVLET_PATH,
366 hrequest.getServletPath());
367 wrequest.setAttribute(RequestDispatcher.FORWARD_PATH_INFO,
368 hrequest.getPathInfo());
369 wrequest.setAttribute(RequestDispatcher.FORWARD_QUERY_STRING,
370 hrequest.getQueryString());
371 wrequest.setAttribute(RequestDispatcher.FORWARD_MAPPING, hrequest.getHttpServletMapping());
372 }
373
374 wrequest.setContextPath(context.getEncodedPath());
375 wrequest.setRequestURI(requestURI);
376 wrequest.setServletPath(servletPath);
377 wrequest.setPathInfo(pathInfo);
378 if (queryString != null) {
379 wrequest.setQueryString(queryString);
380 wrequest.setQueryParams(queryString);
381 }
382 wrequest.setMapping(mapping);
383
384 processRequest(request,response,state);
385 }
386
387 if (request.isAsyncStarted()) {
388
389
390 return;
391 }
392
393
394 if (wrapper.getLogger().isDebugEnabled() )
395 wrapper.getLogger().debug(" Disabling the response for further output");
396
397 if (response instanceof ResponseFacade) {
398 ((ResponseFacade) response).finish();
399 } else {
400
401
402 if (wrapper.getLogger().isDebugEnabled()){
403 wrapper.getLogger().debug( " The Response is vehiculed using a wrapper: "
404 + response.getClass().getName() );
405 }
406
407
408 try {
409 PrintWriter writer = response.getWriter();
410 writer.close();
411 } catch (IllegalStateException e) {
412 try {
413 ServletOutputStream stream = response.getOutputStream();
414 stream.close();
415 } catch (IllegalStateException f) {
416
417 } catch (IOException f) {
418
419 }
420 } catch (IOException e) {
421
422 }
423 }
424
425 }
426
427
428
437 private void processRequest(ServletRequest request,
438 ServletResponse response,
439 State state)
440 throws IOException, ServletException {
441
442 DispatcherType disInt = (DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);
443 if (disInt != null) {
444 boolean doInvoke = true;
445
446 if (context.getFireRequestListenersOnForwards() &&
447 !context.fireRequestInitEvent(request)) {
448 doInvoke = false;
449 }
450
451 if (doInvoke) {
452 if (disInt != DispatcherType.ERROR) {
453 state.outerRequest.setAttribute(
454 Globals.DISPATCHER_REQUEST_PATH_ATTR,
455 getCombinedPath());
456 state.outerRequest.setAttribute(
457 Globals.DISPATCHER_TYPE_ATTR,
458 DispatcherType.FORWARD);
459 invoke(state.outerRequest, response, state);
460 } else {
461 invoke(state.outerRequest, response, state);
462 }
463
464 if (context.getFireRequestListenersOnForwards()) {
465 context.fireRequestDestroyEvent(request);
466 }
467 }
468 }
469 }
470
471
472
478 private String getCombinedPath() {
479 if (servletPath == null) {
480 return null;
481 }
482 if (pathInfo == null) {
483 return servletPath;
484 }
485 return servletPath + pathInfo;
486 }
487
488
489
500 @Override
501 public void include(ServletRequest request, ServletResponse response)
502 throws ServletException, IOException
503 {
504 if (Globals.IS_SECURITY_ENABLED) {
505 try {
506 PrivilegedInclude dp = new PrivilegedInclude(request,response);
507 AccessController.doPrivileged(dp);
508 } catch (PrivilegedActionException pe) {
509 Exception e = pe.getException();
510
511 if (e instanceof ServletException)
512 throw (ServletException) e;
513 throw (IOException) e;
514 }
515 } else {
516 doInclude(request, response);
517 }
518 }
519
520 private void doInclude(ServletRequest request, ServletResponse response)
521 throws ServletException, IOException {
522
523
524 State state = new State(request, response, true);
525
526 if (WRAP_SAME_OBJECT) {
527
528 checkSameObjects(request, response);
529 }
530
531
532 wrapResponse(state);
533
534
535 if (name != null) {
536
537 ApplicationHttpRequest wrequest =
538 (ApplicationHttpRequest) wrapRequest(state);
539 wrequest.setAttribute(Globals.NAMED_DISPATCHER_ATTR, name);
540 if (servletPath != null)
541 wrequest.setServletPath(servletPath);
542 wrequest.setAttribute(Globals.DISPATCHER_TYPE_ATTR,
543 DispatcherType.INCLUDE);
544 wrequest.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
545 getCombinedPath());
546 invoke(state.outerRequest, state.outerResponse, state);
547 }
548
549
550 else {
551
552 ApplicationHttpRequest wrequest =
553 (ApplicationHttpRequest) wrapRequest(state);
554 String contextPath = context.getPath();
555 if (requestURI != null)
556 wrequest.setAttribute(RequestDispatcher.INCLUDE_REQUEST_URI,
557 requestURI);
558 if (contextPath != null)
559 wrequest.setAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH,
560 contextPath);
561 if (servletPath != null)
562 wrequest.setAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH,
563 servletPath);
564 if (pathInfo != null)
565 wrequest.setAttribute(RequestDispatcher.INCLUDE_PATH_INFO,
566 pathInfo);
567 if (queryString != null) {
568 wrequest.setAttribute(RequestDispatcher.INCLUDE_QUERY_STRING,
569 queryString);
570 wrequest.setQueryParams(queryString);
571 }
572 if (mapping != null) {
573 wrequest.setAttribute(RequestDispatcher.INCLUDE_MAPPING, mapping);
574 }
575
576 wrequest.setAttribute(Globals.DISPATCHER_TYPE_ATTR,
577 DispatcherType.INCLUDE);
578 wrequest.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
579 getCombinedPath());
580 invoke(state.outerRequest, state.outerResponse, state);
581 }
582
583 }
584
585
586 @Override
587 public void dispatch(ServletRequest request, ServletResponse response)
588 throws ServletException, IOException {
589 if (Globals.IS_SECURITY_ENABLED) {
590 try {
591 PrivilegedDispatch dp = new PrivilegedDispatch(request,response);
592 AccessController.doPrivileged(dp);
593 } catch (PrivilegedActionException pe) {
594 Exception e = pe.getException();
595
596 if (e instanceof ServletException)
597 throw (ServletException) e;
598 throw (IOException) e;
599 }
600 } else {
601 doDispatch(request, response);
602 }
603 }
604
605 private void doDispatch(ServletRequest request, ServletResponse response)
606 throws ServletException, IOException {
607
608
609 State state = new State(request, response, false);
610
611
612 wrapResponse(state);
613
614 ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest(state);
615 HttpServletRequest hrequest = state.hrequest;
616
617 wrequest.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ASYNC);
618 wrequest.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, getCombinedPath());
619 wrequest.setAttribute(AsyncContext.ASYNC_MAPPING, hrequest.getHttpServletMapping());
620
621 wrequest.setContextPath(context.getEncodedPath());
622 wrequest.setRequestURI(requestURI);
623 wrequest.setServletPath(servletPath);
624 wrequest.setPathInfo(pathInfo);
625 if (queryString != null) {
626 wrequest.setQueryString(queryString);
627 wrequest.setQueryParams(queryString);
628 }
629 if (!Globals.STRICT_SERVLET_COMPLIANCE) {
630 wrequest.setMapping(mapping);
631 }
632
633 invoke(state.outerRequest, state.outerResponse, state);
634 }
635
636
637
638
639
640
655 private void invoke(ServletRequest request, ServletResponse response,
656 State state) throws IOException, ServletException {
657
658
659
660
661 ClassLoader oldCCL = context.bind(false, null);
662
663
664 HttpServletResponse hresponse = state.hresponse;
665 Servlet servlet = null;
666 IOException ioException = null;
667 ServletException servletException = null;
668 RuntimeException runtimeException = null;
669 boolean unavailable = false;
670
671
672 if (wrapper.isUnavailable()) {
673 wrapper.getLogger().warn(
674 sm.getString("applicationDispatcher.isUnavailable",
675 wrapper.getName()));
676 long available = wrapper.getAvailable();
677 if ((available > 0L) && (available < Long.MAX_VALUE))
678 hresponse.setDateHeader("Retry-After", available);
679 hresponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm
680 .getString("applicationDispatcher.isUnavailable", wrapper
681 .getName()));
682 unavailable = true;
683 }
684
685
686 try {
687 if (!unavailable) {
688 servlet = wrapper.allocate();
689 }
690 } catch (ServletException e) {
691 wrapper.getLogger().error(sm.getString("applicationDispatcher.allocateException",
692 wrapper.getName()), StandardWrapper.getRootCause(e));
693 servletException = e;
694 } catch (Throwable e) {
695 ExceptionUtils.handleThrowable(e);
696 wrapper.getLogger().error(sm.getString("applicationDispatcher.allocateException",
697 wrapper.getName()), e);
698 servletException = new ServletException
699 (sm.getString("applicationDispatcher.allocateException",
700 wrapper.getName()), e);
701 servlet = null;
702 }
703
704
705 ApplicationFilterChain filterChain =
706 ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
707
708
709 try {
710
711 if ((servlet != null) && (filterChain != null)) {
712 filterChain.doFilter(request, response);
713 }
714
715 } catch (ClientAbortException e) {
716 ioException = e;
717 } catch (IOException e) {
718 wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",
719 wrapper.getName()), e);
720 ioException = e;
721 } catch (UnavailableException e) {
722 wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",
723 wrapper.getName()), e);
724 servletException = e;
725 wrapper.unavailable(e);
726 } catch (ServletException e) {
727 Throwable rootCause = StandardWrapper.getRootCause(e);
728 if (!(rootCause instanceof ClientAbortException)) {
729 wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",
730 wrapper.getName()), rootCause);
731 }
732 servletException = e;
733 } catch (RuntimeException e) {
734 wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",
735 wrapper.getName()), e);
736 runtimeException = e;
737 }
738
739
740 try {
741 if (filterChain != null)
742 filterChain.release();
743 } catch (Throwable e) {
744 ExceptionUtils.handleThrowable(e);
745 wrapper.getLogger().error(sm.getString("standardWrapper.releaseFilters",
746 wrapper.getName()), e);
747
748 }
749
750
751 try {
752 if (servlet != null) {
753 wrapper.deallocate(servlet);
754 }
755 } catch (ServletException e) {
756 wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException",
757 wrapper.getName()), e);
758 servletException = e;
759 } catch (Throwable e) {
760 ExceptionUtils.handleThrowable(e);
761 wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException",
762 wrapper.getName()), e);
763 servletException = new ServletException
764 (sm.getString("applicationDispatcher.deallocateException",
765 wrapper.getName()), e);
766 }
767
768
769 context.unbind(false, oldCCL);
770
771
772
773 unwrapRequest(state);
774 unwrapResponse(state);
775
776 recycleRequestWrapper(state);
777
778
779 if (ioException != null)
780 throw ioException;
781 if (servletException != null)
782 throw servletException;
783 if (runtimeException != null)
784 throw runtimeException;
785
786 }
787
788
789
792 private void unwrapRequest(State state) {
793
794 if (state.wrapRequest == null)
795 return;
796
797 if (state.outerRequest.isAsyncStarted()) {
798 if (!state.outerRequest.getAsyncContext().hasOriginalRequestAndResponse()) {
799 return;
800 }
801 }
802
803 ServletRequest previous = null;
804 ServletRequest current = state.outerRequest;
805 while (current != null) {
806
807
808 if ((current instanceof Request)
809 || (current instanceof RequestFacade))
810 break;
811
812
813 if (current == state.wrapRequest) {
814 ServletRequest next =
815 ((ServletRequestWrapper) current).getRequest();
816 if (previous == null)
817 state.outerRequest = next;
818 else
819 ((ServletRequestWrapper) previous).setRequest(next);
820 break;
821 }
822
823
824 previous = current;
825 current = ((ServletRequestWrapper) current).getRequest();
826
827 }
828
829 }
830
831
834 private void unwrapResponse(State state) {
835
836 if (state.wrapResponse == null)
837 return;
838
839 if (state.outerRequest.isAsyncStarted()) {
840 if (!state.outerRequest.getAsyncContext().hasOriginalRequestAndResponse()) {
841 return;
842 }
843 }
844
845 ServletResponse previous = null;
846 ServletResponse current = state.outerResponse;
847 while (current != null) {
848
849
850 if ((current instanceof Response)
851 || (current instanceof ResponseFacade))
852 break;
853
854
855 if (current == state.wrapResponse) {
856 ServletResponse next =
857 ((ServletResponseWrapper) current).getResponse();
858 if (previous == null)
859 state.outerResponse = next;
860 else
861 ((ServletResponseWrapper) previous).setResponse(next);
862 break;
863 }
864
865
866 previous = current;
867 current = ((ServletResponseWrapper) current).getResponse();
868
869 }
870
871 }
872
873
874
878 private ServletRequest wrapRequest(State state) {
879
880
881 ServletRequest previous = null;
882 ServletRequest current = state.outerRequest;
883 while (current != null) {
884 if(state.hrequest == null && (current instanceof HttpServletRequest))
885 state.hrequest = (HttpServletRequest)current;
886 if (!(current instanceof ServletRequestWrapper))
887 break;
888 if (current instanceof ApplicationHttpRequest)
889 break;
890 if (current instanceof ApplicationRequest)
891 break;
892 previous = current;
893 current = ((ServletRequestWrapper) current).getRequest();
894 }
895
896
897 ServletRequest wrapper = null;
898 if ((current instanceof ApplicationHttpRequest) ||
899 (current instanceof Request) ||
900 (current instanceof HttpServletRequest)) {
901
902 HttpServletRequest hcurrent = (HttpServletRequest) current;
903 boolean crossContext = false;
904 if ((state.outerRequest instanceof ApplicationHttpRequest) ||
905 (state.outerRequest instanceof Request) ||
906 (state.outerRequest instanceof HttpServletRequest)) {
907 HttpServletRequest houterRequest =
908 (HttpServletRequest) state.outerRequest;
909 Object contextPath = houterRequest.getAttribute(
910 RequestDispatcher.INCLUDE_CONTEXT_PATH);
911 if (contextPath == null) {
912
913 contextPath = houterRequest.getContextPath();
914 }
915 crossContext = !(context.getPath().equals(contextPath));
916 }
917 wrapper = new ApplicationHttpRequest
918 (hcurrent, context, crossContext);
919 } else {
920 wrapper = new ApplicationRequest(current);
921 }
922 if (previous == null)
923 state.outerRequest = wrapper;
924 else
925 ((ServletRequestWrapper) previous).setRequest(wrapper);
926 state.wrapRequest = wrapper;
927 return wrapper;
928
929 }
930
931
932
936 private ServletResponse wrapResponse(State state) {
937
938
939 ServletResponse previous = null;
940 ServletResponse current = state.outerResponse;
941 while (current != null) {
942 if(state.hresponse == null && (current instanceof HttpServletResponse)) {
943 state.hresponse = (HttpServletResponse)current;
944 if(!state.including)
945 return null;
946 }
947 if (!(current instanceof ServletResponseWrapper))
948 break;
949 if (current instanceof ApplicationHttpResponse)
950 break;
951 if (current instanceof ApplicationResponse)
952 break;
953 previous = current;
954 current = ((ServletResponseWrapper) current).getResponse();
955 }
956
957
958 ServletResponse wrapper = null;
959 if ((current instanceof ApplicationHttpResponse) ||
960 (current instanceof Response) ||
961 (current instanceof HttpServletResponse))
962 wrapper =
963 new ApplicationHttpResponse((HttpServletResponse) current,
964 state.including);
965 else
966 wrapper = new ApplicationResponse(current, state.including);
967 if (previous == null)
968 state.outerResponse = wrapper;
969 else
970 ((ServletResponseWrapper) previous).setResponse(wrapper);
971 state.wrapResponse = wrapper;
972 return wrapper;
973
974 }
975
976 private void checkSameObjects(ServletRequest appRequest,
977 ServletResponse appResponse) throws ServletException {
978 ServletRequest originalRequest =
979 ApplicationFilterChain.getLastServicedRequest();
980 ServletResponse originalResponse =
981 ApplicationFilterChain.getLastServicedResponse();
982
983
984 if (originalRequest == null || originalResponse == null) {
985 return;
986 }
987
988 boolean same = false;
989 ServletRequest dispatchedRequest = appRequest;
990
991
992 while (originalRequest instanceof ServletRequestWrapper &&
993 ((ServletRequestWrapper) originalRequest).getRequest()!=null ) {
994 originalRequest =
995 ((ServletRequestWrapper) originalRequest).getRequest();
996 }
997
998 while (!same) {
999 if (originalRequest.equals(dispatchedRequest)) {
1000 same = true;
1001 }
1002 if (!same && dispatchedRequest instanceof ServletRequestWrapper) {
1003 dispatchedRequest =
1004 ((ServletRequestWrapper) dispatchedRequest).getRequest();
1005 } else {
1006 break;
1007 }
1008 }
1009 if (!same) {
1010 throw new ServletException(sm.getString(
1011 "applicationDispatcher.specViolation.request"));
1012 }
1013
1014 same = false;
1015 ServletResponse dispatchedResponse = appResponse;
1016
1017
1018 while (originalResponse instanceof ServletResponseWrapper &&
1019 ((ServletResponseWrapper) originalResponse).getResponse() !=
1020 null ) {
1021 originalResponse =
1022 ((ServletResponseWrapper) originalResponse).getResponse();
1023 }
1024
1025 while (!same) {
1026 if (originalResponse.equals(dispatchedResponse)) {
1027 same = true;
1028 }
1029
1030 if (!same && dispatchedResponse instanceof ServletResponseWrapper) {
1031 dispatchedResponse =
1032 ((ServletResponseWrapper) dispatchedResponse).getResponse();
1033 } else {
1034 break;
1035 }
1036 }
1037
1038 if (!same) {
1039 throw new ServletException(sm.getString(
1040 "applicationDispatcher.specViolation.response"));
1041 }
1042 }
1043
1044 private void recycleRequestWrapper(State state) {
1045 if (state.wrapRequest instanceof ApplicationHttpRequest) {
1046 ((ApplicationHttpRequest) state.wrapRequest).recycle();
1047 }
1048 }
1049 }
1050