Port fix for bug 34956. Enforce requirements of SRV.8.2 / SRV.14.2.5.1
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Sat, 4 Nov 2006 22:35:15 +0000 (22:35 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Sat, 4 Nov 2006 22:35:15 +0000 (22:35 +0000)
git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk@471281 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/core/ApplicationDispatcher.java
java/org/apache/catalina/core/ApplicationFilterChain.java
java/org/apache/catalina/core/LocalStrings.properties

index b0bec2f..f5e8e1d 100644 (file)
@@ -325,6 +325,11 @@ final class ApplicationDispatcher
         // Set up to handle the specified request and response
         setup(request, response, false);
 
+        if (Globals.STRICT_SERVLET_COMPLIANCE) {
+            // Check SRV.8.2 / SRV.14.2.5.1 compliance
+            checkSameObjects();
+        }
+
         // Identify the HTTP-specific request and response objects (if any)
         HttpServletRequest hrequest = null;
         if (request instanceof HttpServletRequest)
@@ -507,6 +512,11 @@ final class ApplicationDispatcher
         // Set up to handle the specified request and response
         setup(request, response, true);
 
+        if (Globals.STRICT_SERVLET_COMPLIANCE) {
+            // Check SRV.8.2 / SRV.14.2.5.1 compliance
+            checkSameObjects();
+        }
+        
         // Create a wrapped response to use for this request
         // ServletResponse wresponse = null;
         ServletResponse wresponse = wrapResponse();
@@ -958,5 +968,55 @@ final class ApplicationDispatcher
 
     }
 
+    private void checkSameObjects() throws ServletException {
+        ServletRequest originalRequest =
+            ApplicationFilterChain.getLastServicedRequest();
+        ServletResponse originalResponse =
+            ApplicationFilterChain.getLastServicedResponse();
+        
+        // Some forwards, eg from valves will not set original values 
+        if (originalRequest == null || originalResponse == null) {
+            return;
+        }
+        
+        boolean same = false;
+        ServletRequest dispatchedRequest = appRequest;
+        
+        while (!same) {
+            if (originalRequest.equals(dispatchedRequest)) {
+                same = true;
+            }
+            if (!same && dispatchedRequest instanceof ServletRequestWrapper) {
+                dispatchedRequest =
+                    ((ServletRequestWrapper) dispatchedRequest).getRequest();
+            } else {
+                break;
+            }
+        }
+        if (!same) {
+            throw new ServletException(sm.getString(
+                    "applicationDispatcher.specViolation.request"));
+        }
+        
+        same = false;
+        ServletResponse dispatchedResponse = appResponse;
+        
+        while (!same) {
+            if (originalResponse.equals(dispatchedResponse)) {
+                same = true;
+            }
+            
+            if (!same && dispatchedResponse instanceof ServletResponseWrapper) {
+                dispatchedResponse =
+                    ((ServletResponseWrapper) dispatchedResponse).getResponse();
+            } else {
+                break;
+            }
+        }
 
+        if (!same) {
+            throw new ServletException(sm.getString(
+                    "applicationDispatcher.specViolation.response"));
+        }
+    }
 }
index 375879e..0e884db 100644 (file)
@@ -36,6 +36,7 @@ import org.apache.catalina.CometEvent;
 import org.apache.catalina.CometFilter;
 import org.apache.catalina.CometFilterChain;
 import org.apache.catalina.CometProcessor;
+import org.apache.catalina.Globals;
 import org.apache.catalina.InstanceEvent;
 import org.apache.catalina.security.SecurityUtil;
 import org.apache.catalina.util.InstanceSupport;
@@ -54,6 +55,19 @@ import org.apache.catalina.util.StringManager;
 
 final class ApplicationFilterChain implements FilterChain, CometFilterChain {
 
+    // Used to enforce requirements of SRV.8.2 / SRV.14.2.5.1
+    private final static ThreadLocal lastServicedRequest;
+    private final static ThreadLocal lastServicedResponse;
+
+    static {
+        if (Globals.STRICT_SERVLET_COMPLIANCE) {
+            lastServicedRequest = new ThreadLocal();
+            lastServicedResponse = new ThreadLocal();
+        } else {
+            lastServicedRequest = null;
+            lastServicedResponse = null;
+        }
+    }
 
     // -------------------------------------------------------------- Constants
 
@@ -250,6 +264,11 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain {
 
         // We fell off the end of the chain -- call the servlet instance
         try {
+            if (Globals.STRICT_SERVLET_COMPLIANCE) {
+                lastServicedRequest.set(request);
+                lastServicedResponse.set(response);
+            }
+
             support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
                                       servlet, request, response);
             if ((request instanceof HttpServletRequest) &&
@@ -293,6 +312,11 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain {
                                       servlet, request, response, e);
             throw new ServletException
               (sm.getString("filterChain.servlet"), e);
+        } finally {
+            if (Globals.STRICT_SERVLET_COMPLIANCE) {
+                lastServicedRequest.set(null);
+                lastServicedResponse.set(null);
+            }
         }
 
     }
@@ -340,6 +364,29 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain {
         }
     }
 
+    
+    /**
+     * The last request passed to a servlet for servicing from the current
+     * thread.
+     * 
+     * @return The last request to be serviced. 
+     */
+    public static ServletRequest getLastServicedRequest() {
+        return (ServletRequest) lastServicedRequest.get();
+    }
+
+    
+    /**
+     * The last response passed to a servlet for servicing from the current
+     * thread.
+     * 
+     * @return The last response to be serviced. 
+     */
+    public static ServletResponse getLastServicedResponse() {
+        return (ServletResponse) lastServicedResponse.get();
+    }
+    
+    
     private void internalDoFilterEvent(CometEvent event)
         throws IOException, ServletException {
 
index 4c81b9d..28ce705 100644 (file)
@@ -10,6 +10,8 @@ applicationDispatcher.forward.throw=Forwarded resource threw an exception
 applicationDispatcher.include.throw=Included resource threw an exception
 applicationDispatcher.isUnavailable=Servlet {0} is currently unavailable
 applicationDispatcher.serviceException=Servlet.service() for servlet {0} threw exception
+applicationDispatcher.specViolation.request=Original SevletRequest or wrapped original ServletRequest not passed to RequestDispatcher in violation of SRV.8.2 and SRV.14.2.5.1
+applicationDispatcher.specViolation.response=Original SevletResponse or wrapped original ServletResponse not passed to RequestDispatcher in violation of SRV.8.2 and SRV.14.2.5.1
 applicationRequest.badParent=Cannot locate parent Request implementation
 applicationRequest.badRequest=Request is not a javax.servlet.ServletRequestWrapper
 applicationResponse.badParent=Cannot locate parent Response implementation