You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2012/03/16 00:05:16 UTC

svn commit: r1301262 - in /tomcat/tc7.0.x/trunk: ./ java/org/apache/catalina/connector/ java/org/apache/catalina/websocket/ java/org/apache/coyote/ java/org/apache/coyote/ajp/ java/org/apache/coyote/http11/ java/org/apache/coyote/http11/upgrade/ java/o...

Author: markt
Date: Thu Mar 15 23:05:15 2012
New Revision: 1301262

URL: http://svn.apache.org/viewvc?rev=1301262&view=rev
Log:
Next stage of WebSocket impl along with some clean-up for MutableInteger required for the WebSocket patch to apply cleanly.
Includes code written by Johno Crawford.

Added:
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/
      - copied from r1241822, tomcat/trunk/java/org/apache/coyote/http11/upgrade/
Removed:
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/UpgradeInbound.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/UpgradeInputStream.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/UpgradeOutbound.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/UpgradeOutputStream.java
Modified:
    tomcat/tc7.0.x/trunk/   (props changed)
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/RequestFacade.java
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/StreamInbound.java
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WebSocketServlet.java
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WsInputStream.java
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WsOutbound.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProcessor.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/Processor.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpAprProtocol.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpNioProtocol.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpProtocol.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/LocalStrings.properties
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Protocol.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/InternalNioOutputBuffer.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeNioProcessor.java
    tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/MutableInteger.java
    tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
    tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java
    tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioBlockingSelector.java
    tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java
    tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioSelectorPool.java
    tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Mar 15 23:05:15 2012
@@ -1 +1 @@
-/tomcat/trunk:1156115-1157160,1157162-1157859,1157862-1157942,1157945-1160347,1160349-1163716,1163718-1166689,1166691-1174340,1174342-1175596,1175598-1175611,1175613-1175932,1175934-1177783,1177785-1177980,1178006-1180720,1180722-1183094,1183096-1187753,1187755,1187775,1187801,1187806,1187809,1187826-1188312,1188314-1188401,1188646-1188840,1188842-1190176,1190178-1195223,1195225-1195953,1195955,1195957-1201238,1201240-1203345,1203347-1206623,1206625-1208046,1208073,1208096,1208114,1208145,1208772,1209194-1212125,1212127-1220291,1220293,1220295-1221321,1221323-1222328,1222332-1222401,1222405-1222795,1222850-1222950,1222969-1225326,1225328-1225463,1225465,1225627,1225629-1226534,1226536-1228908,1228911-1228923,1228927-1229532,1229534-1230766,1230768-1231625,1231627-1233414,1233419-1235207,1235209-1237425,1237427,1237429-1237977,1237981,1237985,1238070,1238073,1239024-1239048,1239050-1239062,1239135,1239256,1239258-1239485,1239785-1240046,1240101,1240106,1240109,1240112,1240114
 ,1240116,1240118,1240121,1240329,1240697,1240795,1240821,1240842,1240857,1241087,1241160,1241908-1241909,1241982,1242099,1242110,1242371,1242434,1242495,1242947,1243034,1243038,1244302,1244511,1244567,1244718-1244719,1244935-1244938,1245274,1245449,1245849,1290875,1292334,1292338,1292345-1292347,1293155,1293831-1293832,1295998,1296284,1297014-1297015,1297017,1297158,1297177,1297202,1297209,1297213,1297717,1297722,1297729,1297768,1297778,1297818,1297828,1297979,1297987,1298121,1298140,1298590,1298592,1298628-1298629,1298794,1298983-1298984,1299020,1299034,1299819,1300154-1300155,1300569,1300948
+/tomcat/trunk:1156115-1157160,1157162-1157859,1157862-1157942,1157945-1160347,1160349-1163716,1163718-1166689,1166691-1174340,1174342-1175596,1175598-1175611,1175613-1175932,1175934-1177783,1177785-1177980,1178006-1180720,1180722-1183094,1183096-1187753,1187755,1187775,1187801,1187806,1187809,1187826-1188312,1188314-1188401,1188646-1188840,1188842-1190176,1190178-1195223,1195225-1195953,1195955,1195957-1201238,1201240-1203345,1203347-1206623,1206625-1208046,1208073,1208096,1208114,1208145,1208772,1209194-1212125,1212127-1220291,1220293,1220295-1221321,1221323-1222328,1222332-1222401,1222405-1222795,1222850-1222950,1222969-1225326,1225328-1225463,1225465,1225627,1225629-1226534,1226536-1228908,1228911-1228923,1228927-1229532,1229534-1230766,1230768-1231625,1231627-1233414,1233419-1235207,1235209-1237425,1237427,1237429-1237977,1237981,1237985,1237995,1238070,1238073,1239024-1239048,1239050-1239062,1239135,1239256,1239258-1239485,1239785-1240046,1240101,1240106,1240109,1240112
 ,1240114,1240116,1240118,1240121,1240329,1240474-1240850,1240857,1241087,1241160,1241408-1241822,1241908-1241909,1241982,1242099,1242110,1242371,1242434,1242495,1242947,1243034,1243038,1244302,1244511,1244567,1244718-1244719,1244935-1244938,1245274,1245449,1245849,1290875,1292334,1292338,1292345-1292347,1293155,1293831-1293832,1295998,1296284,1297014-1297015,1297017,1297158,1297177,1297202,1297209,1297213,1297717,1297722,1297729,1297768,1297778,1297818,1297828,1297979,1297987,1298121,1298140,1298590,1298592,1298628-1298629,1298794,1298983-1298984,1299020,1299034,1299819,1300154-1300155,1300569,1300948

Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java Thu Mar 15 23:05:15 2012
@@ -74,7 +74,7 @@ import org.apache.catalina.realm.Generic
 import org.apache.catalina.util.ParameterMap;
 import org.apache.catalina.util.StringParser;
 import org.apache.coyote.ActionCode;
-import org.apache.coyote.http11.UpgradeInbound;
+import org.apache.coyote.http11.upgrade.UpgradeInbound;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.ExceptionUtils;

Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/RequestFacade.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/RequestFacade.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/RequestFacade.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/RequestFacade.java Thu Mar 15 23:05:15 2012
@@ -41,7 +41,7 @@ import javax.servlet.http.Part;
 
 import org.apache.catalina.Globals;
 import org.apache.catalina.security.SecurityUtil;
-import org.apache.coyote.http11.UpgradeInbound;
+import org.apache.coyote.http11.upgrade.UpgradeInbound;
 import org.apache.tomcat.util.res.StringManager;
 
 /**

Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/StreamInbound.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/StreamInbound.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/StreamInbound.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/StreamInbound.java Thu Mar 15 23:05:15 2012
@@ -22,8 +22,9 @@ import java.io.InputStreamReader;
 import java.io.Reader;
 
 import org.apache.catalina.util.Conversions;
-import org.apache.coyote.http11.UpgradeInbound;
-import org.apache.coyote.http11.UpgradeOutbound;
+import org.apache.coyote.http11.upgrade.UpgradeInbound;
+import org.apache.coyote.http11.upgrade.UpgradeOutbound;
+import org.apache.coyote.http11.upgrade.UpgradeProcessor;
 import org.apache.tomcat.util.buf.B2CConverter;
 import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
 
@@ -41,7 +42,7 @@ public abstract class StreamInbound impl
     // frames
     // TODO
 
-    private InputStream is = null;
+    private UpgradeProcessor<?> processor = null;
     private WsOutbound outbound;
 
     @Override
@@ -51,8 +52,8 @@ public abstract class StreamInbound impl
 
 
     @Override
-    public void setInputStream(InputStream is) {
-        this.is = is;
+    public void setUpgradeProcessor(UpgradeProcessor<?> processor) {
+        this.processor = processor;
     }
 
     public WsOutbound getStreamOutbound() {
@@ -64,7 +65,7 @@ public abstract class StreamInbound impl
         // Must be start the start of a frame
 
         // Read the first byte
-        int i = is.read();
+        int i = processor.read();
 
         fin = (i & 0x80) > 0;
 
@@ -80,7 +81,7 @@ public abstract class StreamInbound impl
         validateOpCode(opCode);
 
         // Read the next byte
-        i = is.read();
+        i = processor.read();
 
         // Client data must be masked and this isn't
         if ((i & 0x80) == 0) {
@@ -91,19 +92,20 @@ public abstract class StreamInbound impl
         payloadLength = i & 0x7F;
         if (payloadLength == 126) {
             byte[] extended = new byte[2];
-            is.read(extended);
+            processor.read(extended);
             payloadLength = Conversions.byteArrayToLong(extended);
         } else if (payloadLength == 127) {
             byte[] extended = new byte[8];
-            is.read(extended);
+            processor.read(extended);
             payloadLength = Conversions.byteArrayToLong(extended);
         }
 
         byte[] mask = new byte[4];
-        is.read(mask);
+        processor.read(mask);
 
         if (opCode == 1 || opCode == 2) {
-            WsInputStream wsIs = new WsInputStream(is, mask, payloadLength);
+            WsInputStream wsIs = new WsInputStream(processor, mask,
+                    payloadLength);
             if (opCode == 2) {
                 onBinaryData(wsIs);
             } else {
@@ -123,7 +125,7 @@ public abstract class StreamInbound impl
         // TODO: Handle control frames appearing in the middle of a multi-frame
         //       message
 
-        return SocketState.UPGRADE;
+        return SocketState.UPGRADED;
     }
 
     protected abstract void onBinaryData(InputStream is) throws IOException;

Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WebSocketServlet.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WebSocketServlet.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WebSocketServlet.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WebSocketServlet.java Thu Mar 15 23:05:15 2012
@@ -90,8 +90,13 @@ public abstract class WebSocketServlet e
             return;
         }
 
-        // TODO Read client handshake - Origin
-        //                              Sec-WebSocket-Protocol
+        String origin = req.getHeader("Origin");
+        if (!verifyOrigin(origin)) {
+            resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+            return;
+        }
+
+        // TODO Read client handshake - Sec-WebSocket-Protocol
         //                              Sec-WebSocket-Extensions
 
         // TODO Extensions require the ability to specify something (API TBD)
@@ -143,5 +148,20 @@ public abstract class WebSocketServlet e
         }
     }
 
+    /**
+     * Intended to be overridden by sub-classes that wish to verify the origin
+     * of a WebSocket request before processing it.
+     *
+     * @param origin    The value of the origin header from the request which
+     *                  may be <code>null</code>
+     *
+     * @return  <code>true</code> to accept the request. <code>false</code> to
+     *          reject it. This default implementation always returns
+     *          <code>true</code>.
+     */
+    protected boolean verifyOrigin(String origin) {
+        return true;
+    }
+
     protected abstract StreamInbound createWebSocketInbound();
 }

Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WsInputStream.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WsInputStream.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WsInputStream.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WsInputStream.java Thu Mar 15 23:05:15 2012
@@ -17,17 +17,19 @@
 package org.apache.catalina.websocket;
 
 import java.io.IOException;
-import java.io.InputStream;
+
+import org.apache.coyote.http11.upgrade.UpgradeProcessor;
 
 public class WsInputStream extends java.io.InputStream {
 
-    private InputStream wrapped;
+    private UpgradeProcessor<?> processor;
     private byte[] mask;
     private long remaining;
     private long read;
 
-    public WsInputStream(InputStream wrapped, byte[] mask, long remaining) {
-        this.wrapped = wrapped;
+    public WsInputStream(UpgradeProcessor<?> processor, byte[] mask,
+            long remaining) {
+        this.processor = processor;
         this.mask = mask;
         this.remaining = remaining;
         this.read = 0;
@@ -42,7 +44,7 @@ public class WsInputStream extends java.
         remaining--;
         read++;
 
-        int masked = wrapped.read();
+        int masked = processor.read();
         return masked ^ mask[(int) ((read - 1) % 4)];
     }
 

Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WsOutbound.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WsOutbound.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WsOutbound.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/websocket/WsOutbound.java Thu Mar 15 23:05:15 2012
@@ -20,7 +20,7 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 
-import org.apache.coyote.http11.UpgradeOutbound;
+import org.apache.coyote.http11.upgrade.UpgradeOutbound;
 import org.apache.tomcat.util.buf.B2CConverter;
 
 public class WsOutbound {

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProcessor.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProcessor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProcessor.java Thu Mar 15 23:05:15 2012
@@ -19,6 +19,7 @@ package org.apache.coyote;
 import java.io.IOException;
 import java.util.concurrent.Executor;
 
+import org.apache.coyote.http11.upgrade.UpgradeInbound;
 import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
 import org.apache.tomcat.util.net.SocketStatus;
@@ -28,18 +29,26 @@ import org.apache.tomcat.util.net.Socket
  * Provides functionality and attributes common to all supported protocols
  * (currently HTTP and AJP).
  */
-public abstract class AbstractProcessor<S> implements ActionHook, Processor {
+public abstract class AbstractProcessor<S> implements ActionHook, Processor<S> {
 
     protected Adapter adapter;
-    protected final AsyncStateMachine asyncStateMachine;
-    protected final AbstractEndpoint endpoint;
-    protected final Request request;
-    protected final Response response;
+    protected AsyncStateMachine<S> asyncStateMachine;
+    protected AbstractEndpoint endpoint;
+    protected Request request;
+    protected Response response;
 
     
+    /**
+     * Intended for use by the Upgrade sub-classes that have no need to
+     * initialise the request, response, etc.
+     */
+    protected AbstractProcessor() {
+        // NOOP
+    }
+
     public AbstractProcessor(AbstractEndpoint endpoint) {
         this.endpoint = endpoint;
-        asyncStateMachine = new AsyncStateMachine(this);
+        asyncStateMachine = new AsyncStateMachine<S>(this);
         
         request = new Request();
 
@@ -61,6 +70,7 @@ public abstract class AbstractProcessor<
     /**
      * The request associated with this processor.
      */
+    @Override
     public Request getRequest() {
         return request;
     }
@@ -95,40 +105,51 @@ public abstract class AbstractProcessor<
     }
     
     
+    @Override
     public boolean isAsync() {
-        return asyncStateMachine.isAsync();
+        return (asyncStateMachine != null && asyncStateMachine.isAsync());
     }
 
 
+    @Override
     public SocketState asyncPostProcess() {
         return asyncStateMachine.asyncPostProcess();
     }
 
-    protected abstract boolean isComet();
+    @Override
+    public abstract boolean isComet();
 
-    protected abstract boolean isUpgrade();
+    @Override
+    public abstract boolean isUpgrade();
 
     /**
      * Process HTTP requests. All requests are treated as HTTP requests to start
      * with although they may change type during processing.
      */
+    @Override
     public abstract SocketState process(SocketWrapper<S> socket)
         throws IOException;
 
     /**
      * Process in-progress Comet requests. These will start as HTTP requests.
      */
+    @Override
     public abstract SocketState event(SocketStatus status) throws IOException;
 
     /**
      * Process in-progress Servlet 3.0 Async requests. These will start as HTTP
      * requests.
      */
+    @Override
     public abstract SocketState asyncDispatch(SocketStatus status);
 
     /**
      * Processes data received on a connection that has been through an HTTP
      * upgrade.
      */
+    @Override
     public abstract SocketState upgradeDispatch() throws IOException;
+
+    @Override
+    public abstract UpgradeInbound getUpgradeInbound();
 }

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java Thu Mar 15 23:05:15 2012
@@ -16,6 +16,7 @@
  */
 package org.apache.coyote;
 
+import java.io.IOException;
 import java.net.InetAddress;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
@@ -28,6 +29,7 @@ import javax.management.MBeanServer;
 import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 
+import org.apache.coyote.http11.upgrade.UpgradeInbound;
 import org.apache.juli.logging.Log;
 import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.modeler.Registry;
@@ -500,7 +502,7 @@ public abstract class AbstractProtocol i
     
     // ------------------------------------------- Connection handler base class
     
-    protected abstract static class AbstractConnectionHandler<S,P extends AbstractProcessor<S>>
+    protected abstract static class AbstractConnectionHandler<S,P extends Processor<S>>
             implements AbstractEndpoint.Handler {
 
         protected abstract Log getLog();
@@ -508,8 +510,8 @@ public abstract class AbstractProtocol i
         protected RequestGroupInfo global = new RequestGroupInfo();
         protected AtomicLong registerCount = new AtomicLong(0);
 
-        protected ConcurrentHashMap<S,P> connections =
-            new ConcurrentHashMap<S,P>();
+        protected ConcurrentHashMap<S,Processor<S>> connections =
+            new ConcurrentHashMap<S,Processor<S>>();
 
         protected RecycledProcessors<P,S> recycledProcessors =
             new RecycledProcessors<P,S>(this);
@@ -531,7 +533,7 @@ public abstract class AbstractProtocol i
 
         public SocketState process(SocketWrapper<S> socket,
                 SocketStatus status) {
-            P processor = connections.remove(socket.getSocket());
+            Processor<S> processor = connections.remove(socket.getSocket());
 
             socket.setAsync(false);
 
@@ -576,9 +578,18 @@ public abstract class AbstractProtocol i
                     // closed. If it works, the socket will be re-added to the
                     // poller
                     release(socket, processor, false, false);
-                } else if (state == SocketState.UPGRADE) {
+                } else if (state == SocketState.UPGRADED) {
                     // Need to keep the connection associated with the processor
-                    longPoll(socket, processor);
+                    upgradePoll(socket, processor);
+                } else if (state == SocketState.UPGRADING) {
+                    // Get the UpgradeInbound handler
+                    UpgradeInbound inbound = processor.getUpgradeInbound();
+                    // Release the Http11 processor to be re-used
+                    release(socket, processor, false, false);
+                    // Create the light-weight upgrade processor
+                    processor = createUpgradeProcessor(socket, inbound);
+                    // Need to keep the connection associated with the processor
+                    upgradePoll(socket, processor);
                 } else {
                     // Connection closed. OK to recycle the processor.
                     release(socket, processor, true, false);
@@ -608,11 +619,18 @@ public abstract class AbstractProtocol i
         }
         
         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 abstract void initSsl(SocketWrapper<S> socket,
+                Processor<S> processor);
+        protected abstract void longPoll(SocketWrapper<S> socket,
+                Processor<S> processor);
+        protected abstract void upgradePoll(SocketWrapper<S> socket,
+                Processor<S> processor);
+        protected abstract void release(SocketWrapper<S> socket,
+                Processor<S> processor, boolean socketClosing,
+                boolean addToPoller);
+        protected abstract Processor<S> createUpgradeProcessor(
+                SocketWrapper<S> socket,
+                UpgradeInbound inbound) throws IOException;
 
         protected void register(AbstractProcessor<S> processor) {
             if (getProtocol().getDomain() != null) {
@@ -641,12 +659,16 @@ public abstract class AbstractProtocol i
             }
         }
 
-        protected void unregister(AbstractProcessor<S> processor) {
+        protected void unregister(Processor<S> processor) {
             if (getProtocol().getDomain() != null) {
                 synchronized (this) {
                     try {
-                        RequestInfo rp =
-                            processor.getRequest().getRequestProcessor();
+                        Request r = processor.getRequest();
+                        if (r == null) {
+                            // Probably an UpgradeProcessor
+                            return;
+                        }
+                        RequestInfo rp = r.getRequestProcessor();
                         rp.setGlobalProcessor(null);
                         ObjectName rpName = rp.getRpName();
                         if (getLog().isDebugEnabled()) {
@@ -663,8 +685,8 @@ public abstract class AbstractProtocol i
         }
     }
     
-    protected static class RecycledProcessors<P extends AbstractProcessor<S>, S>
-            extends ConcurrentLinkedQueue<P> {
+    protected static class RecycledProcessors<P extends Processor<S>, S>
+            extends ConcurrentLinkedQueue<Processor<S>> {
 
         private static final long serialVersionUID = 1L;
         private transient AbstractConnectionHandler<S,P> handler;
@@ -675,7 +697,7 @@ public abstract class AbstractProtocol i
         }
 
         @Override
-        public boolean offer(P processor) {
+        public boolean offer(Processor<S> processor) {
             int cacheSize = handler.getProtocol().getProcessorCache();
             boolean offer = cacheSize == -1 ? true : size.get() < cacheSize;
             //avoid over growing our cache or add after we have stopped
@@ -691,8 +713,8 @@ public abstract class AbstractProtocol i
         }
     
         @Override
-        public P poll() {
-            P result = super.poll();
+        public Processor<S> poll() {
+            Processor<S> result = super.poll();
             if (result != null) {
                 size.decrementAndGet();
             }
@@ -701,7 +723,7 @@ public abstract class AbstractProtocol i
     
         @Override
         public void clear() {
-            P next = poll();
+            Processor<S> next = poll();
             while (next != null) {
                 handler.unregister(next);
                 next = poll();

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java Thu Mar 15 23:05:15 2012
@@ -84,7 +84,7 @@ import org.apache.tomcat.util.res.String
  *                                 error()
  * </pre>                               
  */
-public class AsyncStateMachine {
+public class AsyncStateMachine<S> {
 
     /**
      * The string manager for this package.
@@ -131,10 +131,10 @@ public class AsyncStateMachine {
     private volatile AsyncState state = AsyncState.DISPATCHED;
     // Need this to fire listener on complete
     private AsyncContextCallback asyncCtxt = null;
-    private Processor processor;
+    private Processor<S> processor;
     
     
-    public AsyncStateMachine(Processor processor) {
+    public AsyncStateMachine(Processor<S> processor) {
         this.processor = processor;
     }
 

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/Processor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/Processor.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/Processor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/Processor.java Thu Mar 15 23:05:15 2012
@@ -17,12 +17,39 @@
 
 package org.apache.coyote;
 
+import java.io.IOException;
 import java.util.concurrent.Executor;
 
+import org.apache.coyote.http11.upgrade.UpgradeInbound;
+import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
+import org.apache.tomcat.util.net.SSLSupport;
+import org.apache.tomcat.util.net.SocketStatus;
+import org.apache.tomcat.util.net.SocketWrapper;
+
 
 /**
  * Common interface for processors of all protocols.
  */
-public interface Processor {
+public interface Processor<S> {
     Executor getExecutor();
+
+    SocketState process(SocketWrapper<S> socketWrapper) throws IOException;
+
+    SocketState event(SocketStatus status) throws IOException;
+
+    SocketState asyncDispatch(SocketStatus status);
+    SocketState asyncPostProcess();
+
+    UpgradeInbound getUpgradeInbound();
+    SocketState upgradeDispatch() throws IOException;
+
+    boolean isComet();
+    boolean isAsync();
+    boolean isUpgrade();
+
+    Request getRequest();
+
+    void recycle(boolean socketClosing);
+
+    void setSslSupport(SSLSupport sslSupport);
 }

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java Thu Mar 15 23:05:15 2012
@@ -33,6 +33,7 @@ import org.apache.coyote.OutputBuffer;
 import org.apache.coyote.Request;
 import org.apache.coyote.RequestInfo;
 import org.apache.coyote.Response;
+import org.apache.coyote.http11.upgrade.UpgradeInbound;
 import org.apache.juli.logging.Log;
 import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.buf.ByteChunk;
@@ -507,6 +508,14 @@ public abstract class AbstractAjpProcess
 
 
     @Override
+    public void setSslSupport(SSLSupport sslSupport) {
+        // Should never reach this code but in case we do...
+        throw new IllegalStateException(
+                sm.getString("ajpprocessor.ssl.notsupported"));
+    }
+
+
+    @Override
     public SocketState event(SocketStatus status) throws IOException {
         // Should never reach this code but in case we do...
         throw new IOException(
@@ -522,6 +531,14 @@ public abstract class AbstractAjpProcess
     }
 
 
+    @Override
+    public UpgradeInbound getUpgradeInbound() {
+        // Should never reach this code but in case we do...
+        throw new IllegalStateException(
+                sm.getString("ajpprocessor.httpupgrade.notsupported"));
+    }
+
+
     /**
      * Recycle the processor, ready for the next request which may be on the
      * same connection or a different connection.
@@ -530,6 +547,7 @@ public abstract class AbstractAjpProcess
      *                      allowing the processor to perform any additional
      *                      clean-up that may be required
      */
+    @Override
     public void recycle(boolean socketClosing) {
         asyncStateMachine.recycle();
 
@@ -560,14 +578,14 @@ public abstract class AbstractAjpProcess
 
 
     @Override
-    protected final boolean isComet() {
+    public final boolean isComet() {
         // AJP does not support Comet
         return false;
     }
 
 
     @Override
-    protected final boolean isUpgrade() {
+    public final boolean isUpgrade() {
         // AJP does not support HTTP upgrade
         return false;
     }

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java Thu Mar 15 23:05:15 2012
@@ -17,6 +17,8 @@
 package org.apache.coyote.ajp;
 
 import org.apache.coyote.AbstractProtocol;
+import org.apache.coyote.Processor;
+import org.apache.coyote.http11.upgrade.UpgradeInbound;
 import org.apache.tomcat.util.net.SocketWrapper;
 import org.apache.tomcat.util.res.StringManager;
 
@@ -76,15 +78,29 @@ public abstract class AbstractAjpProtoco
             extends AbstractConnectionHandler<S, P> {
 
         @Override
-        protected void initSsl(SocketWrapper<S> socket, P processor) {
+        protected void initSsl(SocketWrapper<S> socket, Processor<S> processor) {
             // NOOP for AJP
         }
 
         @Override
-        protected void longPoll(SocketWrapper<S> socket, P processor) {
+        protected void longPoll(SocketWrapper<S> socket,
+                Processor<S> processor) {
             // Same requirements for all AJP connectors
             connections.put(socket.getSocket(), processor);
             socket.setAsync(true);
         }
+
+        @Override
+        protected void upgradePoll(SocketWrapper<S> socket,
+                Processor<S> processor) {
+            // TODO Should never happen. ISE?
+        }
+
+        @Override
+        protected P createUpgradeProcessor(SocketWrapper<S> socket,
+                UpgradeInbound inbound) {
+            // TODO should fail - throw IOE
+            return null;
+        }
     }
 }

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpAprProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpAprProtocol.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpAprProtocol.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpAprProtocol.java Thu Mar 15 23:05:15 2012
@@ -17,6 +17,7 @@
 package org.apache.coyote.ajp;
 
 import org.apache.coyote.AbstractProtocol;
+import org.apache.coyote.Processor;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.net.AbstractEndpoint;
@@ -120,7 +121,7 @@ public class AjpAprProtocol extends Abst
          */
         @Override
         public void release(SocketWrapper<Long> socket,
-                AjpAprProcessor processor, boolean isSocketClosing,
+                Processor<Long> processor, boolean isSocketClosing,
                 boolean addToPoller) {
             processor.recycle(isSocketClosing);
             recycledProcessors.offer(processor);

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java Thu Mar 15 23:05:15 2012
@@ -292,8 +292,7 @@ public class AjpNioProcessor extends Abs
             //ignore
         }
         try {
-            pool.write(writeBuffer, socket, selector, writeTimeout, true,
-                    null);
+            pool.write(writeBuffer, socket, selector, writeTimeout, true);
         }finally { 
             if ( selector != null ) pool.put(selector);
         }

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpNioProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpNioProtocol.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpNioProtocol.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpNioProtocol.java Thu Mar 15 23:05:15 2012
@@ -20,6 +20,7 @@ import java.nio.channels.SocketChannel;
 import java.util.Iterator;
 
 import org.apache.coyote.AbstractProtocol;
+import org.apache.coyote.Processor;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.net.AbstractEndpoint;
@@ -120,12 +121,12 @@ public class AjpNioProtocol extends Abst
             if (log.isDebugEnabled()) 
                 log.debug("Iterating through our connections to release a socket channel:"+socket);
             boolean released = false;
-            Iterator<java.util.Map.Entry<NioChannel, AjpNioProcessor>> it = connections.entrySet().iterator();
+            Iterator<java.util.Map.Entry<NioChannel, Processor<NioChannel>>> it = connections.entrySet().iterator();
             while (it.hasNext()) {
-                java.util.Map.Entry<NioChannel, AjpNioProcessor> entry = it.next();
+                java.util.Map.Entry<NioChannel, Processor<NioChannel>> entry = it.next();
                 if (entry.getKey().getIOChannel()==socket) {
                     it.remove();
-                    AjpNioProcessor result = entry.getValue();
+                    Processor<NioChannel> result = entry.getValue();
                     result.recycle(true);
                     unregister(result);
                     released = true;
@@ -142,7 +143,7 @@ public class AjpNioProtocol extends Abst
          */
         @Override
         public void release(SocketWrapper<NioChannel> socket) {
-            AjpNioProcessor processor = connections.remove(socket);
+            Processor<NioChannel> processor = connections.remove(socket);
             if (processor != null) {
                 processor.recycle(true);
                 recycledProcessors.offer(processor);
@@ -155,7 +156,7 @@ public class AjpNioProtocol extends Abst
          */
         @Override
         public void release(SocketWrapper<NioChannel> socket,
-                AjpNioProcessor processor, boolean isSocketClosing,
+                Processor<NioChannel> processor, boolean isSocketClosing,
                 boolean addToPoller) {
             processor.recycle(isSocketClosing);
             recycledProcessors.offer(processor);

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpProtocol.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpProtocol.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AjpProtocol.java Thu Mar 15 23:05:15 2012
@@ -19,6 +19,7 @@ package org.apache.coyote.ajp;
 import java.net.Socket;
 
 import org.apache.coyote.AbstractProtocol;
+import org.apache.coyote.Processor;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.net.AbstractEndpoint;
@@ -121,7 +122,7 @@ public class AjpProtocol extends Abstrac
          */
         @Override
         public void release(SocketWrapper<Socket> socket,
-                AjpProcessor processor, boolean isSocketClosing,
+                Processor<Socket> processor, boolean isSocketClosing,
                 boolean addToPoller) {
             processor.recycle(isSocketClosing);
             recycledProcessors.offer(processor);

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/LocalStrings.properties?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/LocalStrings.properties (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/LocalStrings.properties Thu Mar 15 23:05:15 2012
@@ -40,6 +40,7 @@ ajpprocessor.request.process=Error proce
 ajpprocessor.certs.fail=Certificate conversion failed
 ajpprocessor.socket.info=Exception getting socket information
 ajpprocessor.comet.notsupported=The Comet protocol is not supported by this connector
+ajpprocessor.ssl.notsupported=The SSL protocol is not supported by this connector
 ajpprocessor.httpupgrade.notsupported=HTTP upgrades are not supported by this connector
 
 ajpmessage.null=Cannot append null value

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java Thu Mar 15 23:05:15 2012
@@ -36,6 +36,7 @@ import org.apache.coyote.http11.filters.
 import org.apache.coyote.http11.filters.SavedRequestInputFilter;
 import org.apache.coyote.http11.filters.VoidInputFilter;
 import org.apache.coyote.http11.filters.VoidOutputFilter;
+import org.apache.coyote.http11.upgrade.UpgradeInbound;
 import org.apache.juli.logging.Log;
 import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.buf.Ascii;
@@ -60,6 +61,14 @@ public abstract class AbstractHttp11Proc
     protected static final StringManager sm =
         StringManager.getManager(Constants.Package);
 
+    /**
+     * Intended for use by the Upgrade sub-classes that have no need to
+     * initialise the request, response, etc.
+     */
+    protected AbstractHttp11Processor() {
+        // NOOP
+    }
+
     /*
      * Tracks how many internal filters are in the filter library so they
      * are skipped when looking for pluggable filters.
@@ -839,11 +848,6 @@ public abstract class AbstractHttp11Proc
             ((AtomicBoolean) param).set(asyncStateMachine.isAsyncTimingOut());
         } else if (actionCode == ActionCode.UPGRADE) {
             upgradeInbound = (UpgradeInbound) param;
-            upgradeInbound.setInputStream(
-                    new UpgradeInputStream(getInputBuffer()));
-            upgradeInbound.setUpgradeOutbound(
-                    new UpgradeOutbound(
-                            new UpgradeOutputStream(getOutputBuffer())));
             // Stop further HTTP output
             getOutputBuffer().finished = true;
         } else {
@@ -1070,8 +1074,7 @@ public abstract class AbstractHttp11Proc
         } else if (isAsync() || comet) {
             return SocketState.LONG;
         } else if (isUpgrade()) {
-            // May be data on the connection to process
-            return upgradeDispatch();
+            return SocketState.UPGRADING;
         } else {
             if (sendfileInProgress) {
                 return SocketState.SENDFILE;
@@ -1583,22 +1586,16 @@ public abstract class AbstractHttp11Proc
 
     @Override
     public SocketState upgradeDispatch() throws IOException {
-        SocketState result = upgradeInbound.onData();
-        AbstractInputBuffer<S> ib = getInputBuffer();
-        while (result == SocketState.UPGRADE) {
-            // Check to see if there is more data to process
-            if (ib.available() == 0) {
-                // Read any data that might be available
-                // Note: This will block for BIO regardless
-                ib.fill(false);
-            }
-            if (ib.available() == 0) {
-                // Still no data available, exit this loop
-                break;
-            }
-            result = upgradeInbound.onData();
-        }
-        return result;
+        // Should never reach this code but in case we do...
+        // TODO
+        throw new IOException(
+                sm.getString("TODO"));
+    }
+
+
+    @Override
+    public UpgradeInbound getUpgradeInbound() {
+        return upgradeInbound;
     }
 
 
@@ -1655,10 +1652,18 @@ public abstract class AbstractHttp11Proc
             SocketWrapper<S> socketWrapper);
 
 
-    public final void recycle() {
-        getInputBuffer().recycle();
-        getOutputBuffer().recycle();
-        asyncStateMachine.recycle();
+
+    @Override
+    public final void recycle(boolean isSocketClosing) {
+        if (getInputBuffer() != null) {
+            getInputBuffer().recycle();
+        }
+        if (getOutputBuffer() != null) {
+            getOutputBuffer().recycle();
+        }
+        if (asyncStateMachine != null) {
+            asyncStateMachine.recycle();
+        }
         upgradeInbound = null;
         remoteAddr = null;
         remoteHost = null;

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java Thu Mar 15 23:05:15 2012
@@ -57,6 +57,15 @@ public class Http11AprProcessor extends 
     // ----------------------------------------------------------- Constructors
 
 
+    /**
+     * Intended for use by the Upgrade sub-classes that have no need to
+     * initialise the request, response, etc.
+     */
+    protected Http11AprProcessor() {
+        // NOOP
+    }
+
+
     public Http11AprProcessor(int headerBufferSize, AprEndpoint endpoint,
             int maxTrailerSize) {
 
@@ -257,6 +266,11 @@ public class Http11AprProcessor extends 
     }
 
 
+    @Override
+    public void setSslSupport(SSLSupport sslSupport) {
+        // NOOP for APR
+    }
+
     // ----------------------------------------------------- ActionHook Methods
 
 

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java Thu Mar 15 23:05:15 2012
@@ -16,7 +16,12 @@
  */
 package org.apache.coyote.http11;
 
+import java.io.IOException;
+
 import org.apache.coyote.AbstractProtocol;
+import org.apache.coyote.Processor;
+import org.apache.coyote.http11.upgrade.UpgradeAprProcessor;
+import org.apache.coyote.http11.upgrade.UpgradeInbound;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.net.AbstractEndpoint;
@@ -211,9 +216,9 @@ public class Http11AprProtocol extends A
          */
         @Override
         public void release(SocketWrapper<Long> socket,
-                Http11AprProcessor processor, boolean isSocketClosing,
+                Processor<Long> processor, boolean isSocketClosing,
                 boolean addToPoller) {
-            processor.recycle();
+            processor.recycle(isSocketClosing);
             recycledProcessors.offer(processor);
             if (addToPoller && proto.endpoint.isRunning()) {
                 ((AprEndpoint)proto.endpoint).getPoller().add(
@@ -223,24 +228,32 @@ public class Http11AprProtocol extends A
 
         @Override
         protected void initSsl(SocketWrapper<Long> socket,
-                Http11AprProcessor processor) {
+                Processor<Long> processor) {
             // NOOP for APR
         }
 
         @Override
         protected void longPoll(SocketWrapper<Long> socket,
-                Http11AprProcessor processor) {
+                Processor<Long> processor) {
             connections.put(socket.getSocket(), processor);
 
             if (processor.isAsync()) {
                 socket.setAsync(true);
-            } else if (processor.comet && proto.endpoint.isRunning()) {
+            } else if (processor.isComet() && proto.endpoint.isRunning()) {
                 ((AprEndpoint) proto.endpoint).getCometPoller().add(
                         socket.getSocket().longValue(), false);
             }
         }
 
         @Override
+        protected void upgradePoll(SocketWrapper<Long> socket,
+                Processor<Long> processor) {
+            connections.put(socket.getSocket(), processor);
+            ((AprEndpoint) proto.endpoint).getPoller().add(
+                    socket.getSocket().longValue(), false);
+        }
+
+        @Override
         protected Http11AprProcessor createProcessor() {
             Http11AprProcessor processor = new Http11AprProcessor(
                     proto.getMaxHttpHeaderSize(), (AprEndpoint)proto.endpoint,
@@ -263,5 +276,12 @@ public class Http11AprProtocol extends A
             register(processor);
             return processor;
         }
+
+        @Override
+        protected Processor<Long> createUpgradeProcessor(
+                SocketWrapper<Long> socket, UpgradeInbound inbound)
+                throws IOException {
+            return new UpgradeAprProcessor(socket, inbound);
+        }
     }
 }

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Thu Mar 15 23:05:15 2012
@@ -62,6 +62,15 @@ public class Http11NioProcessor extends 
     // ----------------------------------------------------------- Constructors
 
 
+    /**
+     * Intended for use by the Upgrade sub-classes that have no need to
+     * initialise the request, response, etc.
+     */
+    protected Http11NioProcessor() {
+        // NOOP
+    }
+
+
     public Http11NioProcessor(int maxHttpHeaderSize, NioEndpoint endpoint,
             int maxTrailerSize) {
 
@@ -546,6 +555,7 @@ public class Http11NioProcessor extends 
     /**
      * Set the SSL information for this HTTP connection.
      */
+    @Override
     public void setSslSupport(SSLSupport sslSupport) {
         this.sslSupport = sslSupport;
     }

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java Thu Mar 15 23:05:15 2012
@@ -16,16 +16,22 @@
  */
 package org.apache.coyote.http11;
 
+import java.io.IOException;
+import java.nio.channels.SelectionKey;
 import java.nio.channels.SocketChannel;
 import java.util.Iterator;
 
 import org.apache.coyote.AbstractProtocol;
+import org.apache.coyote.Processor;
+import org.apache.coyote.http11.upgrade.UpgradeInbound;
+import org.apache.coyote.http11.upgrade.UpgradeNioProcessor;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.NioChannel;
 import org.apache.tomcat.util.net.NioEndpoint;
 import org.apache.tomcat.util.net.NioEndpoint.Handler;
+import org.apache.tomcat.util.net.NioEndpoint.KeyAttachment;
 import org.apache.tomcat.util.net.SSLImplementation;
 import org.apache.tomcat.util.net.SecureNioChannel;
 import org.apache.tomcat.util.net.SocketWrapper;
@@ -167,13 +173,13 @@ public class Http11NioProtocol extends A
             if (log.isDebugEnabled())
                 log.debug("Iterating through our connections to release a socket channel:"+socket);
             boolean released = false;
-            Iterator<java.util.Map.Entry<NioChannel, Http11NioProcessor>> it = connections.entrySet().iterator();
+            Iterator<java.util.Map.Entry<NioChannel, Processor<NioChannel>>> it = connections.entrySet().iterator();
             while (it.hasNext()) {
-                java.util.Map.Entry<NioChannel, Http11NioProcessor> entry = it.next();
+                java.util.Map.Entry<NioChannel, Processor<NioChannel>> entry = it.next();
                 if (entry.getKey().getIOChannel()==socket) {
                     it.remove();
-                    Http11NioProcessor result = entry.getValue();
-                    result.recycle();
+                    Processor<NioChannel> result = entry.getValue();
+                    result.recycle(true);
                     unregister(result);
                     released = true;
                     break;
@@ -189,10 +195,10 @@ public class Http11NioProtocol extends A
          */
         @Override
         public void release(SocketWrapper<NioChannel> socket) {
-            Http11NioProcessor processor =
+            Processor<NioChannel> processor =
                 connections.remove(socket.getSocket());
             if (processor != null) {
-                processor.recycle();
+                processor.recycle(true);
                 recycledProcessors.offer(processor);
             }
         }
@@ -209,9 +215,9 @@ public class Http11NioProtocol extends A
          */
         @Override
         public void release(SocketWrapper<NioChannel> socket,
-                Http11NioProcessor processor, boolean isSocketClosing,
+                Processor<NioChannel> processor, boolean isSocketClosing,
                 boolean addToPoller) {
-            processor.recycle();
+            processor.recycle(isSocketClosing);
             recycledProcessors.offer(processor);
             if (addToPoller) {
                 socket.getSocket().getPoller().add(socket.getSocket());
@@ -221,7 +227,7 @@ public class Http11NioProtocol extends A
 
         @Override
         protected void initSsl(SocketWrapper<NioChannel> socket,
-                Http11NioProcessor processor) {
+                Processor<NioChannel> processor) {
             if (proto.isSSLEnabled() &&
                     (proto.sslImplementation != null)
                     && (socket.getSocket() instanceof SecureNioChannel)) {
@@ -237,7 +243,7 @@ public class Http11NioProtocol extends A
 
         @Override
         protected void longPoll(SocketWrapper<NioChannel> socket,
-                Http11NioProcessor processor) {
+                Processor<NioChannel> processor) {
             connections.put(socket.getSocket(), processor);
 
             if (processor.isAsync()) {
@@ -273,5 +279,25 @@ public class Http11NioProtocol extends A
             register(processor);
             return processor;
         }
+
+        @Override
+        protected Processor<NioChannel> createUpgradeProcessor(
+                SocketWrapper<NioChannel> socket, UpgradeInbound inbound)
+                throws IOException {
+            return new UpgradeNioProcessor(socket, inbound,
+                    ((Http11NioProtocol) getProtocol()).getEndpoint().getSelectorPool());
+        }
+
+        @Override
+        protected void upgradePoll(SocketWrapper<NioChannel> socket,
+                Processor<NioChannel> processor) {
+            connections.put(socket.getSocket(), processor);
+
+            SelectionKey key = socket.getSocket().getIOChannel().keyFor(
+                    socket.getSocket().getPoller().getSelector());
+            key.interestOps(SelectionKey.OP_READ);
+            ((KeyAttachment) socket).interestOps(
+                    SelectionKey.OP_READ);
+        }
     }
 }

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java Thu Mar 15 23:05:15 2012
@@ -49,6 +49,15 @@ public class Http11Processor extends Abs
    // ------------------------------------------------------------ Constructor
 
 
+    /**
+     * Intended for use by the Upgrade sub-classes that have no need to
+     * initialise the request, response, etc.
+     */
+    protected Http11Processor() {
+        // NOOP
+    }
+
+
     public Http11Processor(int headerBufferSize, JIoEndpoint endpoint,
             int maxTrailerSize) {
 
@@ -103,7 +112,8 @@ public class Http11Processor extends Abs
     /**
      * Set the SSL information for this HTTP connection.
      */
-    public void setSSLSupport(SSLSupport sslSupport) {
+    @Override
+    public void setSslSupport(SSLSupport sslSupport) {
         this.sslSupport = sslSupport;
     }
 

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Protocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Protocol.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Protocol.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Protocol.java Thu Mar 15 23:05:15 2012
@@ -16,9 +16,13 @@
  */
 package org.apache.coyote.http11;
 
+import java.io.IOException;
 import java.net.Socket;
 
 import org.apache.coyote.AbstractProtocol;
+import org.apache.coyote.Processor;
+import org.apache.coyote.http11.upgrade.UpgradeBioProcessor;
+import org.apache.coyote.http11.upgrade.UpgradeInbound;
 import org.apache.juli.logging.Log;
 import org.apache.tomcat.util.net.AbstractEndpoint;
 import org.apache.tomcat.util.net.JIoEndpoint;
@@ -131,28 +135,28 @@ public class Http11Protocol extends Abst
          */
         @Override
         public void release(SocketWrapper<Socket> socket,
-                Http11Processor processor, boolean isSocketClosing,
+                Processor<Socket> processor, boolean isSocketClosing,
                 boolean addToPoller) {
-            processor.recycle();
+            processor.recycle(isSocketClosing);
             recycledProcessors.offer(processor);
         }
 
         @Override
         protected void initSsl(SocketWrapper<Socket> socket,
-                Http11Processor processor) {
+                Processor<Socket> processor) {
             if (proto.isSSLEnabled() && (proto.sslImplementation != null)) {
-                processor.setSSLSupport(
+                processor.setSslSupport(
                         proto.sslImplementation.getSSLSupport(
                                 socket.getSocket()));
             } else {
-                processor.setSSLSupport(null);
+                processor.setSslSupport(null);
             }
 
         }
 
         @Override
         protected void longPoll(SocketWrapper<Socket> socket,
-                Http11Processor processor) {
+                Processor<Socket> processor) {
             connections.put(socket.getSocket(), processor);
         }
 
@@ -180,5 +184,18 @@ public class Http11Protocol extends Abst
             register(processor);
             return processor;
         }
+
+        @Override
+        protected Processor<Socket> createUpgradeProcessor(
+                SocketWrapper<Socket> socket, UpgradeInbound inbound)
+                throws IOException {
+            return new UpgradeBioProcessor(socket, inbound);
+        }
+
+        @Override
+        protected void upgradePoll(SocketWrapper<Socket> socket,
+                Processor<Socket> processor) {
+            connections.put(socket.getSocket(), processor);
+        }
     }
 }

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/InternalNioOutputBuffer.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/InternalNioOutputBuffer.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/InternalNioOutputBuffer.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/InternalNioOutputBuffer.java Thu Mar 15 23:05:15 2012
@@ -24,7 +24,6 @@ import java.nio.channels.Selector;
 
 import org.apache.coyote.OutputBuffer;
 import org.apache.coyote.Response;
-import org.apache.tomcat.util.MutableInteger;
 import org.apache.tomcat.util.buf.ByteChunk;
 import org.apache.tomcat.util.http.HttpMessages;
 import org.apache.tomcat.util.net.AbstractEndpoint;
@@ -68,11 +67,6 @@ public class InternalNioOutputBuffer ext
 
 
     /**
-     * Number of bytes last written
-     */
-    private MutableInteger lastWrite = new MutableInteger(1);
-
-    /**
      * Underlying socket.
      */
     private NioChannel socket;
@@ -113,7 +107,6 @@ public class InternalNioOutputBuffer ext
             socket.getBufHandler().getWriteBuffer().clear();
             socket = null;
         }
-        lastWrite.set(1);
     }
 
 
@@ -167,10 +160,10 @@ public class InternalNioOutputBuffer ext
             //ignore
         }
         try {
-            written = pool.write(bytebuffer, socket, selector, writeTimeout, block,lastWrite);
+            written = pool.write(bytebuffer, socket, selector, writeTimeout, block);
             //make sure we are flushed 
             do {
-                if (socket.flush(true,selector,writeTimeout,lastWrite)) break;
+                if (socket.flush(true,selector,writeTimeout)) break;
             }while ( true );
         }finally { 
             if ( selector != null ) pool.put(selector);

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeNioProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeNioProcessor.java?rev=1301262&r1=1241822&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeNioProcessor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeNioProcessor.java Thu Mar 15 23:05:15 2012
@@ -1,179 +1,179 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package org.apache.coyote.http11.upgrade;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.nio.channels.Selector;
-
-import org.apache.tomcat.util.net.NioChannel;
-import org.apache.tomcat.util.net.NioEndpoint;
-import org.apache.tomcat.util.net.NioSelectorPool;
-import org.apache.tomcat.util.net.SocketWrapper;
-
-/**
- * Implementation note: The need to extend Http11Processor could probably be
- * removed if the Processor interface was expanded to cover all of the methods
- * required by the AbstractProtocol. That would simplify the code and further
- * reduce the size of instances of this class.
- */
-public class UpgradeNioProcessor extends UpgradeProcessor<NioChannel> {
-
-    private NioChannel nioChannel;
-    private NioSelectorPool pool;
-
-    public UpgradeNioProcessor(SocketWrapper<NioChannel> wrapper,
-            UpgradeInbound upgradeInbound, NioSelectorPool pool) {
-        super(upgradeInbound);
-
-        this.nioChannel = wrapper.getSocket();
-        this.pool = pool;
-    }
-
-
-    /*
-     * Output methods
-     */
-    @Override
-    public void flush() throws IOException {
-        NioEndpoint.KeyAttachment att =
-                (NioEndpoint.KeyAttachment) nioChannel.getAttachment(false);
-        if (att == null) {
-            throw new IOException("Key must be cancelled");
-        }
-        long writeTimeout = att.getTimeout();
-        Selector selector = null;
-        try {
-            selector = pool.get();
-        } catch ( IOException x ) {
-            //ignore
-        }
-        try {
-            do {
-                if (nioChannel.flush(true, selector, writeTimeout)) {
-                    break;
-                }
-            } while (true);
-        } finally {
-            if (selector != null) {
-                pool.put(selector);
-            }
-        }
-    }
-
-    @Override
-    public void write(int b) throws IOException {
-        writeToSocket(new byte[] {(byte) b});
-    }
-
-    /*
-     * Input methods
-     */
-    @Override
-    public int read() throws IOException {
-        byte[] bytes = new byte[1];
-        readSocket(true, bytes, 0, 1);
-        return bytes[0];
-    }
-
-    @Override
-    public int read(byte[] bytes) throws IOException {
-        return readSocket(true, bytes, 0, bytes.length);
-    }
-
-
-    /*
-     * Adapted from the NioInputBuffer.
-     */
-    private int readSocket(boolean block, byte[] bytes, int offset, int len)
-            throws IOException {
-
-        int nRead = 0;
-        nioChannel.getBufHandler().getReadBuffer().clear();
-        nioChannel.getBufHandler().getReadBuffer().limit(len);
-        if (block) {
-            Selector selector = null;
-            try {
-                selector = pool.get();
-            } catch ( IOException x ) {
-                // Ignore
-            }
-            try {
-                NioEndpoint.KeyAttachment att =
-                        (NioEndpoint.KeyAttachment) nioChannel.getAttachment(false);
-                if (att == null) {
-                    throw new IOException("Key must be cancelled.");
-                }
-                nRead = pool.read(nioChannel.getBufHandler().getReadBuffer(),
-                        nioChannel, selector, att.getTimeout());
-            } catch (EOFException eof) {
-                nRead = -1;
-            } finally {
-                if (selector != null) {
-                    pool.put(selector);
-                }
-            }
-        } else {
-            nRead = nioChannel.read(nioChannel.getBufHandler().getReadBuffer());
-        }
-        if (nRead > 0) {
-            nioChannel.getBufHandler().getReadBuffer().flip();
-            nioChannel.getBufHandler().getReadBuffer().limit(nRead);
-            nioChannel.getBufHandler().getReadBuffer().get(bytes, offset, nRead);
-            return nRead;
-        } else if (nRead == -1) {
-            //return false;
-            throw new EOFException(sm.getString("nio.eof.error"));
-        } else {
-            return 0;
-        }
-    }
-
-
-    /*
-     * Adapted from the NioOutputBuffer
-     */
-    private synchronized int writeToSocket(byte[] bytes) throws IOException {
-
-        nioChannel.getBufHandler().getWriteBuffer().clear();
-        nioChannel.getBufHandler().getWriteBuffer().put(bytes);
-        nioChannel.getBufHandler().getWriteBuffer().flip();
-
-        int written = 0;
-        NioEndpoint.KeyAttachment att =
-                (NioEndpoint.KeyAttachment) nioChannel.getAttachment(false);
-        if (att == null) {
-            throw new IOException("Key must be cancelled");
-        }
-        long writeTimeout = att.getTimeout();
-        Selector selector = null;
-        try {
-            selector = pool.get();
-        } catch ( IOException x ) {
-            //ignore
-        }
-        try {
-            written = pool.write(nioChannel.getBufHandler().getWriteBuffer(),
-                    nioChannel, selector, writeTimeout, true);
-        } finally {
-            if (selector != null) {
-                pool.put(selector);
-            }
-        }
-        return written;
-    }
-}
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.coyote.http11.upgrade;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.channels.Selector;
+
+import org.apache.tomcat.util.net.NioChannel;
+import org.apache.tomcat.util.net.NioEndpoint;
+import org.apache.tomcat.util.net.NioSelectorPool;
+import org.apache.tomcat.util.net.SocketWrapper;
+
+/**
+ * Implementation note: The need to extend Http11Processor could probably be
+ * removed if the Processor interface was expanded to cover all of the methods
+ * required by the AbstractProtocol. That would simplify the code and further
+ * reduce the size of instances of this class.
+ */
+public class UpgradeNioProcessor extends UpgradeProcessor<NioChannel> {
+
+    private NioChannel nioChannel;
+    private NioSelectorPool pool;
+
+    public UpgradeNioProcessor(SocketWrapper<NioChannel> wrapper,
+            UpgradeInbound upgradeInbound, NioSelectorPool pool) {
+        super(upgradeInbound);
+
+        this.nioChannel = wrapper.getSocket();
+        this.pool = pool;
+    }
+
+
+    /*
+     * Output methods
+     */
+    @Override
+    public void flush() throws IOException {
+        NioEndpoint.KeyAttachment att =
+                (NioEndpoint.KeyAttachment) nioChannel.getAttachment(false);
+        if (att == null) {
+            throw new IOException("Key must be cancelled");
+        }
+        long writeTimeout = att.getTimeout();
+        Selector selector = null;
+        try {
+            selector = pool.get();
+        } catch ( IOException x ) {
+            //ignore
+        }
+        try {
+            do {
+                if (nioChannel.flush(true, selector, writeTimeout)) {
+                    break;
+                }
+            } while (true);
+        } finally {
+            if (selector != null) {
+                pool.put(selector);
+            }
+        }
+    }
+
+    @Override
+    public void write(int b) throws IOException {
+        writeToSocket(new byte[] {(byte) b});
+    }
+
+    /*
+     * Input methods
+     */
+    @Override
+    public int read() throws IOException {
+        byte[] bytes = new byte[1];
+        readSocket(true, bytes, 0, 1);
+        return bytes[0];
+    }
+
+    @Override
+    public int read(byte[] bytes) throws IOException {
+        return readSocket(true, bytes, 0, bytes.length);
+    }
+
+
+    /*
+     * Adapted from the NioInputBuffer.
+     */
+    private int readSocket(boolean block, byte[] bytes, int offset, int len)
+            throws IOException {
+
+        int nRead = 0;
+        nioChannel.getBufHandler().getReadBuffer().clear();
+        nioChannel.getBufHandler().getReadBuffer().limit(len);
+        if (block) {
+            Selector selector = null;
+            try {
+                selector = pool.get();
+            } catch ( IOException x ) {
+                // Ignore
+            }
+            try {
+                NioEndpoint.KeyAttachment att =
+                        (NioEndpoint.KeyAttachment) nioChannel.getAttachment(false);
+                if (att == null) {
+                    throw new IOException("Key must be cancelled.");
+                }
+                nRead = pool.read(nioChannel.getBufHandler().getReadBuffer(),
+                        nioChannel, selector, att.getTimeout());
+            } catch (EOFException eof) {
+                nRead = -1;
+            } finally {
+                if (selector != null) {
+                    pool.put(selector);
+                }
+            }
+        } else {
+            nRead = nioChannel.read(nioChannel.getBufHandler().getReadBuffer());
+        }
+        if (nRead > 0) {
+            nioChannel.getBufHandler().getReadBuffer().flip();
+            nioChannel.getBufHandler().getReadBuffer().limit(nRead);
+            nioChannel.getBufHandler().getReadBuffer().get(bytes, offset, nRead);
+            return nRead;
+        } else if (nRead == -1) {
+            //return false;
+            throw new EOFException(sm.getString("nio.eof.error"));
+        } else {
+            return 0;
+        }
+    }
+
+
+    /*
+     * Adapted from the NioOutputBuffer
+     */
+    private synchronized int writeToSocket(byte[] bytes) throws IOException {
+
+        nioChannel.getBufHandler().getWriteBuffer().clear();
+        nioChannel.getBufHandler().getWriteBuffer().put(bytes);
+        nioChannel.getBufHandler().getWriteBuffer().flip();
+
+        int written = 0;
+        NioEndpoint.KeyAttachment att =
+                (NioEndpoint.KeyAttachment) nioChannel.getAttachment(false);
+        if (att == null) {
+            throw new IOException("Key must be cancelled");
+        }
+        long writeTimeout = att.getTimeout();
+        Selector selector = null;
+        try {
+            selector = pool.get();
+        } catch ( IOException x ) {
+            //ignore
+        }
+        try {
+            written = pool.write(nioChannel.getBufHandler().getWriteBuffer(),
+                    nioChannel, selector, writeTimeout, true);
+        } finally {
+            if (selector != null) {
+                pool.put(selector);
+            }
+        }
+        return written;
+    }
+}

Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/MutableInteger.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/MutableInteger.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/MutableInteger.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/MutableInteger.java Thu Mar 15 23:05:15 2012
@@ -17,6 +17,10 @@
 
 package org.apache.tomcat.util;
 
+/**
+ * @deprecated Will be removed in Tomcat 8.0.x
+ */
+@Deprecated
 public class MutableInteger {
     protected int value = 0;
     public MutableInteger() {}

Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java Thu Mar 15 23:05:15 2012
@@ -55,7 +55,7 @@ public abstract class AbstractEndpoint {
         public enum SocketState {
             // TODO Add a new state to the AsyncStateMachine and remove
             //      ASYNC_END (if possible)
-            OPEN, CLOSED, LONG, ASYNC_END, SENDFILE, UPGRADE
+            OPEN, CLOSED, LONG, ASYNC_END, SENDFILE, UPGRADING, UPGRADED
         }
 
 

Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java Thu Mar 15 23:05:15 2012
@@ -320,7 +320,9 @@ public class JIoEndpoint extends Abstrac
                         } catch (IOException e) {
                             // Ignore
                         }
-                    } else if (state == SocketState.OPEN){
+                    } else if (state == SocketState.OPEN ||
+                            state == SocketState.UPGRADING  ||
+                            state == SocketState.UPGRADED){
                         socket.setKeptAlive(true);
                         socket.access();
                         launch = true;

Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioBlockingSelector.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioBlockingSelector.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioBlockingSelector.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioBlockingSelector.java Thu Mar 15 23:05:15 2012
@@ -34,7 +34,6 @@ import java.util.concurrent.atomic.Atomi
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.ExceptionUtils;
-import org.apache.tomcat.util.MutableInteger;
 import org.apache.tomcat.util.net.NioEndpoint.KeyAttachment;
 
 public class NioBlockingSelector {
@@ -79,7 +78,8 @@ public class NioBlockingSelector {
      * @throws SocketTimeoutException if the write times out
      * @throws IOException if an IO Exception occurs in the underlying socket logic
      */
-    public int write(ByteBuffer buf, NioChannel socket, long writeTimeout,MutableInteger lastWrite) throws IOException {
+    public int write(ByteBuffer buf, NioChannel socket, long writeTimeout)
+            throws IOException {
         SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
         if ( key == null ) throw new IOException("Key no longer registered");
         KeyReference reference = new KeyReference();
@@ -92,7 +92,6 @@ public class NioBlockingSelector {
             while ( (!timedout) && buf.hasRemaining()) {
                 if (keycount > 0) { //only write if we were registered for a write
                     int cnt = socket.write(buf); //write the data
-                    if (lastWrite != null) lastWrite.set(cnt);
                     if (cnt == -1)
                         throw new EOFException();
                     written += cnt;

Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java Thu Mar 15 23:05:15 2012
@@ -25,7 +25,6 @@ import java.nio.channels.SelectionKey;
 import java.nio.channels.Selector;
 import java.nio.channels.SocketChannel;
 
-import org.apache.tomcat.util.MutableInteger;
 import org.apache.tomcat.util.net.NioEndpoint.Poller;
 import org.apache.tomcat.util.net.SecureNioChannel.ApplicationBufferHandler;
 
@@ -75,13 +74,12 @@ public class NioChannel implements ByteC
      * @param block     Unused. May be used when overridden
      * @param s         Unused. May be used when overridden
      * @param timeout   Unused. May be used when overridden
-     * @param lastWrite
      * @return Always returns <code>true</code> since there is no network buffer
      *         in the regular channel
      * @throws IOException
      */
-    public boolean flush(boolean block, Selector s, long timeout,MutableInteger lastWrite) throws IOException {
-        if (lastWrite!=null) lastWrite.set(1);
+    public boolean flush(boolean block, Selector s, long timeout)
+            throws IOException {
         return true;
     }
 

Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioSelectorPool.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioSelectorPool.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioSelectorPool.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioSelectorPool.java Thu Mar 15 23:05:15 2012
@@ -28,7 +28,6 @@ import java.util.concurrent.atomic.Atomi
 
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.MutableInteger;
 
 /**
  *
@@ -166,13 +165,13 @@ public class NioSelectorPool {
      * @throws IOException if an IO Exception occurs in the underlying socket logic
      */
     public int write(ByteBuffer buf, NioChannel socket, Selector selector, long writeTimeout) throws IOException {
-        return write(buf,socket,selector,writeTimeout,true,null);
+        return write(buf,socket,selector,writeTimeout,true);
     }
 
     public int write(ByteBuffer buf, NioChannel socket, Selector selector,
-                     long writeTimeout, boolean block,MutableInteger lastWrite) throws IOException {
+                     long writeTimeout, boolean block) throws IOException {
         if ( SHARED && block ) {
-            return blockingSelector.write(buf,socket,writeTimeout,lastWrite);
+            return blockingSelector.write(buf,socket,writeTimeout);
         }
         SelectionKey key = null;
         int written = 0;
@@ -184,7 +183,6 @@ public class NioSelectorPool {
                 int cnt = 0;
                 if ( keycount > 0 ) { //only write if we were registered for a write
                     cnt = socket.write(buf); //write the data
-                    if (lastWrite!=null) lastWrite.set(cnt);
                     if (cnt == -1) throw new EOFException();
 
                     written += cnt;

Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java?rev=1301262&r1=1301261&r2=1301262&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java Thu Mar 15 23:05:15 2012
@@ -29,8 +29,6 @@ import javax.net.ssl.SSLEngineResult;
 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
 import javax.net.ssl.SSLEngineResult.Status;
 
-import org.apache.tomcat.util.MutableInteger;
-
 /**
  *
  * Implementation of a secure socket channel
@@ -110,17 +108,17 @@ public class SecureNioChannel extends Ni
      * @param block     Should a blocking write be used?
      * @param s
      * @param timeout
-     * @param lastWrite
      * @return <code>true</code> if the network buffer has been flushed out and
      *         is empty else <code>false</code>
      * @throws IOException
      */
     @Override
-    public boolean flush(boolean block, Selector s, long timeout,MutableInteger lastWrite) throws IOException {
+    public boolean flush(boolean block, Selector s, long timeout)
+            throws IOException {
         if (!block) {
             flush(netOutBuffer);
         } else {
-            pool.write(netOutBuffer, this, s, timeout,block,lastWrite);
+            pool.write(netOutBuffer, this, s, timeout,block);
         }
         return !netOutBuffer.hasRemaining();
     }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org