You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by xu...@apache.org on 2011/07/11 08:29:23 UTC

svn commit: r1145039 [1/2] - in /geronimo/external/trunk/tomcat-parent-7.0.18: ./ catalina/src/main/java/org/apache/catalina/connector/ catalina/src/main/java/org/apache/catalina/security/ catalina/src/main/java/org/apache/catalina/startup/ catalina/sr...

Author: xuhaihong
Date: Mon Jul 11 06:29:23 2011
New Revision: 1145039

URL: http://svn.apache.org/viewvc?rev=1145039&view=rev
Log:
Merge the changes from Tomcat trunk to rev.1144976

Added:
    geronimo/external/trunk/tomcat-parent-7.0.18/util/src/main/java/org/apache/tomcat/util/modeler/mbeans-descriptors.dtd   (with props)
Removed:
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/startup/ClusterRuleSetFactory.java
Modified:
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/connector/CoyoteAdapter.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/security/SecurityClassLoad.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/startup/Catalina.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/valves/AccessLogValve.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProcessor.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProtocol.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProcessor.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProtocol.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpNioProcessor.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpNioProtocol.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpProcessor.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpProtocol.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/AbstractHttp11Processor.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/Http11AprProcessor.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/Http11AprProtocol.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/Http11NioProcessor.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/Http11NioProtocol.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/Http11Processor.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/Http11Protocol.java
    geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/tomcat/util/net/AbstractEndpoint.java
    geronimo/external/trunk/tomcat-parent-7.0.18/pom.xml

Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/connector/CoyoteAdapter.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/connector/CoyoteAdapter.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/connector/CoyoteAdapter.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/connector/CoyoteAdapter.java Mon Jul 11 06:29:23 2011
@@ -269,6 +269,7 @@ public class CoyoteAdapter implements Ad
         boolean comet = false;
         boolean success = true;
         AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext();
+        req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
         try {
             if (!request.isAsync() && !comet) {
                 // Error or timeout - need to tell listeners the request is over

Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/security/SecurityClassLoad.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/security/SecurityClassLoad.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/security/SecurityClassLoad.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/security/SecurityClassLoad.java Mon Jul 11 06:29:23 2011
@@ -239,6 +239,7 @@ public final class SecurityClassLoad {
     private static final void loadTomcatPackage(ClassLoader loader)
         throws Exception {
         final String basePackage = "org.apache.tomcat.";
+        loader.loadClass(basePackage + "util.buf.HexUtils");
         loader.loadClass(basePackage + "util.buf.StringCache");
         loader.loadClass(basePackage + "util.buf.StringCache$ByteEntry");
         loader.loadClass(basePackage + "util.buf.StringCache$CharEntry");

Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/startup/Catalina.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/startup/Catalina.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/startup/Catalina.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/startup/Catalina.java Mon Jul 11 06:29:23 2011
@@ -36,6 +36,7 @@ import org.apache.catalina.LifecycleExce
 import org.apache.catalina.LifecycleState;
 import org.apache.catalina.Server;
 import org.apache.catalina.core.StandardServer;
+import org.apache.catalina.ha.ClusterRuleSet;
 import org.apache.catalina.security.SecurityConfig;
 import org.apache.juli.ClassLoaderLogManager;
 import org.apache.tomcat.util.ExceptionUtils;
@@ -373,13 +374,13 @@ public class Catalina {
         digester.addRuleSet(new EngineRuleSet("Server/Service/"));
         digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
         digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
-        digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Host/Cluster/"));
+        digester.addRuleSet(new ClusterRuleSet("Server/Service/Engine/Host/Cluster/"));
         digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));
 
         // When the 'engine' is found, set the parentClassLoader.
         digester.addRule("Server/Service/Engine",
                          new SetParentClassLoaderRule(parentClassLoader));
-        digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Cluster/"));
+        digester.addRuleSet(new ClusterRuleSet("Server/Service/Engine/Cluster/"));
 
         long t2=System.currentTimeMillis();
         if (log.isDebugEnabled())

Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/valves/AccessLogValve.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/valves/AccessLogValve.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/valves/AccessLogValve.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/valves/AccessLogValve.java Mon Jul 11 06:29:23 2011
@@ -263,7 +263,7 @@ public class AccessLogValve extends Valv
         private class Cache {
 
             /* CLF log format */
-            private static final String cLFFormat = "dd/MMM/yyy:HH:mm:ss";
+            private static final String cLFFormat = "dd/MMM/yyyy:HH:mm:ss";
 
             /* Second used to retrieve CLF format in most recent invocation */
             private long previousSeconds = 0L;

Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProcessor.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProcessor.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProcessor.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProcessor.java Mon Jul 11 06:29:23 2011
@@ -16,16 +16,19 @@
  */
 package org.apache.coyote;
 
+import java.io.IOException;
 import java.util.concurrent.Executor;
 
 import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
+import org.apache.tomcat.util.net.SocketStatus;
+import org.apache.tomcat.util.net.SocketWrapper;
 
 /**
  * Provides functionality and attributes common to all supported protocols
  * (currently HTTP and AJP).
  */
-public abstract class AbstractProcessor implements ActionHook, Processor {
+public abstract class AbstractProcessor<S> implements ActionHook, Processor {
 
     protected Adapter adapter;
     protected final AsyncStateMachine asyncStateMachine;
@@ -100,4 +103,25 @@ public abstract class AbstractProcessor 
     public SocketState asyncPostProcess() {
         return asyncStateMachine.asyncPostProcess();
     }
+
+    protected abstract boolean isComet();
+
+    /**
+     * Process HTTP requests. All requests are treated as HTTP requests to start
+     * with although they may change type during processing.
+     */
+    public abstract SocketState process(SocketWrapper<S> socket)
+        throws IOException;
+
+
+    /**
+     * Process in-progress Comet requests. These will start as HTTP requests.
+     */
+    public abstract SocketState event(SocketStatus status) throws IOException;
+
+    /**
+     * Process in-progress Servlet 3.0 Async requests. These will start as HTTP
+     * requests.
+     */
+    public abstract SocketState asyncDispatch(SocketStatus status);
 }

Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProtocol.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProtocol.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProtocol.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProtocol.java Mon Jul 11 06:29:23 2011
@@ -17,6 +17,7 @@
 package org.apache.coyote;
 
 import java.net.InetAddress;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -28,9 +29,12 @@ import javax.management.MalformedObjectN
 import javax.management.ObjectName;
 
 import org.apache.juli.logging.Log;
+import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.modeler.Registry;
 import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.AbstractEndpoint.Handler;
+import org.apache.tomcat.util.net.SocketStatus;
+import org.apache.tomcat.util.net.SocketWrapper;
 import org.apache.tomcat.util.res.StringManager;
 
 public abstract class AbstractProtocol implements ProtocolHandler,
@@ -229,8 +233,7 @@ public abstract class AbstractProtocol i
             name.append('-');
         }
         name.append(endpoint.getPort());
-        String quotedName = ObjectName.quote(name.toString());
-        return quotedName.substring(1, quotedName.length()-1);
+        return ObjectName.quote(name.toString());
     }
 
     
@@ -359,7 +362,8 @@ public abstract class AbstractProtocol i
                     getHandler().getGlobal(), rgOname, null );
         }
 
-        endpoint.setName(getName());
+        String endpointName = getName();
+        endpoint.setName(endpointName.substring(1, endpointName.length()-1));
 
         try {
             endpoint.init();
@@ -456,14 +460,22 @@ public abstract class AbstractProtocol i
     
     // ------------------------------------------- Connection handler base class
     
-    protected abstract static class AbstractConnectionHandler
+    protected abstract static class AbstractConnectionHandler<S,P extends AbstractProcessor<S>>
             implements AbstractEndpoint.Handler {
 
+        protected abstract Log getLog();
+
         protected RequestGroupInfo global = new RequestGroupInfo();
         protected AtomicLong registerCount = new AtomicLong(0);
 
+        protected ConcurrentHashMap<S,P> connections =
+            new ConcurrentHashMap<S,P>();
+
+        protected RecycledProcessors<P,S> recycledProcessors =
+            new RecycledProcessors<P,S>(this);
+        
+
         protected abstract AbstractProtocol getProtocol();
-        protected abstract Log getLog();
 
 
         @Override
@@ -471,8 +483,88 @@ public abstract class AbstractProtocol i
             return global;
         }
 
+        @Override
+        public void recycle() {
+            recycledProcessors.clear();
+        }
+        
+
+        public SocketState process(SocketWrapper<S> socket,
+                SocketStatus status) {
+            P processor = connections.remove(socket.getSocket());
+
+            socket.setAsync(false);
+
+            try {
+                if (processor == null) {
+                    processor = recycledProcessors.poll();
+                }
+                if (processor == null) {
+                    processor = createProcessor();
+                }
+
+                initSsl(socket, processor);
+
+                SocketState state = SocketState.CLOSED;
+                do {
+                    if (processor.isAsync() || state == SocketState.ASYNC_END) {
+                        state = processor.asyncDispatch(status);
+                    } else if (processor.isComet()) {
+                        state = processor.event(status);
+                    } else {
+                        state = processor.process(socket);
+                    }
+    
+                    if (state != SocketState.CLOSED && processor.isAsync()) {
+                        state = processor.asyncPostProcess();
+                    }
+                } while (state == SocketState.ASYNC_END);
+
+                if (state == SocketState.LONG) {
+                    // In the middle of processing a request/response. Keep the
+                    // socket associated with the processor. Exact requirements
+                    // depend on type of long poll
+                    longPoll(socket, processor);
+                } else if (state == SocketState.OPEN){
+                    // In keep-alive but between requests. OK to recycle
+                    // processor. Continue to poll for the next request.
+                    release(socket, processor, false, true);
+                } else {
+                    // Connection closed. OK to recycle the processor.
+                    release(socket, processor, true, false);
+                }
+                return state;
+            } catch(java.net.SocketException e) {
+                // SocketExceptions are normal
+                getLog().debug(sm.getString(
+                        "ajpprotocol.proto.socketexception.debug"), e);
+            } catch (java.io.IOException e) {
+                // IOExceptions are normal
+                getLog().debug(sm.getString(
+                        "ajpprotocol.proto.ioexception.debug"), e);
+            }
+            // Future developers: if you discover any other
+            // rare-but-nonfatal exceptions, catch them here, and log as
+            // above.
+            catch (Throwable e) {
+                ExceptionUtils.handleThrowable(e);
+                // any other exception or error is odd. Here we log it
+                // with "ERROR" level, so it will show up even on
+                // less-than-verbose logs.
+                getLog().error(sm.getString("ajpprotocol.proto.error"), e);
+            }
+            release(socket, processor, true, false);
+            return SocketState.CLOSED;
+        }
+        
+        protected abstract P createProcessor();
+        protected abstract void initSsl(SocketWrapper<S> socket, P processor);
+        protected abstract void longPoll(SocketWrapper<S> socket, P processor);
+        protected abstract void release(SocketWrapper<S> socket, P processor,
+                boolean socketClosing, boolean addToPoller);
+
 
-        protected void register(AbstractProcessor processor) {
+        protected void register(AbstractProcessor<S> processor) {
             if (getProtocol().getDomain() != null) {
                 synchronized (this) {
                     try {
@@ -499,7 +591,7 @@ public abstract class AbstractProtocol i
             }
         }
 
-        protected void unregister(AbstractProcessor processor) {
+        protected void unregister(AbstractProcessor<S> processor) {
             if (getProtocol().getDomain() != null) {
                 synchronized (this) {
                     try {
@@ -521,14 +613,14 @@ public abstract class AbstractProtocol i
         }
     }
     
-    protected static class RecycledProcessors<P extends AbstractProcessor>
+    protected static class RecycledProcessors<P extends AbstractProcessor<S>, S>
             extends ConcurrentLinkedQueue<P> {
 
         private static final long serialVersionUID = 1L;
-        private AbstractConnectionHandler handler;
+        private transient AbstractConnectionHandler<S,P> handler;
         protected AtomicInteger size = new AtomicInteger(0);
 
-        public RecycledProcessors(AbstractConnectionHandler handler) {
+        public RecycledProcessors(AbstractConnectionHandler<S,P> handler) {
             this.handler = handler;
         }
 

Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProcessor.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProcessor.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProcessor.java Mon Jul 11 06:29:23 2011
@@ -14,7 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package org.apache.coyote.ajp;
 
 import java.io.ByteArrayInputStream;
@@ -48,7 +47,7 @@ import org.apache.tomcat.util.res.String
 /**
  * Base class for AJP Processor implementations.
  */
-public abstract class AbstractAjpProcessor extends AbstractProcessor {
+public abstract class AbstractAjpProcessor<S> extends AbstractProcessor<S> {
 
     protected abstract Log getLog();
 
@@ -70,7 +69,7 @@ public abstract class AbstractAjpProcess
      * Flush message array.
      */
     protected static final byte[] flushMessageArray;
-    
+
 
     /**
      * Pong message array.
@@ -88,7 +87,7 @@ public abstract class AbstractAjpProcess
         endMessageArray = new byte[endMessage.getLen()];
         System.arraycopy(endMessage.getBuffer(), 0, endMessageArray, 0,
                 endMessage.getLen());
-        
+
         // Allocate the flush message array
         AjpMessage flushMessage = new AjpMessage(16);
         flushMessage.reset();
@@ -99,7 +98,7 @@ public abstract class AbstractAjpProcess
         flushMessageArray = new byte[flushMessage.getLen()];
         System.arraycopy(flushMessage.getBuffer(), 0, flushMessageArray, 0,
                 flushMessage.getLen());
-        
+
         // Allocate the pong message array
         AjpMessage pongMessage = new AjpMessage(16);
         pongMessage.reset();
@@ -110,7 +109,7 @@ public abstract class AbstractAjpProcess
                 0, pongMessage.getLen());
     }
 
-    
+
     // ----------------------------------------------------- Instance Variables
 
 
@@ -146,7 +145,7 @@ public abstract class AbstractAjpProcess
      */
     protected AjpMessage bodyMessage = null;
 
-    
+
     /**
      * Body message.
      */
@@ -205,28 +204,28 @@ public abstract class AbstractAjpProcess
      * Finished response.
      */
     protected boolean finished = false;
-    
-    
+
+
     /**
      * Bytes written to client for the current request
      */
     protected long byteCount = 0;
-    
-    
+
+
     // ------------------------------------------------------------ Constructor
-    
+
     public AbstractAjpProcessor(int packetSize, AbstractEndpoint endpoint) {
-        
+
         super(endpoint);
 
         this.packetSize = packetSize;
 
         request.setInputBuffer(new SocketInputBuffer());
-        
+
         requestHeaderMessage = new AjpMessage(packetSize);
         responseHeaderMessage = new AjpMessage(packetSize);
         bodyMessage = new AjpMessage(packetSize);
-        
+
         // Set the getBody message buffer
         AjpMessage getBodyMessage = new AjpMessage(16);
         getBodyMessage.reset();
@@ -237,10 +236,10 @@ public abstract class AbstractAjpProcess
         getBodyMessage.end();
         getBodyMessageArray = new byte[getBodyMessage.getLen()];
         System.arraycopy(getBodyMessage.getBuffer(), 0, getBodyMessageArray, 
-                         0, getBodyMessage.getLen());
+                0, getBodyMessage.getLen());
     }
 
-    
+
     // ------------------------------------------------------------- Properties
 
 
@@ -289,651 +288,670 @@ public abstract class AbstractAjpProcess
     // --------------------------------------------------------- Public Methods
 
 
-   /**
-    * Send an action to the connector.
-    *
-    * @param actionCode Type of the action
-    * @param param Action parameter
-    */
-   @Override
-   public final void action(ActionCode actionCode, Object param) {
-       
-       if (actionCode == ActionCode.COMMIT) {
-
-           if (response.isCommitted())
-               return;
-
-           // Validate and write response headers
-           try {
-               prepareResponse();
-           } catch (IOException e) {
-               // Set error flag
-               error = true;
-           }
-
-           try {
-               flush(false);
-           } catch (IOException e) {
-               // Set error flag
-               error = true;
-           }
-
-       } else if (actionCode == ActionCode.CLIENT_FLUSH) {
-
-           if (!response.isCommitted()) {
-               // Validate and write response headers
-               try {
-                   prepareResponse();
-               } catch (IOException e) {
-                   // Set error flag
-                   error = true;
-                   return;
-               }
-           }
-
-           try {
-               flush(true);
-           } catch (IOException e) {
-               // Set error flag
-               error = true;
-           }
-
-       } else if (actionCode == ActionCode.DISABLE_SWALLOW_INPUT) {
-           // TODO: Do not swallow request input but
-           // make sure we are closing the connection
-           error = true;
-
-       } else if (actionCode == ActionCode.CLOSE) {
-           // Close
-           // End the processing of the current request, and stop any further
-           // transactions with the client
-
-           try {
-               finish();
-           } catch (IOException e) {
-               // Set error flag
-               error = true;
-           }
-
-       } else if (actionCode == ActionCode.REQ_SSL_ATTRIBUTE ) {
-
-           if (!certificates.isNull()) {
-               ByteChunk certData = certificates.getByteChunk();
-               X509Certificate jsseCerts[] = null;
-               ByteArrayInputStream bais =
-                   new ByteArrayInputStream(certData.getBytes(),
-                           certData.getStart(),
-                           certData.getLength());
-               // Fill the  elements.
-               try {
-                   CertificateFactory cf;
-                   if (clientCertProvider == null) {
-                       cf = CertificateFactory.getInstance("X.509");
-                   } else {
-                       cf = CertificateFactory.getInstance("X.509",
-                               clientCertProvider);
-                   }
-                   while(bais.available() > 0) {
-                       X509Certificate cert = (X509Certificate)
-                           cf.generateCertificate(bais);
-                       if(jsseCerts == null) {
-                           jsseCerts = new X509Certificate[1];
-                           jsseCerts[0] = cert;
-                       } else {
-                           X509Certificate [] temp = new X509Certificate[jsseCerts.length+1];
-                           System.arraycopy(jsseCerts,0,temp,0,jsseCerts.length);
-                           temp[jsseCerts.length] = cert;
-                           jsseCerts = temp;
-                       }
-                   }
-               } catch (java.security.cert.CertificateException e) {
-                   getLog().error(sm.getString("ajpprocessor.certs.fail"), e);
-                   return;
-               } catch (NoSuchProviderException e) {
-                   getLog().error(sm.getString("ajpprocessor.certs.fail"), e);
-                   return;
-               }
-               request.setAttribute(SSLSupport.CERTIFICATE_KEY, jsseCerts);
-           }
-
-       } else if (actionCode == ActionCode.REQ_HOST_ATTRIBUTE) {
-
-           // Get remote host name using a DNS resolution
-           if (request.remoteHost().isNull()) {
-               try {
-                   request.remoteHost().setString(InetAddress.getByName
-                           (request.remoteAddr().toString()).getHostName());
-               } catch (IOException iex) {
-                   // Ignore
-               }
-           }
-
-       } else if (actionCode == ActionCode.REQ_LOCAL_ADDR_ATTRIBUTE) {
-
-           // Copy from local name for now, which should simply be an address
-           request.localAddr().setString(request.localName().toString());
-
-       } else if (actionCode == ActionCode.REQ_SET_BODY_REPLAY) {
-
-           // Set the given bytes as the content
-           ByteChunk bc = (ByteChunk) param;
-           int length = bc.getLength();
-           bodyBytes.setBytes(bc.getBytes(), bc.getStart(), length);
-           request.setContentLength(length);
-           first = false;
-           empty = false;
-           replay = true;
-
-       } else if (actionCode == ActionCode.ASYNC_START) {
-           asyncStateMachine.asyncStart((AsyncContextCallback) param);
-       } else if (actionCode == ActionCode.ASYNC_DISPATCHED) {
-           asyncStateMachine.asyncDispatched();
-       } else if (actionCode == ActionCode.ASYNC_TIMEOUT) {
-           AtomicBoolean result = (AtomicBoolean) param;
-           result.set(asyncStateMachine.asyncTimeout());
-       } else if (actionCode == ActionCode.ASYNC_RUN) {
-           asyncStateMachine.asyncRun((Runnable) param);
-       } else if (actionCode == ActionCode.ASYNC_ERROR) {
-           asyncStateMachine.asyncError();
-       } else if (actionCode == ActionCode.ASYNC_IS_STARTED) {
-           ((AtomicBoolean) param).set(asyncStateMachine.isAsyncStarted());
-       } else if (actionCode == ActionCode.ASYNC_IS_DISPATCHING) {
-           ((AtomicBoolean) param).set(asyncStateMachine.isAsyncDispatching());
-       } else if (actionCode == ActionCode.ASYNC_IS_ASYNC) {
-           ((AtomicBoolean) param).set(asyncStateMachine.isAsync());
-       } else if (actionCode == ActionCode.ASYNC_IS_TIMINGOUT) {
-           ((AtomicBoolean) param).set(asyncStateMachine.isAsyncTimingOut());
-       }  else {
-           actionInternal(actionCode, param);
-       }
-   }
-   
-   // Methods called by action()
-   protected abstract void actionInternal(ActionCode actionCode, Object param);
-   protected abstract void flush(boolean tbd) throws IOException;
-   protected abstract void finish() throws IOException;
-   
-   
-   public SocketState asyncDispatch(SocketStatus status) {
-
-       RequestInfo rp = request.getRequestProcessor();
-       try {
-           rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
-           error = !adapter.asyncDispatch(request, response, status);
-       } catch (InterruptedIOException e) {
-           error = true;
-       } catch (Throwable t) {
-           ExceptionUtils.handleThrowable(t);
-           getLog().error(sm.getString("http11processor.request.process"), t);
-           error = true;
-       } finally {
-           if (error) {
-               // 500 - Internal Server Error
-               response.setStatus(500);
-               adapter.log(request, response, 0);
-           }
-       }
-
-       rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
-
-       if (error) {
-           response.setStatus(500);
-       }
-       if (isAsync()) {
-           if (error) {
-               request.updateCounters();
-               return SocketState.CLOSED;
-           } else {
-               return SocketState.LONG;
-           }
-       } else {
-           request.updateCounters();
-           if (error) {
-               return SocketState.CLOSED;
-           } else {
-               return SocketState.OPEN;
-           }
-       }
-   }
-
-   
-   public void recycle() {
-       asyncStateMachine.recycle();
-
-       // Recycle Request object
-       first = true;
-       endOfStream = false;
-       empty = true;
-       replay = false;
-       finished = false;
-       request.recycle();
-       response.recycle();
-       certificates.recycle();
-       byteCount = 0;
-   }
-   
-   // ------------------------------------------------------ Protected Methods
-
-
-   /**
-    * After reading the request headers, we have to setup the request filters.
-    */
-   protected void prepareRequest() {
-
-       // Translate the HTTP method code to a String.
-       byte methodCode = requestHeaderMessage.getByte();
-       if (methodCode != Constants.SC_M_JK_STORED) {
-           String methodName = Constants.getMethodForCode(methodCode - 1);
-           request.method().setString(methodName);
-       }
-
-       requestHeaderMessage.getBytes(request.protocol());
-       requestHeaderMessage.getBytes(request.requestURI());
-
-       requestHeaderMessage.getBytes(request.remoteAddr());
-       requestHeaderMessage.getBytes(request.remoteHost());
-       requestHeaderMessage.getBytes(request.localName());
-       request.setLocalPort(requestHeaderMessage.getInt());
-
-       boolean isSSL = requestHeaderMessage.getByte() != 0;
-       if (isSSL) {
-           request.scheme().setString("https");
-       }
-
-       // Decode headers
-       MimeHeaders headers = request.getMimeHeaders();
-
-       int hCount = requestHeaderMessage.getInt();
-       for(int i = 0 ; i < hCount ; i++) {
-           String hName = null;
-
-           // Header names are encoded as either an integer code starting
-           // with 0xA0, or as a normal string (in which case the first
-           // two bytes are the length).
-           int isc = requestHeaderMessage.peekInt();
-           int hId = isc & 0xFF;
-
-           MessageBytes vMB = null;
-           isc &= 0xFF00;
-           if(0xA000 == isc) {
-               requestHeaderMessage.getInt(); // To advance the read position
-               hName = Constants.getHeaderForCode(hId - 1);
-               vMB = headers.addValue(hName);
-           } else {
-               // reset hId -- if the header currently being read
-               // happens to be 7 or 8 bytes long, the code below
-               // will think it's the content-type header or the
-               // content-length header - SC_REQ_CONTENT_TYPE=7,
-               // SC_REQ_CONTENT_LENGTH=8 - leading to unexpected
-               // behaviour.  see bug 5861 for more information.
-               hId = -1;
-               requestHeaderMessage.getBytes(tmpMB);
-               ByteChunk bc = tmpMB.getByteChunk();
-               vMB = headers.addValue(bc.getBuffer(),
-                       bc.getStart(), bc.getLength());
-           }
-
-           requestHeaderMessage.getBytes(vMB);
-
-           if (hId == Constants.SC_REQ_CONTENT_LENGTH ||
-                   (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) {
-               // just read the content-length header, so set it
-               long cl = vMB.getLong();
-               if(cl < Integer.MAX_VALUE)
-                   request.setContentLength( (int)cl );
-           } else if (hId == Constants.SC_REQ_CONTENT_TYPE ||
-                   (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) {
-               // just read the content-type header, so set it
-               ByteChunk bchunk = vMB.getByteChunk();
-               request.contentType().setBytes(bchunk.getBytes(),
-                       bchunk.getOffset(),
-                       bchunk.getLength());
-           }
-       }
-
-       // Decode extra attributes
-       boolean secret = false;
-       byte attributeCode;
-       while ((attributeCode = requestHeaderMessage.getByte())
-               != Constants.SC_A_ARE_DONE) {
-
-           switch (attributeCode) {
-
-           case Constants.SC_A_REQ_ATTRIBUTE :
-               requestHeaderMessage.getBytes(tmpMB);
-               String n = tmpMB.toString();
-               requestHeaderMessage.getBytes(tmpMB);
-               String v = tmpMB.toString();
-               /*
-                * AJP13 misses to forward the remotePort.
-                * Allow the AJP connector to add this info via
-                * a private request attribute.
-                * We will accept the forwarded data as the remote port,
-                * and remove it from the public list of request attributes.
-                */
-               if(n.equals(Constants.SC_A_REQ_REMOTE_PORT)) {
-                   try {
-                       request.setRemotePort(Integer.parseInt(v));
-                   } catch (NumberFormatException nfe) {
-                       // Ignore invalid value
-                   }
-               } else {
-                   request.setAttribute(n, v );
-               }
-               break;
-
-           case Constants.SC_A_CONTEXT :
-               requestHeaderMessage.getBytes(tmpMB);
-               // nothing
-               break;
-
-           case Constants.SC_A_SERVLET_PATH :
-               requestHeaderMessage.getBytes(tmpMB);
-               // nothing
-               break;
-
-           case Constants.SC_A_REMOTE_USER :
-               if (tomcatAuthentication) {
-                   // ignore server
-                   requestHeaderMessage.getBytes(tmpMB);
-               } else {
-                   requestHeaderMessage.getBytes(request.getRemoteUser());
-               }
-               break;
-
-           case Constants.SC_A_AUTH_TYPE :
-               if (tomcatAuthentication) {
-                   // ignore server
-                   requestHeaderMessage.getBytes(tmpMB);
-               } else {
-                   requestHeaderMessage.getBytes(request.getAuthType());
-               }
-               break;
-
-           case Constants.SC_A_QUERY_STRING :
-               requestHeaderMessage.getBytes(request.queryString());
-               break;
-
-           case Constants.SC_A_JVM_ROUTE :
-               requestHeaderMessage.getBytes(request.instanceId());
-               break;
-
-           case Constants.SC_A_SSL_CERT :
-               request.scheme().setString("https");
-               // SSL certificate extraction is lazy, moved to JkCoyoteHandler
-               requestHeaderMessage.getBytes(certificates);
-               break;
-
-           case Constants.SC_A_SSL_CIPHER :
-               request.scheme().setString("https");
-               requestHeaderMessage.getBytes(tmpMB);
-               request.setAttribute(SSLSupport.CIPHER_SUITE_KEY,
-                                    tmpMB.toString());
-               break;
-
-           case Constants.SC_A_SSL_SESSION :
-               request.scheme().setString("https");
-               requestHeaderMessage.getBytes(tmpMB);
-               request.setAttribute(SSLSupport.SESSION_ID_KEY,
-                                    tmpMB.toString());
-               break;
-
-           case Constants.SC_A_SSL_KEY_SIZE :
-               request.setAttribute(SSLSupport.KEY_SIZE_KEY,
-                       Integer.valueOf(requestHeaderMessage.getInt()));
-               break;
-
-           case Constants.SC_A_STORED_METHOD:
-               requestHeaderMessage.getBytes(request.method());
-               break;
-
-           case Constants.SC_A_SECRET:
-               requestHeaderMessage.getBytes(tmpMB);
-               if (requiredSecret != null) {
-                   secret = true;
-                   if (!tmpMB.equals(requiredSecret)) {
-                       response.setStatus(403);
-                       adapter.log(request, response, 0);
-                       error = true;
-                   }
-               }
-               break;
-
-           default:
-               // Ignore unknown attribute for backward compatibility
-               break;
-
-           }
-
-       }
-
-       // Check if secret was submitted if required
-       if ((requiredSecret != null) && !secret) {
-           response.setStatus(403);
-           adapter.log(request, response, 0);
-           error = true;
-       }
-
-       // Check for a full URI (including protocol://host:port/)
-       ByteChunk uriBC = request.requestURI().getByteChunk();
-       if (uriBC.startsWithIgnoreCase("http", 0)) {
-
-           int pos = uriBC.indexOf("://", 0, 3, 4);
-           int uriBCStart = uriBC.getStart();
-           int slashPos = -1;
-           if (pos != -1) {
-               byte[] uriB = uriBC.getBytes();
-               slashPos = uriBC.indexOf('/', pos + 3);
-               if (slashPos == -1) {
-                   slashPos = uriBC.getLength();
-                   // Set URI as "/"
-                   request.requestURI().setBytes
-                       (uriB, uriBCStart + pos + 1, 1);
-               } else {
-                   request.requestURI().setBytes
-                       (uriB, uriBCStart + slashPos,
-                        uriBC.getLength() - slashPos);
-               }
-               MessageBytes hostMB = headers.setValue("host");
-               hostMB.setBytes(uriB, uriBCStart + pos + 3,
-                               slashPos - pos - 3);
-           }
-
-       }
-
-       MessageBytes valueMB = request.getMimeHeaders().getValue("host");
-       parseHost(valueMB);
-
-   }
-   
-   
-   /**
-    * Parse host.
-    */
-   protected void parseHost(MessageBytes valueMB) {
-
-       if (valueMB == null || valueMB.isNull()) {
-           // HTTP/1.0
-           request.setServerPort(request.getLocalPort());
-           try {
-               request.serverName().duplicate(request.localName());
-           } catch (IOException e) {
-               response.setStatus(400);
-               adapter.log(request, response, 0);
-               error = true;
-           }
-           return;
-       }
-
-       ByteChunk valueBC = valueMB.getByteChunk();
-       byte[] valueB = valueBC.getBytes();
-       int valueL = valueBC.getLength();
-       int valueS = valueBC.getStart();
-       int colonPos = -1;
-       if (hostNameC.length < valueL) {
-           hostNameC = new char[valueL];
-       }
-
-       boolean ipv6 = (valueB[valueS] == '[');
-       boolean bracketClosed = false;
-       for (int i = 0; i < valueL; i++) {
-           char b = (char) valueB[i + valueS];
-           hostNameC[i] = b;
-           if (b == ']') {
-               bracketClosed = true;
-           } else if (b == ':') {
-               if (!ipv6 || bracketClosed) {
-                   colonPos = i;
-                   break;
-               }
-           }
-       }
-
-       if (colonPos < 0) {
-           if (request.scheme().equalsIgnoreCase("https")) {
-               // 443 - Default HTTPS port
-               request.setServerPort(443);
-           } else {
-               // 80 - Default HTTTP port
-               request.setServerPort(80);
-           }
-           request.serverName().setChars(hostNameC, 0, valueL);
-       } else {
-
-           request.serverName().setChars(hostNameC, 0, colonPos);
-
-           int port = 0;
-           int mult = 1;
-           for (int i = valueL - 1; i > colonPos; i--) {
-               int charValue = HexUtils.getDec(valueB[i + valueS]);
-               if (charValue == -1) {
-                   // Invalid character
-                   error = true;
-                   // 400 - Bad request
-                   response.setStatus(400);
-                   adapter.log(request, response, 0);
-                   break;
-               }
-               port = port + (charValue * mult);
-               mult = 10 * mult;
-           }
-           request.setServerPort(port);
-       }
-   }
-   
-   
-   /**
-    * When committing the response, we have to validate the set of headers, as
-    * well as setup the response filters.
-    */
-   protected void prepareResponse()
-       throws IOException {
-
-       response.setCommitted(true);
-
-       responseHeaderMessage.reset();
-       responseHeaderMessage.appendByte(Constants.JK_AJP13_SEND_HEADERS);
-
-       // HTTP header contents
-       responseHeaderMessage.appendInt(response.getStatus());
-       String message = null;
-       if (org.apache.coyote.Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER &&
-               HttpMessages.isSafeInHttpHeader(response.getMessage())) {
-           message = response.getMessage();
-       }
-       if (message == null){
-           message = HttpMessages.getMessage(response.getStatus());
-       }
-       if (message == null) {
-           // mod_jk + httpd 2.x fails with a null status message - bug 45026
-           message = Integer.toString(response.getStatus());
-       }
-       tmpMB.setString(message);
-       responseHeaderMessage.appendBytes(tmpMB);
-
-       // Special headers
-       MimeHeaders headers = response.getMimeHeaders();
-       String contentType = response.getContentType();
-       if (contentType != null) {
-           headers.setValue("Content-Type").setString(contentType);
-       }
-       String contentLanguage = response.getContentLanguage();
-       if (contentLanguage != null) {
-           headers.setValue("Content-Language").setString(contentLanguage);
-       }
-       long contentLength = response.getContentLengthLong();
-       if (contentLength >= 0) {
-           headers.setValue("Content-Length").setLong(contentLength);
-       }
-
-       // Other headers
-       int numHeaders = headers.size();
-       responseHeaderMessage.appendInt(numHeaders);
-       for (int i = 0; i < numHeaders; i++) {
-           MessageBytes hN = headers.getName(i);
-           int hC = Constants.getResponseAjpIndex(hN.toString());
-           if (hC > 0) {
-               responseHeaderMessage.appendInt(hC);
-           }
-           else {
-               responseHeaderMessage.appendBytes(hN);
-           }
-           MessageBytes hV=headers.getValue(i);
-           responseHeaderMessage.appendBytes(hV);
-       }
-
-       // Write to buffer
-       responseHeaderMessage.end();
-       output(responseHeaderMessage.getBuffer(), 0,
-               responseHeaderMessage.getLen());
-   }
-   
-   // Methods called by prepareResponse()
-   protected abstract void output(byte[] src, int offset, int length)
-           throws IOException;
-   
-   
-   // ------------------------------------- InputStreamInputBuffer Inner Class
-
-
-   /**
-    * This class is an input buffer which will read its data from an input
-    * stream.
-    */
-   protected class SocketInputBuffer
-       implements InputBuffer {
-
-
-       /**
-        * Read bytes into the specified chunk.
-        */
-       @Override
-       public int doRead(ByteChunk chunk, Request req )
-           throws IOException {
-
-           if (endOfStream) {
-               return -1;
-           }
-           if (first && req.getContentLengthLong() > 0) {
-               // Handle special first-body-chunk
-               if (!receive()) {
-                   return 0;
-               }
-           } else if (empty) {
-               if (!refillReadBuffer()) {
-                   return -1;
-               }
-           }
-           ByteChunk bc = bodyBytes.getByteChunk();
-           chunk.setBytes(bc.getBuffer(), bc.getStart(), bc.getLength());
-           empty = true;
-           return chunk.getLength();
-
-       }
-
-   }
-   
-   // Methods used by SocketInputBuffer
-   protected abstract boolean receive() throws IOException;
-   protected abstract boolean refillReadBuffer() throws IOException;
+    /**
+     * Send an action to the connector.
+     *
+     * @param actionCode Type of the action
+     * @param param Action parameter
+     */
+    @Override
+    public final void action(ActionCode actionCode, Object param) {
+
+        if (actionCode == ActionCode.COMMIT) {
+
+            if (response.isCommitted())
+                return;
+
+            // Validate and write response headers
+            try {
+                prepareResponse();
+            } catch (IOException e) {
+                // Set error flag
+                error = true;
+            }
+
+            try {
+                flush(false);
+            } catch (IOException e) {
+                // Set error flag
+                error = true;
+            }
+
+        } else if (actionCode == ActionCode.CLIENT_FLUSH) {
+
+            if (!response.isCommitted()) {
+                // Validate and write response headers
+                try {
+                    prepareResponse();
+                } catch (IOException e) {
+                    // Set error flag
+                    error = true;
+                    return;
+                }
+            }
+
+            try {
+                flush(true);
+            } catch (IOException e) {
+                // Set error flag
+                error = true;
+            }
+
+        } else if (actionCode == ActionCode.DISABLE_SWALLOW_INPUT) {
+            // TODO: Do not swallow request input but
+            // make sure we are closing the connection
+            error = true;
+
+        } else if (actionCode == ActionCode.CLOSE) {
+            // Close
+            // End the processing of the current request, and stop any further
+            // transactions with the client
+
+            try {
+                finish();
+            } catch (IOException e) {
+                // Set error flag
+                error = true;
+            }
+
+        } else if (actionCode == ActionCode.REQ_SSL_ATTRIBUTE ) {
+
+            if (!certificates.isNull()) {
+                ByteChunk certData = certificates.getByteChunk();
+                X509Certificate jsseCerts[] = null;
+                ByteArrayInputStream bais =
+                    new ByteArrayInputStream(certData.getBytes(),
+                            certData.getStart(),
+                            certData.getLength());
+                // Fill the  elements.
+                try {
+                    CertificateFactory cf;
+                    if (clientCertProvider == null) {
+                        cf = CertificateFactory.getInstance("X.509");
+                    } else {
+                        cf = CertificateFactory.getInstance("X.509",
+                                clientCertProvider);
+                    }
+                    while(bais.available() > 0) {
+                        X509Certificate cert = (X509Certificate)
+                        cf.generateCertificate(bais);
+                        if(jsseCerts == null) {
+                            jsseCerts = new X509Certificate[1];
+                            jsseCerts[0] = cert;
+                        } else {
+                            X509Certificate [] temp = new X509Certificate[jsseCerts.length+1];
+                            System.arraycopy(jsseCerts,0,temp,0,jsseCerts.length);
+                            temp[jsseCerts.length] = cert;
+                            jsseCerts = temp;
+                        }
+                    }
+                } catch (java.security.cert.CertificateException e) {
+                    getLog().error(sm.getString("ajpprocessor.certs.fail"), e);
+                    return;
+                } catch (NoSuchProviderException e) {
+                    getLog().error(sm.getString("ajpprocessor.certs.fail"), e);
+                    return;
+                }
+                request.setAttribute(SSLSupport.CERTIFICATE_KEY, jsseCerts);
+            }
+
+        } else if (actionCode == ActionCode.REQ_HOST_ATTRIBUTE) {
+
+            // Get remote host name using a DNS resolution
+            if (request.remoteHost().isNull()) {
+                try {
+                    request.remoteHost().setString(InetAddress.getByName
+                            (request.remoteAddr().toString()).getHostName());
+                } catch (IOException iex) {
+                    // Ignore
+                }
+            }
+
+        } else if (actionCode == ActionCode.REQ_LOCAL_ADDR_ATTRIBUTE) {
+
+            // Copy from local name for now, which should simply be an address
+            request.localAddr().setString(request.localName().toString());
+
+        } else if (actionCode == ActionCode.REQ_SET_BODY_REPLAY) {
+
+            // Set the given bytes as the content
+            ByteChunk bc = (ByteChunk) param;
+            int length = bc.getLength();
+            bodyBytes.setBytes(bc.getBytes(), bc.getStart(), length);
+            request.setContentLength(length);
+            first = false;
+            empty = false;
+            replay = true;
+
+        } else if (actionCode == ActionCode.ASYNC_START) {
+            asyncStateMachine.asyncStart((AsyncContextCallback) param);
+        } else if (actionCode == ActionCode.ASYNC_DISPATCHED) {
+            asyncStateMachine.asyncDispatched();
+        } else if (actionCode == ActionCode.ASYNC_TIMEOUT) {
+            AtomicBoolean result = (AtomicBoolean) param;
+            result.set(asyncStateMachine.asyncTimeout());
+        } else if (actionCode == ActionCode.ASYNC_RUN) {
+            asyncStateMachine.asyncRun((Runnable) param);
+        } else if (actionCode == ActionCode.ASYNC_ERROR) {
+            asyncStateMachine.asyncError();
+        } else if (actionCode == ActionCode.ASYNC_IS_STARTED) {
+            ((AtomicBoolean) param).set(asyncStateMachine.isAsyncStarted());
+        } else if (actionCode == ActionCode.ASYNC_IS_DISPATCHING) {
+            ((AtomicBoolean) param).set(asyncStateMachine.isAsyncDispatching());
+        } else if (actionCode == ActionCode.ASYNC_IS_ASYNC) {
+            ((AtomicBoolean) param).set(asyncStateMachine.isAsync());
+        } else if (actionCode == ActionCode.ASYNC_IS_TIMINGOUT) {
+            ((AtomicBoolean) param).set(asyncStateMachine.isAsyncTimingOut());
+        }  else {
+            actionInternal(actionCode, param);
+        }
+    }
+
+    // Methods called by action()
+    protected abstract void actionInternal(ActionCode actionCode, Object param);
+    protected abstract void flush(boolean tbd) throws IOException;
+    protected abstract void finish() throws IOException;
+
+
+    @Override
+    public SocketState asyncDispatch(SocketStatus status) {
+
+        RequestInfo rp = request.getRequestProcessor();
+        try {
+            rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
+            error = !adapter.asyncDispatch(request, response, status);
+        } catch (InterruptedIOException e) {
+            error = true;
+        } catch (Throwable t) {
+            ExceptionUtils.handleThrowable(t);
+            getLog().error(sm.getString("http11processor.request.process"), t);
+            error = true;
+        } finally {
+            if (error) {
+                // 500 - Internal Server Error
+                response.setStatus(500);
+                adapter.log(request, response, 0);
+            }
+        }
+
+        rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
+
+        if (isAsync()) {
+            if (error) {
+                request.updateCounters();
+                return SocketState.CLOSED;
+            } else {
+                return SocketState.LONG;
+            }
+        } else {
+            request.updateCounters();
+            if (error) {
+                return SocketState.CLOSED;
+            } else {
+                return SocketState.OPEN;
+            }
+        }
+    }
+
+
+    @Override
+    protected final boolean isComet() {
+        // AJP does not support Comet
+        return false;
+    }
+
+    @Override
+    public SocketState event(SocketStatus status) throws IOException {
+        // Should never reach this code but in case we do...
+        throw new IOException(
+                sm.getString("ajpprocessor.comet.notsupported"));
+    }
+
+    /**
+     * Recycle the processor, ready for the next request which may be on the
+     * same connection or a different connection.
+     * 
+     * @param socketClosing Indicates if the socket is about to be closed
+     *                      allowing the processor to perform any additional
+     *                      clean-up that may be required
+     */
+    public void recycle(boolean socketClosing) {
+        asyncStateMachine.recycle();
+
+        // Recycle Request object
+        first = true;
+        endOfStream = false;
+        empty = true;
+        replay = false;
+        finished = false;
+        request.recycle();
+        response.recycle();
+        certificates.recycle();
+        byteCount = 0;
+    }
+
+    // ------------------------------------------------------ Protected Methods
+
+
+    /**
+     * After reading the request headers, we have to setup the request filters.
+     */
+    protected void prepareRequest() {
+
+        // Translate the HTTP method code to a String.
+        byte methodCode = requestHeaderMessage.getByte();
+        if (methodCode != Constants.SC_M_JK_STORED) {
+            String methodName = Constants.getMethodForCode(methodCode - 1);
+            request.method().setString(methodName);
+        }
+
+        requestHeaderMessage.getBytes(request.protocol());
+        requestHeaderMessage.getBytes(request.requestURI());
+
+        requestHeaderMessage.getBytes(request.remoteAddr());
+        requestHeaderMessage.getBytes(request.remoteHost());
+        requestHeaderMessage.getBytes(request.localName());
+        request.setLocalPort(requestHeaderMessage.getInt());
+
+        boolean isSSL = requestHeaderMessage.getByte() != 0;
+        if (isSSL) {
+            request.scheme().setString("https");
+        }
+
+        // Decode headers
+        MimeHeaders headers = request.getMimeHeaders();
+
+        int hCount = requestHeaderMessage.getInt();
+        for(int i = 0 ; i < hCount ; i++) {
+            String hName = null;
+
+            // Header names are encoded as either an integer code starting
+            // with 0xA0, or as a normal string (in which case the first
+            // two bytes are the length).
+            int isc = requestHeaderMessage.peekInt();
+            int hId = isc & 0xFF;
+
+            MessageBytes vMB = null;
+            isc &= 0xFF00;
+            if(0xA000 == isc) {
+                requestHeaderMessage.getInt(); // To advance the read position
+                hName = Constants.getHeaderForCode(hId - 1);
+                vMB = headers.addValue(hName);
+            } else {
+                // reset hId -- if the header currently being read
+                // happens to be 7 or 8 bytes long, the code below
+                // will think it's the content-type header or the
+                // content-length header - SC_REQ_CONTENT_TYPE=7,
+                // SC_REQ_CONTENT_LENGTH=8 - leading to unexpected
+                // behaviour.  see bug 5861 for more information.
+                hId = -1;
+                requestHeaderMessage.getBytes(tmpMB);
+                ByteChunk bc = tmpMB.getByteChunk();
+                vMB = headers.addValue(bc.getBuffer(),
+                        bc.getStart(), bc.getLength());
+            }
+
+            requestHeaderMessage.getBytes(vMB);
+
+            if (hId == Constants.SC_REQ_CONTENT_LENGTH ||
+                    (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) {
+                // just read the content-length header, so set it
+                long cl = vMB.getLong();
+                if(cl < Integer.MAX_VALUE)
+                    request.setContentLength( (int)cl );
+            } else if (hId == Constants.SC_REQ_CONTENT_TYPE ||
+                    (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) {
+                // just read the content-type header, so set it
+                ByteChunk bchunk = vMB.getByteChunk();
+                request.contentType().setBytes(bchunk.getBytes(),
+                        bchunk.getOffset(),
+                        bchunk.getLength());
+            }
+        }
+
+        // Decode extra attributes
+        boolean secret = false;
+        byte attributeCode;
+        while ((attributeCode = requestHeaderMessage.getByte())
+                != Constants.SC_A_ARE_DONE) {
+
+            switch (attributeCode) {
+
+            case Constants.SC_A_REQ_ATTRIBUTE :
+                requestHeaderMessage.getBytes(tmpMB);
+                String n = tmpMB.toString();
+                requestHeaderMessage.getBytes(tmpMB);
+                String v = tmpMB.toString();
+                /*
+                 * AJP13 misses to forward the remotePort.
+                 * Allow the AJP connector to add this info via
+                 * a private request attribute.
+                 * We will accept the forwarded data as the remote port,
+                 * and remove it from the public list of request attributes.
+                 */
+                if(n.equals(Constants.SC_A_REQ_REMOTE_PORT)) {
+                    try {
+                        request.setRemotePort(Integer.parseInt(v));
+                    } catch (NumberFormatException nfe) {
+                        // Ignore invalid value
+                    }
+                } else {
+                    request.setAttribute(n, v );
+                }
+                break;
+
+            case Constants.SC_A_CONTEXT :
+                requestHeaderMessage.getBytes(tmpMB);
+                // nothing
+                break;
+
+            case Constants.SC_A_SERVLET_PATH :
+                requestHeaderMessage.getBytes(tmpMB);
+                // nothing
+                break;
+
+            case Constants.SC_A_REMOTE_USER :
+                if (tomcatAuthentication) {
+                    // ignore server
+                    requestHeaderMessage.getBytes(tmpMB);
+                } else {
+                    requestHeaderMessage.getBytes(request.getRemoteUser());
+                }
+                break;
+
+            case Constants.SC_A_AUTH_TYPE :
+                if (tomcatAuthentication) {
+                    // ignore server
+                    requestHeaderMessage.getBytes(tmpMB);
+                } else {
+                    requestHeaderMessage.getBytes(request.getAuthType());
+                }
+                break;
+
+            case Constants.SC_A_QUERY_STRING :
+                requestHeaderMessage.getBytes(request.queryString());
+                break;
+
+            case Constants.SC_A_JVM_ROUTE :
+                requestHeaderMessage.getBytes(request.instanceId());
+                break;
+
+            case Constants.SC_A_SSL_CERT :
+                request.scheme().setString("https");
+                // SSL certificate extraction is lazy, moved to JkCoyoteHandler
+                requestHeaderMessage.getBytes(certificates);
+                break;
+
+            case Constants.SC_A_SSL_CIPHER :
+                request.scheme().setString("https");
+                requestHeaderMessage.getBytes(tmpMB);
+                request.setAttribute(SSLSupport.CIPHER_SUITE_KEY,
+                        tmpMB.toString());
+                break;
+
+            case Constants.SC_A_SSL_SESSION :
+                request.scheme().setString("https");
+                requestHeaderMessage.getBytes(tmpMB);
+                request.setAttribute(SSLSupport.SESSION_ID_KEY,
+                        tmpMB.toString());
+                break;
+
+            case Constants.SC_A_SSL_KEY_SIZE :
+                request.setAttribute(SSLSupport.KEY_SIZE_KEY,
+                        Integer.valueOf(requestHeaderMessage.getInt()));
+                break;
+
+            case Constants.SC_A_STORED_METHOD:
+                requestHeaderMessage.getBytes(request.method());
+                break;
+
+            case Constants.SC_A_SECRET:
+                requestHeaderMessage.getBytes(tmpMB);
+                if (requiredSecret != null) {
+                    secret = true;
+                    if (!tmpMB.equals(requiredSecret)) {
+                        response.setStatus(403);
+                        adapter.log(request, response, 0);
+                        error = true;
+                    }
+                }
+                break;
+
+            default:
+                // Ignore unknown attribute for backward compatibility
+                break;
+
+            }
+
+        }
+
+        // Check if secret was submitted if required
+        if ((requiredSecret != null) && !secret) {
+            response.setStatus(403);
+            adapter.log(request, response, 0);
+            error = true;
+        }
+
+        // Check for a full URI (including protocol://host:port/)
+        ByteChunk uriBC = request.requestURI().getByteChunk();
+        if (uriBC.startsWithIgnoreCase("http", 0)) {
+
+            int pos = uriBC.indexOf("://", 0, 3, 4);
+            int uriBCStart = uriBC.getStart();
+            int slashPos = -1;
+            if (pos != -1) {
+                byte[] uriB = uriBC.getBytes();
+                slashPos = uriBC.indexOf('/', pos + 3);
+                if (slashPos == -1) {
+                    slashPos = uriBC.getLength();
+                    // Set URI as "/"
+                    request.requestURI().setBytes
+                    (uriB, uriBCStart + pos + 1, 1);
+                } else {
+                    request.requestURI().setBytes
+                    (uriB, uriBCStart + slashPos,
+                            uriBC.getLength() - slashPos);
+                }
+                MessageBytes hostMB = headers.setValue("host");
+                hostMB.setBytes(uriB, uriBCStart + pos + 3,
+                        slashPos - pos - 3);
+            }
+
+        }
+
+        MessageBytes valueMB = request.getMimeHeaders().getValue("host");
+        parseHost(valueMB);
+
+    }
+
+
+    /**
+     * Parse host.
+     */
+    protected void parseHost(MessageBytes valueMB) {
+
+        if (valueMB == null || valueMB.isNull()) {
+            // HTTP/1.0
+            request.setServerPort(request.getLocalPort());
+            try {
+                request.serverName().duplicate(request.localName());
+            } catch (IOException e) {
+                response.setStatus(400);
+                adapter.log(request, response, 0);
+                error = true;
+            }
+            return;
+        }
+
+        ByteChunk valueBC = valueMB.getByteChunk();
+        byte[] valueB = valueBC.getBytes();
+        int valueL = valueBC.getLength();
+        int valueS = valueBC.getStart();
+        int colonPos = -1;
+        if (hostNameC.length < valueL) {
+            hostNameC = new char[valueL];
+        }
+
+        boolean ipv6 = (valueB[valueS] == '[');
+        boolean bracketClosed = false;
+        for (int i = 0; i < valueL; i++) {
+            char b = (char) valueB[i + valueS];
+            hostNameC[i] = b;
+            if (b == ']') {
+                bracketClosed = true;
+            } else if (b == ':') {
+                if (!ipv6 || bracketClosed) {
+                    colonPos = i;
+                    break;
+                }
+            }
+        }
+
+        if (colonPos < 0) {
+            if (request.scheme().equalsIgnoreCase("https")) {
+                // 443 - Default HTTPS port
+                request.setServerPort(443);
+            } else {
+                // 80 - Default HTTTP port
+                request.setServerPort(80);
+            }
+            request.serverName().setChars(hostNameC, 0, valueL);
+        } else {
+
+            request.serverName().setChars(hostNameC, 0, colonPos);
+
+            int port = 0;
+            int mult = 1;
+            for (int i = valueL - 1; i > colonPos; i--) {
+                int charValue = HexUtils.getDec(valueB[i + valueS]);
+                if (charValue == -1) {
+                    // Invalid character
+                    error = true;
+                    // 400 - Bad request
+                    response.setStatus(400);
+                    adapter.log(request, response, 0);
+                    break;
+                }
+                port = port + (charValue * mult);
+                mult = 10 * mult;
+            }
+            request.setServerPort(port);
+        }
+    }
+
+
+    /**
+     * When committing the response, we have to validate the set of headers, as
+     * well as setup the response filters.
+     */
+    protected void prepareResponse()
+    throws IOException {
+
+        response.setCommitted(true);
+
+        responseHeaderMessage.reset();
+        responseHeaderMessage.appendByte(Constants.JK_AJP13_SEND_HEADERS);
+
+        // HTTP header contents
+        responseHeaderMessage.appendInt(response.getStatus());
+        String message = null;
+        if (org.apache.coyote.Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER &&
+                HttpMessages.isSafeInHttpHeader(response.getMessage())) {
+            message = response.getMessage();
+        }
+        if (message == null){
+            message = HttpMessages.getMessage(response.getStatus());
+        }
+        if (message == null) {
+            // mod_jk + httpd 2.x fails with a null status message - bug 45026
+            message = Integer.toString(response.getStatus());
+        }
+        tmpMB.setString(message);
+        responseHeaderMessage.appendBytes(tmpMB);
+
+        // Special headers
+        MimeHeaders headers = response.getMimeHeaders();
+        String contentType = response.getContentType();
+        if (contentType != null) {
+            headers.setValue("Content-Type").setString(contentType);
+        }
+        String contentLanguage = response.getContentLanguage();
+        if (contentLanguage != null) {
+            headers.setValue("Content-Language").setString(contentLanguage);
+        }
+        long contentLength = response.getContentLengthLong();
+        if (contentLength >= 0) {
+            headers.setValue("Content-Length").setLong(contentLength);
+        }
+
+        // Other headers
+        int numHeaders = headers.size();
+        responseHeaderMessage.appendInt(numHeaders);
+        for (int i = 0; i < numHeaders; i++) {
+            MessageBytes hN = headers.getName(i);
+            int hC = Constants.getResponseAjpIndex(hN.toString());
+            if (hC > 0) {
+                responseHeaderMessage.appendInt(hC);
+            }
+            else {
+                responseHeaderMessage.appendBytes(hN);
+            }
+            MessageBytes hV=headers.getValue(i);
+            responseHeaderMessage.appendBytes(hV);
+        }
+
+        // Write to buffer
+        responseHeaderMessage.end();
+        output(responseHeaderMessage.getBuffer(), 0,
+                responseHeaderMessage.getLen());
+    }
+
+    // Methods called by prepareResponse()
+    protected abstract void output(byte[] src, int offset, int length)
+    throws IOException;
+
+
+    // ------------------------------------- InputStreamInputBuffer Inner Class
+
+
+    /**
+     * This class is an input buffer which will read its data from an input
+     * stream.
+     */
+    protected class SocketInputBuffer
+    implements InputBuffer {
+
+
+        /**
+         * Read bytes into the specified chunk.
+         */
+        @Override
+        public int doRead(ByteChunk chunk, Request req )
+        throws IOException {
+
+            if (endOfStream) {
+                return -1;
+            }
+            if (first && req.getContentLengthLong() > 0) {
+                // Handle special first-body-chunk
+                if (!receive()) {
+                    return 0;
+                }
+            } else if (empty) {
+                if (!refillReadBuffer()) {
+                    return -1;
+                }
+            }
+            ByteChunk bc = bodyBytes.getByteChunk();
+            chunk.setBytes(bc.getBuffer(), bc.getStart(), bc.getLength());
+            empty = true;
+            return chunk.getLength();
+
+        }
+
+    }
+
+    // Methods used by SocketInputBuffer
+    protected abstract boolean receive() throws IOException;
+    protected abstract boolean refillReadBuffer() throws IOException;
 }

Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProtocol.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProtocol.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProtocol.java Mon Jul 11 06:29:23 2011
@@ -17,6 +17,7 @@
 package org.apache.coyote.ajp;
 
 import org.apache.coyote.AbstractProtocol;
+import org.apache.tomcat.util.net.SocketWrapper;
 import org.apache.tomcat.util.res.StringManager;
 
 public abstract class AbstractAjpProtocol extends AbstractProtocol {
@@ -70,4 +71,20 @@ public abstract class AbstractAjpProtoco
             this.packetSize = packetSize;
         }
     }
+    
+    protected abstract static class AbstractAjpConnectionHandler<S,P extends AbstractAjpProcessor<S>>
+            extends AbstractConnectionHandler<S, P> {
+
+        @Override
+        protected void initSsl(SocketWrapper<S> socket, P processor) {
+            // NOOP for AJP
+        }
+
+        @Override
+        protected void longPoll(SocketWrapper<S> socket, P processor) {
+            // Same requirements for all AJP connectors
+            connections.put(socket.getSocket(), processor);
+            socket.setAsync(true);
+        }
+    }
 }

Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProcessor.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProcessor.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProcessor.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProcessor.java Mon Jul 11 06:29:23 2011
@@ -14,7 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package org.apache.coyote.ajp;
 
 import java.io.IOException;
@@ -31,8 +30,6 @@ import org.apache.tomcat.jni.Socket;
 import org.apache.tomcat.jni.Status;
 import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.HexUtils;
-import org.apache.tomcat.util.http.HttpMessages;
 import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
 import org.apache.tomcat.util.net.AprEndpoint;
 import org.apache.tomcat.util.net.SocketStatus;
@@ -50,7 +47,7 @@ import org.apache.tomcat.util.net.Socket
  * @author Costin Manolache
  * @author Bill Barker
  */
-public class AjpAprProcessor extends AbstractAjpProcessor {
+public class AjpAprProcessor extends AbstractAjpProcessor<Long> {
 
 
     /**
@@ -76,13 +73,6 @@ public class AjpAprProcessor extends Abs
         inputBuffer = ByteBuffer.allocateDirect(packetSize * 2);
         inputBuffer.limit(0);
         outputBuffer = ByteBuffer.allocateDirect(packetSize * 2);
-
-        // Cause loading of HexUtils
-        HexUtils.load();
-
-        // Cause loading of HttpMessages
-        HttpMessages.getMessage(200);
-
     }
 
 
@@ -116,6 +106,7 @@ public class AjpAprProcessor extends Abs
      *
      * @throws IOException error during an I/O operation
      */
+    @Override
     public SocketState process(SocketWrapper<Long> socket)
         throws IOException {
         RequestInfo rp = request.getRequestProcessor();
@@ -229,7 +220,7 @@ public class AjpAprProcessor extends Abs
             request.updateCounters();
 
             rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
-            recycle();
+            recycle(false);
         }
 
         rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
@@ -497,8 +488,8 @@ public class AjpAprProcessor extends Abs
      * Recycle the processor.
      */
     @Override
-    public void recycle() {
-        super.recycle();
+    public void recycle(boolean socketClosing) {
+        super.recycle(socketClosing);
 
         inputBuffer.clear();
         inputBuffer.limit(0);

Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProtocol.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProtocol.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProtocol.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProtocol.java Mon Jul 11 06:29:23 2011
@@ -14,19 +14,14 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package org.apache.coyote.ajp;
 
-import java.util.concurrent.ConcurrentHashMap;
-
 import org.apache.coyote.AbstractProtocol;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.AprEndpoint;
 import org.apache.tomcat.util.net.AprEndpoint.Handler;
-import org.apache.tomcat.util.net.SocketStatus;
 import org.apache.tomcat.util.net.SocketWrapper;
 
 
@@ -100,16 +95,11 @@ public class AjpAprProtocol extends Abst
 
 
     protected static class AjpConnectionHandler
-            extends AbstractConnectionHandler implements Handler {
+            extends AbstractAjpConnectionHandler<Long,AjpAprProcessor>
+            implements Handler {
 
         protected AjpAprProtocol proto;
 
-        protected ConcurrentHashMap<SocketWrapper<Long>, AjpAprProcessor> connections =
-            new ConcurrentHashMap<SocketWrapper<Long>, AjpAprProcessor>();
-
-        protected RecycledProcessors<AjpAprProcessor> recycledProcessors =
-            new RecycledProcessors<AjpAprProcessor>(this);
-
         public AjpConnectionHandler(AjpAprProtocol proto) {
             this.proto = proto;
         }
@@ -124,81 +114,24 @@ public class AjpAprProtocol extends Abst
             return log;
         }
 
+        /**
+         * Expected to be used by the handler once the processor is no longer
+         * required.
+         */
         @Override
-        public void recycle() {
-            recycledProcessors.clear();
-        }
-        
-        @Override
-        public SocketState process(SocketWrapper<Long> socket,
-                SocketStatus status) {
-            AjpAprProcessor processor = connections.remove(socket);
-
-            socket.setAsync(false);
-
-            try {
-                if (processor == null) {
-                    processor = recycledProcessors.poll();
-                }
-                if (processor == null) {
-                    processor = createProcessor();
-                }
-
-                SocketState state = SocketState.CLOSED;
-                do {
-                    if (processor.isAsync() || state == SocketState.ASYNC_END) {
-                        state = processor.asyncDispatch(status);
-                    } else {
-                        state = processor.process(socket);
-                    }
-
-                    if (state != SocketState.CLOSED && processor.isAsync()) {
-                        state = processor.asyncPostProcess();
-                    }
-                } while (state == SocketState.ASYNC_END);
-                
-                if (state == SocketState.LONG) {
-                    // Need to make socket available for next processing cycle
-                    // but no need for the poller
-                    connections.put(socket, processor);
-                    socket.setAsync(true);
-                } else if (state == SocketState.OPEN){
-                    // In keep-alive but between requests. OK to recycle
-                    // processor. Continue to poll for the next request.
-                    processor.recycle();
-                    recycledProcessors.offer(processor);
-                    ((AprEndpoint)proto.endpoint).getPoller().add(
-                            socket.getSocket().longValue());
-                } else {
-                    processor.recycle();
-                    recycledProcessors.offer(processor);
-                }
-                return state;
-
-            } catch(java.net.SocketException e) {
-                // SocketExceptions are normal
-                log.debug(sm.getString(
-                        "ajpprotocol.proto.socketexception.debug"), e);
-            } catch (java.io.IOException e) {
-                // IOExceptions are normal
-                log.debug(sm.getString(
-                        "ajpprotocol.proto.ioexception.debug"), e);
-            }
-            // Future developers: if you discover any other
-            // rare-but-nonfatal exceptions, catch them here, and log as
-            // above.
-            catch (Throwable e) {
-                ExceptionUtils.handleThrowable(e);
-                // any other exception or error is odd. Here we log it
-                // with "ERROR" level, so it will show up even on
-                // less-than-verbose logs.
-                log.error(sm.getString("ajpprotocol.proto.error"), e);
-            }
-            processor.recycle();
+        public void release(SocketWrapper<Long> socket,
+                AjpAprProcessor processor, boolean isSocketClosing,
+                boolean addToPoller) {
+            processor.recycle(isSocketClosing);
             recycledProcessors.offer(processor);
-            return SocketState.CLOSED;
+            if (addToPoller) {
+                ((AprEndpoint)proto.endpoint).getPoller().add(
+                        socket.getSocket().longValue());
+            }
         }
 
+
+        @Override
         protected AjpAprProcessor createProcessor() {
             AjpAprProcessor processor = new AjpAprProcessor(proto.packetSize, (AprEndpoint)proto.endpoint);
             processor.setAdapter(proto.adapter);

Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpNioProcessor.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpNioProcessor.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpNioProcessor.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpNioProcessor.java Mon Jul 11 06:29:23 2011
@@ -14,7 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package org.apache.coyote.ajp;
 
 import java.io.EOFException;
@@ -31,8 +30,6 @@ import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.HexUtils;
-import org.apache.tomcat.util.http.HttpMessages;
 import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
 import org.apache.tomcat.util.net.NioChannel;
 import org.apache.tomcat.util.net.NioEndpoint;
@@ -45,7 +42,7 @@ import org.apache.tomcat.util.net.Socket
 /**
  * Processes AJP requests using NIO.
  */
-public class AjpNioProcessor extends AbstractAjpProcessor {
+public class AjpNioProcessor extends AbstractAjpProcessor<NioChannel> {
 
 
     /**
@@ -67,13 +64,6 @@ public class AjpNioProcessor extends Abs
         response.setOutputBuffer(new SocketOutputBuffer());
 
         pool = endpoint.getSelectorPool();
-
-        // Cause loading of HexUtils
-        HexUtils.load();
-
-        // Cause loading of HttpMessages
-        HttpMessages.getMessage(200);
-
     }
 
 
@@ -101,6 +91,7 @@ public class AjpNioProcessor extends Abs
      *
      * @throws IOException error during an I/O operation
      */
+    @Override
     public SocketState process(SocketWrapper<NioChannel> socket)
         throws IOException {
         RequestInfo rp = request.getRequestProcessor();
@@ -137,14 +128,14 @@ public class AjpNioProcessor extends Abs
                     } catch (IOException e) {
                         error = true;
                     }
-                    recycle();
+                    recycle(true);
                     continue;
                 } else if(type != Constants.JK_AJP13_FORWARD_REQUEST) {
                     // Usually the servlet didn't read the previous request body
                     if(log.isDebugEnabled()) {
                         log.debug("Unexpected message: "+type);
                     }
-                    recycle();
+                    recycle(false);
                     continue;
                 }
                 request.setStartTime(System.currentTimeMillis());
@@ -226,7 +217,7 @@ public class AjpNioProcessor extends Abs
                 socket.setTimeout(keepAliveTimeout);
             }
 
-            recycle();
+            recycle(true);
         }
         
         rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);