Add async-supported impl for Servlets
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Mon, 7 Dec 2009 14:17:14 +0000 (14:17 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Mon, 7 Dec 2009 14:17:14 +0000 (14:17 +0000)
git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@887928 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/Wrapper.java
java/org/apache/catalina/core/ApplicationFilterChain.java
java/org/apache/catalina/core/StandardWrapper.java
java/org/apache/catalina/deploy/ServletDef.java
java/org/apache/catalina/startup/WebRuleSet.java
java/org/apache/catalina/startup/WebXml.java

index bd68437..fbefbd3 100644 (file)
@@ -347,5 +347,17 @@ public interface Wrapper extends Container {
      * Set the multi-part configuration for the associated servlet. To clear the
      * multi-part configuration specify <code>null</code> as the new value.
      */
-    public void setMultipartConfigElement(MultipartConfigElement multipartConfig);
+    public void setMultipartConfigElement(
+            MultipartConfigElement multipartConfig);
+    
+    /**
+     * Does the associated Servlet support async processing? Defaults to
+     * <code>true</code>
+     */
+    public boolean isAsyncSupported();
+    
+    /**
+     * Set the async support for the associated servlet.
+     */
+    public void setAsyncSupported(boolean asyncSupport);
 }
index 0082aad..64df629 100644 (file)
@@ -28,8 +28,10 @@ import javax.servlet.FilterChain;
 import javax.servlet.Servlet;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
+import javax.servlet.ServletRequestWrapper;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.catalina.Globals;
@@ -273,11 +275,25 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain {
 
             support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
                                       servlet, request, response);
-            if ((request instanceof HttpServletRequest) &&
+            ServletRequest wRequest; 
+            if (request.isAsyncSupported()
+                    && !support.getWrapper().isAsyncSupported()) {
+                if (request instanceof HttpServletRequest) {
+                    wRequest = new HttpServletRequestNoAsyc(
+                            (HttpServletRequest) request);
+                } else {
+                    // Must be a ServletRequest
+                    wRequest = new ServletRequestNoAsyc(request);
+                }
+            } else {
+                wRequest = request;
+            }
+            // Use potentially wrapped request from this point
+            if ((wRequest instanceof HttpServletRequest) &&
                 (response instanceof HttpServletResponse)) {
                     
                 if( Globals.IS_SECURITY_ENABLED ) {
-                    final ServletRequest req = request;
+                    final ServletRequest req = wRequest;
                     final ServletResponse res = response;
                     Principal principal = 
                         ((HttpServletRequest) req).getUserPrincipal();
@@ -289,11 +305,12 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain {
                                                principal);   
                     args = null;
                 } else {  
-                    servlet.service(request, response);
+                    servlet.service(wRequest, response);
                 }
             } else {
-                servlet.service(request, response);
+                servlet.service(wRequest, response);
             }
+            // Stop using wrapped request now Servlet has been processed
             support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
                                       servlet, request, response);
         } catch (IOException e) {
@@ -581,4 +598,30 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain {
     }
 
 
+    // --------------------------------- Wrapper classes for isAsyncSupported()
+    
+    private class HttpServletRequestNoAsyc extends HttpServletRequestWrapper {
+
+        public HttpServletRequestNoAsyc(HttpServletRequest request) {
+            super(request);
+        }
+        
+        @Override
+        public boolean isAsyncSupported() {
+            return false;
+        }
+    }
+
+    private class ServletRequestNoAsyc extends ServletRequestWrapper {
+
+        public ServletRequestNoAsyc(ServletRequest request) {
+            super(request);
+        }
+        
+        @Override
+        public boolean isAsyncSupported() {
+            return false;
+        }
+    }
+
 }
index 90435d6..5b88434 100644 (file)
@@ -260,6 +260,11 @@ public class StandardWrapper
      * Multipart config
      */
     protected MultipartConfigElement multipartConfigElement = null;
+    
+    /**
+     * Async support
+     */
+    protected boolean asyncSupported = true;
 
     /**
      * Static class array used when the SecurityManager is turned on and 
@@ -1502,6 +1507,15 @@ public class StandardWrapper
         this.multipartConfigElement = multipartConfigElement;
     }
 
+    @Override
+    public boolean isAsyncSupported() {
+        return asyncSupported;
+    }
+    
+    public void setAsyncSupported(boolean asyncSupported) {
+        this.asyncSupported = asyncSupported;
+    }
+
     // -------------------------------------------------------- Package Methods
 
 
index 9ec90ba..72e2a4b 100644 (file)
@@ -220,4 +220,18 @@ public class ServletDef implements Serializable {
     public void setMultipartDef(MultipartDef multipartDef) {
         this.multipartDef = multipartDef;
     }
+    
+    
+    /**
+     * Does this servlet support async.
+     */
+    private String asyncSupported = null;
+    
+    public String getAsyncSupported() {
+        return this.asyncSupported;
+    }
+    
+    public void setAsyncSupported(String asyncSupported) {
+        this.asyncSupported = asyncSupported;
+    }
 }
index 78a0564..3a3a3d2 100644 (file)
@@ -383,6 +383,10 @@ public class WebRuleSet extends RuleSetBase {
         digester.addCallMethod(fullPrefix + "/servlet/multipart-config/file-size-threshold",
                                "setFileSizeThreshold", 0);
 
+        digester.addCallMethod(fullPrefix + "/servlet/async-supported",
+                "setAsyncSupported", 0);
+
+        
         digester.addRule(fullPrefix + "/servlet-mapping",
                                new CallMethodMultiRule("addServletMapping", 2, 0));
         digester.addCallParam(fullPrefix + "/servlet-mapping/servlet-name", 1);
index 82f8252..ba7a352 100644 (file)
@@ -18,7 +18,6 @@
 
 package org.apache.catalina.startup;
 
-import java.io.File;
 import java.net.URL;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -30,7 +29,6 @@ import java.util.Map;
 import java.util.Set;
 
 import javax.servlet.MultipartConfigElement;
-import javax.servlet.ServletContext;
 
 import org.apache.catalina.Context;
 import org.apache.catalina.Wrapper;
@@ -517,9 +515,6 @@ public class WebXml {
 
         // messageDestinations were ignored in Tomcat 6, so ignore here
         
-        // TODO SERVLET3 - This needs to be more fine-grained. Whether or not to
-        //                 process annotations on destroy() will depend on where
-        //                 the filter/servlet was loaded from. Joy.
         context.setIgnoreAnnotations(metadataComplete);
         for (String extension : mimeMappings.keySet()) {
             context.addMimeMapping(extension, mimeMappings.get(extension));
@@ -582,6 +577,10 @@ public class WebXml {
                             multipartdef.getLocation()));
                 }
             }
+            if (servlet.getAsyncSupported() != null) {
+                wrapper.setAsyncSupported(
+                        Boolean.parseBoolean(servlet.getAsyncSupported()));
+            }
             context.addChild(wrapper);
         }
         for (String pattern : servletMappings.keySet()) {
@@ -1050,6 +1049,15 @@ public class WebXml {
                     dest.getMultipartDef(), failOnConflict);
         }
         
+        if (dest.getAsyncSupported() == null) {
+            dest.setAsyncSupported(src.getAsyncSupported());
+        } else if (src.getAsyncSupported() != null) {
+            if (failOnConflict &&
+                    !src.getAsyncSupported().equals(dest.getAsyncSupported())) {
+                return false;
+            }
+        }
+        
         return true;
     }