hc-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject svn commit: r369238 - in /jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote: ./ impl/
Date Sun, 15 Jan 2006 17:41:15 GMT
Author: olegk
Date: Sun Jan 15 09:40:58 2006
New Revision: 369238

URL: http://svn.apache.org/viewcvs?rev=369238&view=rev
Log:
Refactored TestConnector to make use of a custom HttpConnection implementatation, which integrates
better with the Coyote API

Added:
    jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/CommitTrigger.java
Removed:
    jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/CoyoteHttpEntity.java
    jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/HttpProcessingContext.java
Modified:
    jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/HttpConnectionFactory.java
    jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/HttpConnectionManager.java
    jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/CoyoteHttpConnection.java
    jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultConnectionListener.java
    jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultHttpConnectionFactory.java
    jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultHttpConnectionManager.java
    jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/HttpConnectionProcessor.java

Modified: jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/HttpConnectionFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/HttpConnectionFactory.java?rev=369238&r1=369237&r2=369238&view=diff
==============================================================================
--- jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/HttpConnectionFactory.java
(original)
+++ jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/HttpConnectionFactory.java
Sun Jan 15 09:40:58 2006
@@ -32,7 +32,7 @@
 import java.io.IOException;
 import java.net.Socket;
 
-import org.apache.http.HttpServerConnection;
+import org.apache.http.coyote.impl.CoyoteHttpConnection;
 
 /**
  * <p>
@@ -43,6 +43,6 @@
  */
 public interface HttpConnectionFactory {
 
-    HttpServerConnection newConnection(Socket socket) throws IOException;
+    CoyoteHttpConnection newConnection(Socket socket) throws IOException;
     
 }

Modified: jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/HttpConnectionManager.java
URL: http://svn.apache.org/viewcvs/jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/HttpConnectionManager.java?rev=369238&r1=369237&r2=369238&view=diff
==============================================================================
--- jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/HttpConnectionManager.java
(original)
+++ jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/HttpConnectionManager.java
Sun Jan 15 09:40:58 2006
@@ -29,7 +29,7 @@
 
 package org.apache.http.coyote;
 
-import org.apache.http.HttpServerConnection;
+import org.apache.http.coyote.impl.CoyoteHttpConnection;
 
 /**
  * <p>
@@ -40,7 +40,7 @@
  */
 public interface HttpConnectionManager {
 
-    void process(HttpServerConnection incoming);
+    void process(CoyoteHttpConnection incoming);
     
     void shutdown();
     

Added: jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/CommitTrigger.java
URL: http://svn.apache.org/viewcvs/jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/CommitTrigger.java?rev=369238&view=auto
==============================================================================
--- jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/CommitTrigger.java
(added)
+++ jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/CommitTrigger.java
Sun Jan 15 09:40:58 2006
@@ -0,0 +1,45 @@
+/*
+ * $HeadURL: $
+ * $Revision: $
+ * $Date: $
+ *
+ * ====================================================================
+ *
+ *  Copyright 1999-2004 The Apache Software Foundation
+ *
+ *  Licensed 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.coyote.impl;
+
+import java.io.IOException;
+
+/**
+ * <p>
+ * </p>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @version $Revision: $
+ */
+public interface CommitTrigger {
+
+    void commit() throws IOException;
+    
+}

Modified: jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/CoyoteHttpConnection.java
URL: http://svn.apache.org/viewcvs/jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/CoyoteHttpConnection.java?rev=369238&r1=369237&r2=369238&view=diff
==============================================================================
--- jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/CoyoteHttpConnection.java
(original)
+++ jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/CoyoteHttpConnection.java
Sun Jan 15 09:40:58 2006
@@ -30,10 +30,45 @@
 package org.apache.http.coyote.impl;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.Socket;
+import java.net.SocketAddress;
 
-import org.apache.http.impl.DefaultHttpServerConnection;
+import org.apache.coyote.InputBuffer;
+import org.apache.coyote.OutputBuffer;
+import org.apache.coyote.Request;
+import org.apache.coyote.Response;
+import org.apache.http.ConnectionClosedException;
+import org.apache.http.Header;
+import org.apache.http.HeaderElement;
+import org.apache.http.HttpConnection;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpException;
+import org.apache.http.HttpMutableRequest;
+import org.apache.http.HttpRequestFactory;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpVersion;
+import org.apache.http.ProtocolException;
+import org.apache.http.RequestLine;
+import org.apache.http.StatusLine;
+import org.apache.http.impl.DefaultHttpRequestFactory;
+import org.apache.http.impl.io.SocketHttpDataReceiver;
+import org.apache.http.impl.io.SocketHttpDataTransmitter;
+import org.apache.http.io.CharArrayBuffer;
+import org.apache.http.io.ChunkedInputStream;
+import org.apache.http.io.ChunkedOutputStream;
+import org.apache.http.io.ContentLengthInputStream;
+import org.apache.http.io.ContentLengthOutputStream;
+import org.apache.http.io.HttpDataInputStream;
+import org.apache.http.io.HttpDataReceiver;
+import org.apache.http.io.HttpDataTransmitter;
+import org.apache.http.io.IdentityOutputStream;
+import org.apache.http.params.HttpConnectionParams;
 import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HTTP;
+import org.apache.tomcat.util.buf.ByteChunk;
 
 /**
  * <p>
@@ -42,24 +77,244 @@
  *
  * @version $Revision$
  */
-public class CoyoteHttpConnection extends DefaultHttpServerConnection {
+public class CoyoteHttpConnection implements HttpConnection, InputBuffer, OutputBuffer {
 
-    private String name = null;
+    private final Socket socket;
+    private final HttpDataTransmitter datatransmitter;
+    private final HttpDataReceiver datareceiver;
+    private final CharArrayBuffer charbuffer; 
+    private final HttpRequestFactory requestfactory;
+    private final byte[] readbuffer;
+
+    private CommitTrigger commitTrigger = null;
+    private OutputStream out = null;
+    private InputStream in = null;
     
-    public CoyoteHttpConnection() {
+    public CoyoteHttpConnection(final Socket socket, final HttpParams params) 
+            throws IOException {
         super();
-        this.name = "No Connection"; 
+        if (socket == null) {
+            throw new IllegalArgumentException("Socket may not be null"); 
+        }
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may not be null"); 
+        }
+        socket.setTcpNoDelay(HttpConnectionParams.getTcpNoDelay(params));
+        socket.setSoTimeout(HttpConnectionParams.getSoTimeout(params));
+        
+        int linger = HttpConnectionParams.getLinger(params);
+        if (linger >= 0) {
+            socket.setSoLinger(linger > 0, linger);
+        }
+        
+        int buffersize = HttpConnectionParams.getSocketBufferSize(params);
+        this.socket = socket;
+        this.datatransmitter = new SocketHttpDataTransmitter(socket, buffersize); 
+        this.datareceiver = new SocketHttpDataReceiver(socket, buffersize); 
+        this.charbuffer = new CharArrayBuffer(256);
+        this.requestfactory = new DefaultHttpRequestFactory();
+        this.readbuffer = new byte[buffersize];
     }
 
-    @Override
-	public void bind(final Socket socket, final HttpParams params) throws IOException {
-		super.bind(socket, params);
-        this.name = socket.getRemoteSocketAddress().toString(); 
-	}
+	public void close() throws IOException {
+        this.datatransmitter.flush();
+        try {
+            this.socket.shutdownOutput();
+        } catch (IOException ignore) {
+        }
+        try {
+            this.socket.shutdownInput();
+        } catch (IOException ignore) {
+        }
+        this.socket.close();
+    }
+
+    public boolean isOpen() {
+        return !this.socket.isClosed();
+    }
+
+    public boolean isStale() {
+        try {
+            this.datareceiver.isDataAvailable(1);
+            return false;
+        } catch (IOException ex) {
+            return true;
+        }
+    }
+
+    public void shutdown() throws IOException {
+        Socket tmpsocket = this.socket;
+        if (tmpsocket != null) {
+            tmpsocket.close();
+        }
+    }
+
+    public CommitTrigger getCommitTrigger() {
+        return this.commitTrigger;
+    }
+
+    public void setCommitTrigger(final CommitTrigger commitTrigger) {
+        this.commitTrigger = commitTrigger;
+    }
+
+    public HttpMutableRequest readRequest(final HttpParams params) 
+            throws HttpException, IOException {
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may not be null");
+        }
+        this.charbuffer.clear();
+        int i = this.datareceiver.readLine(this.charbuffer);
+        if (i == -1) {
+            throw new ConnectionClosedException("Client closed connection"); 
+        }
+        RequestLine requestline = RequestLine.parse(this.charbuffer, 0, this.charbuffer.length());
+        HttpMutableRequest request = this.requestfactory.newHttpRequest(requestline);
+        request.getParams().setDefaults(params);
+        Header[] headers = Header.parseAll(this.datareceiver);
+        for (i = 0; i < headers.length; i++) {
+            request.addHeader(headers[i]);
+        }
+        
+        // Prepare input stream
+        this.in = null;
+        if (request instanceof HttpEntityEnclosingRequest) {
+            Header transferEncodingHeader = request.getLastHeader(HTTP.TRANSFER_ENCODING);
+            Header contentLengthHeader = request.getLastHeader(HTTP.CONTENT_LEN);
+            if (transferEncodingHeader != null) {
+                HeaderElement[] encodings = transferEncodingHeader.getElements();
+                for (i = 0; i < encodings.length; i++) {
+                    String encoding = encodings[i].getName();
+                    if (encoding != null && !encoding.equals("") 
+                        && !encoding.equalsIgnoreCase(HTTP.CHUNK_CODING)
+                        && !encoding.equalsIgnoreCase(HTTP.IDENTITY_CODING)) {
+                        throw new ProtocolException("Unsupported transfer encoding: " + encoding);
+                    }
+                }
+                int len = encodings.length;
+                if (HTTP.IDENTITY_CODING.equalsIgnoreCase(transferEncodingHeader.getValue()))
{
+                    this.in = new HttpDataInputStream(this.datareceiver);               
            
+                } else if ((len > 0) && (HTTP.CHUNK_CODING.equalsIgnoreCase(
+                        encodings[len - 1].getName()))) { 
+                    this.in = new ChunkedInputStream(datareceiver);
+                } else {
+                    throw new ProtocolException("Chunk-encoding must be the last one applied");
+                }
+            } else if (contentLengthHeader != null) {
+                try {
+                    long contentlen = Long.parseLong(contentLengthHeader.getValue());
+                    this.in = new ContentLengthInputStream(datareceiver, contentlen);
+                } catch (NumberFormatException e) {
+                    throw new ProtocolException("Invalid content length: " + 
+                            contentLengthHeader.getValue());
+                }
+            } else {
+                throw new ProtocolException("Request entity is not correctly delimited");
+            }
+        }
+        return request;
+    }
+    
+    public void closeInput() throws IOException {
+        if (this.in != null) {
+            while (this.in.read(this.readbuffer) != -1) {
+                // Consume leftover content
+            }
+            this.in.close();
+            this.in = null;
+        }
+    }
+    
+    public void sendResponse(final HttpResponse response) 
+            throws HttpException, IOException {
+        if (response == null) {
+            throw new IllegalArgumentException("HTTP response may not be null");
+        }
+        this.charbuffer.clear();
+        StatusLine.format(this.charbuffer, response.getStatusLine());
+        this.datatransmitter.writeLine(this.charbuffer);
+        Header[] headers = response.getAllHeaders();
+        for (int i = 0; i < headers.length; i++) {
+            this.charbuffer.clear();
+            Header.format(this.charbuffer, headers[i]);
+            this.datatransmitter.writeLine(this.charbuffer);
+        }
+        this.charbuffer.clear();
+        this.datatransmitter.writeLine(this.charbuffer);
+
+        // Prepare output stream
+        this.out = null;
+        HttpVersion ver = response.getStatusLine().getHttpVersion();
+        HttpEntity entity = response.getEntity();
+        if (entity != null) {
+            long len = entity.getContentLength();
+            if (entity.isChunked() && ver.greaterEquals(HttpVersion.HTTP_1_1)) {
+                this.out = new ChunkedOutputStream(this.datatransmitter);
+            } else if (len >= 0) {
+                this.out = new ContentLengthOutputStream(this.datatransmitter, len);
+            } else {
+                this.out = new IdentityOutputStream(this.datatransmitter); 
+            }
+        } else {
+            this.datatransmitter.flush();
+        }
+    }
+
+    public void flush() throws IOException {
+        if (this.out != null) {
+            this.out.flush();
+        } else {
+            this.datatransmitter.flush();
+        }
+    }
+
+    public void closeOutput() throws IOException {
+        if (this.out != null) {
+            this.out.flush();
+            this.out.close();
+            this.out = null;
+        }
+    }
+    
+    public int doRead(final ByteChunk chunk, final Request request) 
+            throws IOException {
+        if (chunk == null) {
+            throw new IllegalArgumentException("Byte chunk may not be null");
+        }
+        if (this.in != null) {
+            int l = this.in.read(this.readbuffer);
+            if (l >= 0) {
+                chunk.setBytes(this.readbuffer, 0, l);
+            }
+            return l;
+        } else {
+            return -1;
+        }
+    }
 
-	@Override
+    public int doWrite(final ByteChunk chunk, final Response response) 
+            throws IOException {
+        if (chunk == null) {
+            throw new IllegalArgumentException("Byte chunk may not be null");
+        }
+        if (this.commitTrigger != null) {
+            this.commitTrigger.commit();
+        }
+        if (this.out != null) {
+            this.out.write(chunk.getBytes(), chunk.getStart(), chunk.getLength()); 
+            return chunk.getLength();
+        } else {
+            return -1;
+        }
+    }
+    
+    @Override
 	public String toString() {
-		return this.name;
+        SocketAddress address = this.socket.getRemoteSocketAddress();
+        if (address != null) {
+            return address.toString(); 
+        } else {
+            return "<no address>";
+        }
 	}
-    
+
 }

Modified: jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultConnectionListener.java
URL: http://svn.apache.org/viewcvs/jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultConnectionListener.java?rev=369238&r1=369237&r2=369238&view=diff
==============================================================================
--- jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultConnectionListener.java
(original)
+++ jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultConnectionListener.java
Sun Jan 15 09:40:58 2006
@@ -35,7 +35,6 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.http.HttpServerConnection;
 import org.apache.http.coyote.HttpConnectionFactory;
 import org.apache.http.coyote.HttpConnectionManager;
 import org.apache.http.coyote.IOProcessor;
@@ -86,7 +85,7 @@
                         LOG.debug("Incoming HTTP connection from " + 
                         		socket.getRemoteSocketAddress());
                     }
-                    HttpServerConnection conn = this.connfactory.newConnection(socket);
+                    CoyoteHttpConnection conn = this.connfactory.newConnection(socket);
                     this.connmanager.process(conn);
                 } catch (IOException ex) {
                 	if (LOG.isInfoEnabled()) {

Modified: jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultHttpConnectionFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultHttpConnectionFactory.java?rev=369238&r1=369237&r2=369238&view=diff
==============================================================================
--- jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultHttpConnectionFactory.java
(original)
+++ jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultHttpConnectionFactory.java
Sun Jan 15 09:40:58 2006
@@ -32,7 +32,6 @@
 import java.io.IOException;
 import java.net.Socket;
 
-import org.apache.http.HttpServerConnection;
 import org.apache.http.coyote.HttpConnectionFactory;
 import org.apache.http.params.HttpParams;
 
@@ -55,11 +54,9 @@
         this.params = params;
     }
     
-    public HttpServerConnection newConnection(final Socket socket)
+    public CoyoteHttpConnection newConnection(final Socket socket)
             throws IOException {
-        HttpServerConnection conn = new CoyoteHttpConnection();
-        conn.bind(socket, params);
-        return conn;
+        return new CoyoteHttpConnection(socket, this.params);
     }
     
 }

Modified: jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultHttpConnectionManager.java
URL: http://svn.apache.org/viewcvs/jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultHttpConnectionManager.java?rev=369238&r1=369237&r2=369238&view=diff
==============================================================================
--- jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultHttpConnectionManager.java
(original)
+++ jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/DefaultHttpConnectionManager.java
Sun Jan 15 09:40:58 2006
@@ -37,7 +37,6 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.coyote.Adapter;
-import org.apache.http.HttpServerConnection;
 import org.apache.http.coyote.HttpConnectionManager;
 import org.apache.http.coyote.IOProcessingListener;
 import org.apache.http.coyote.IOProcessor;
@@ -102,7 +101,7 @@
         this.processors.remove(processor);
     }
     
-    public void process(final HttpServerConnection conn) {
+    public void process(final CoyoteHttpConnection conn) {
         if (conn == null) {
             throw new IllegalArgumentException("HTTP connection may not be null");
         }

Modified: jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/HttpConnectionProcessor.java
URL: http://svn.apache.org/viewcvs/jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/HttpConnectionProcessor.java?rev=369238&r1=369237&r2=369238&view=diff
==============================================================================
--- jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/HttpConnectionProcessor.java
(original)
+++ jakarta/httpcomponents/trunk/coyote-httpconnector/src/java/org/apache/http/coyote/impl/HttpConnectionProcessor.java
Sun Jan 15 09:40:58 2006
@@ -30,7 +30,6 @@
 package org.apache.http.coyote.impl;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.InetAddress;
 import java.net.SocketException;
 import java.net.SocketTimeoutException;
@@ -44,21 +43,16 @@
 import org.apache.coyote.ActionHook;
 import org.apache.coyote.Adapter;
 import org.apache.coyote.Constants;
-import org.apache.coyote.InputBuffer;
-import org.apache.coyote.OutputBuffer;
 import org.apache.coyote.Request;
 import org.apache.coyote.Response;
 import org.apache.http.ConnectionClosedException;
 import org.apache.http.Header;
-import org.apache.http.HttpEntity;
 import org.apache.http.HttpEntityEnclosingRequest;
 import org.apache.http.HttpException;
-import org.apache.http.HttpMutableEntityEnclosingRequest;
 import org.apache.http.HttpMutableRequest;
 import org.apache.http.HttpMutableResponse;
 import org.apache.http.HttpRequest;
 import org.apache.http.HttpResponse;
-import org.apache.http.HttpServerConnection;
 import org.apache.http.HttpStatus;
 import org.apache.http.HttpVersion;
 import org.apache.http.MethodNotSupportedException;
@@ -71,17 +65,18 @@
 import org.apache.http.coyote.NotImplementedException;
 import org.apache.http.coyote.UnsupportedHttpVersionException;
 import org.apache.http.coyote.params.CoyoteParams;
+import org.apache.http.entity.BasicHttpEntity;
 import org.apache.http.impl.ConnectionReuseStrategy;
 import org.apache.http.impl.DefaultConnectionReuseStrategy;
 import org.apache.http.message.BasicHttpResponse;
-import org.apache.http.params.HttpConnectionParams;
 import org.apache.http.params.HttpParams;
 import org.apache.http.protocol.AbstractHttpProcessor;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpExecutionContext;
 import org.apache.http.protocol.ResponseConnControl;
 import org.apache.http.protocol.ResponseContent;
 import org.apache.http.protocol.ResponseDate;
 import org.apache.http.protocol.ResponseServer;
-import org.apache.tomcat.util.buf.ByteChunk;
 import org.apache.tomcat.util.http.MimeHeaders;
 
 /**
@@ -92,16 +87,18 @@
  * @version $Revision$
  */
 public class HttpConnectionProcessor extends AbstractHttpProcessor 
-		implements IOProcessor, InputBuffer, OutputBuffer, ActionHook {
+		implements IOProcessor, ActionHook {
 
     private static Log LOG = LogFactory.getLog(HttpConnectionProcessor.class);
 	
     private volatile boolean destroyed = false;
     
-    private final HttpServerConnection conn;
+    private final CoyoteHttpConnection conn;
     private final HttpParams params;
     private final Adapter adapter;
     private final IOProcessingListener listener;
+    private final HttpContext context;
+    private final ConnectionReuseStrategy connStrategy;
 
     private final Request coyotereq;
     private final Response coyoteres;
@@ -109,17 +106,12 @@
     private HttpMutableRequest httpreq = null;
     private HttpMutableResponse httpres = null;
     
-    private HttpEntity in = null;
-    private CoyoteHttpEntity out = null;
-
-	private final byte[] inbuffer;
-	
     public HttpConnectionProcessor(
-            final HttpServerConnection conn,
+            final CoyoteHttpConnection conn,
             final HttpParams params,
             final Adapter adapter,
             final IOProcessingListener listener) {
-    	super(new HttpProcessingContext(null));
+    	super();
         if (conn == null) {
             throw new IllegalArgumentException("HTTP connection may not be null");
         }
@@ -133,20 +125,24 @@
         this.params = params;
         this.adapter = adapter;
         this.listener = listener;
+        this.context = new HttpExecutionContext(null);
+        this.connStrategy = new DefaultConnectionReuseStrategy();
+        
+        this.conn.setCommitTrigger(new CommitTrigger() {
+            
+            public void commit() throws IOException {
+                commitResponse();
+            }
+            
+        });      
         
         this.coyotereq = new Request();
         this.coyoteres = new Response();
-        this.coyotereq.setInputBuffer(this);
-        this.coyoteres.setOutputBuffer(this);
+        this.coyotereq.setInputBuffer(conn);
+        this.coyoteres.setOutputBuffer(conn);
         this.coyoteres.setHook(this);
         this.coyoteres.setRequest(this.coyotereq);
         
-        int buffersize = HttpConnectionParams.getSocketBufferSize(this.params);
-        if (buffersize < 2048) {
-            buffersize = 2048;
-        }
-        this.inbuffer = new byte[buffersize];
-
         // Add required protocol interceptors
         addInterceptor(new ResponseContent());
         addInterceptor(new ResponseConnControl());
@@ -154,7 +150,7 @@
         addInterceptor(new ResponseServer());
         
         // Add connection to the HTTP context
-        getContext().setAttribute(HttpProcessingContext.HTTP_CONNECTION, conn);
+        this.context.setAttribute(HttpContext.HTTP_CONNECTION, conn);
     }
 
     public void run() {
@@ -165,13 +161,9 @@
                         receiveHttpRequest();
                         prepareCoyoteRequest();
                         callServletContainer();
-                        if (!this.coyoteres.isCommitted()) {
-                            prepareHttpResponse();
-                            sendHttpResponse();
-                            this.coyoteres.setCommitted(true);
-                        }
-                        closeInputBuffer();
-                        closeOutputBuffer();
+                        commitResponse();
+                        this.conn.closeInput();
+                        this.conn.closeOutput();
                     	manageHttpConnection();
                         reset();
                 	} catch (HttpException ex) {
@@ -205,7 +197,7 @@
         LOG.debug("Waiting for incoming HTTP request");
         this.coyotereq.getRequestProcessor().setStage(Constants.STAGE_NEW);
         try {
-            this.httpreq = this.conn.receiveRequestHeader(this.params);
+            this.httpreq = this.conn.readRequest(this.params);
         } catch (SocketException ex) {
             if (LOG.isDebugEnabled()) {
                 LOG.debug(ex.getMessage());
@@ -215,15 +207,11 @@
         this.coyotereq.setStartTime(System.currentTimeMillis());
         LOG.debug("HTTP request header received");
         
-        if (this.httpreq instanceof HttpMutableEntityEnclosingRequest) {
-            this.conn.receiveRequestEntity((HttpMutableEntityEnclosingRequest)this.httpreq);
-        }
-        
         this.coyotereq.getRequestProcessor().setStage(Constants.STAGE_PREPARE);
 
-        preprocessRequest(this.httpreq);
+        preprocessRequest(this.httpreq, this.context);
         // Add request to the HTTP context
-        getContext().setAttribute(HttpProcessingContext.HTTP_REQUEST, this.httpreq);
+        this.context.setAttribute(HttpContext.HTTP_REQUEST, this.httpreq);
     }
 
     private HttpMutableResponse createResponse(int status) {
@@ -250,27 +238,25 @@
     }
 
     private void sendAck() throws IOException {
-    	if (this.httpreq instanceof HttpEntityEnclosingRequest) {
-    		if (((HttpEntityEnclosingRequest)this.httpreq).expectContinue()) {
-    	        HttpResponse ack = createResponse(HttpStatus.SC_CONTINUE);
-    	        try {
-    	            this.conn.sendResponseHeader(ack);
-    	            LOG.debug("100-Continue sent");
-    	        } catch (HttpException ex) {
-    	            LOG.error("Malformed HTTP response", ex);
-    	            this.conn.close();
-    	        }
-    		}
-    	}
+        if (this.httpreq instanceof HttpEntityEnclosingRequest) {
+            if (((HttpEntityEnclosingRequest)this.httpreq).expectContinue()) {
+                HttpResponse ack = createResponse(HttpStatus.SC_CONTINUE);
+                try {
+                    this.conn.sendResponse(ack);
+                    this.conn.flush();
+                    LOG.debug("100-Continue sent");
+                } catch (HttpException ex) {
+                    LOG.error("Malformed HTTP response", ex);
+                    this.conn.close();
+                }
+            }
+        }
     }
     
     private void sendHttpResponse() throws IOException {
     	try {
-            if (this.httpres instanceof HttpMutableResponse) {
-            	postprocessResponse((HttpMutableResponse)this.httpres);
-            }
-    		this.conn.sendResponseHeader(this.httpres);
-            this.conn.sendResponseEntity(this.httpres);
+    	    postprocessResponse(this.httpres, this.context);
+    		this.conn.sendResponse(this.httpres);
             LOG.debug("HTTP response header sent");
     	} catch (HttpException ex) {
     		LOG.error("Malformed HTTP response", ex);
@@ -278,28 +264,6 @@
     	}
     }
 
-    private void closeInputBuffer() throws IOException {
-    	if (this.in != null) {
-            InputStream instream = this.in.getContent();
-    		while (instream.read(this.inbuffer) != -1) {
-                // Consume leftover content
-    		}
-            instream.close();            
-    	}
-    }
-    
-    private void flushOutputBuffer() throws IOException {
-        if (this.out != null) {
-            this.out.flush();
-        }
-    }
-    
-    private void closeOutputBuffer() throws IOException {
-        if (this.out != null) {
-            this.out.close();
-        }
-    }
-    
     private void prepareCoyoteRequest() throws IOException, HttpException {
     	this.coyotereq.getRequestProcessor().setStage(Constants.STAGE_PARSE);
         // Convert the request line
@@ -380,11 +344,6 @@
         for (Header header: headers) {
         	this.coyotereq.getMimeHeaders().addValue(header.getName()).setString(header.getValue());
         }
-        
-        // Keep the input entity if available
-        if (this.httpreq instanceof HttpEntityEnclosingRequest) {
-        	this.in = ((HttpEntityEnclosingRequest)this.httpreq).getEntity();
-        }
     }
         
     private void callServletContainer() throws IOException, HttpException {
@@ -401,6 +360,14 @@
         }
 	}
 
+    private void commitResponse() throws IOException {
+        if (!this.coyoteres.isCommitted()) {
+            prepareHttpResponse();
+            sendHttpResponse();
+            this.coyoteres.setCommitted(true);
+        }
+    }
+    
     private boolean canResponseHaveBody(final HttpRequest request, final HttpResponse response)
{
         if ("HEAD".equalsIgnoreCase(request.getRequestLine().getMethod())) {
             return false;
@@ -430,31 +397,32 @@
         }
         
         StatusLine statusline = new StatusLine(ver, statuscode, statusPhrase);
-        BasicHttpResponse tmp = new BasicHttpResponse(statusline);
-        tmp.getParams().setDefaults(this.params);
-        this.httpres = tmp;
+        this.httpres = new BasicHttpResponse(statusline);
+        this.httpres.getParams().setDefaults(this.params);
         MimeHeaders headers = this.coyoteres.getMimeHeaders();
         int size = headers.size();
         for (int i = 0; i < size; i++) {
             String name = headers.getName(i).getString();
             String value = headers.getValue(i).getString();
-            tmp.addHeader(new Header(name, value, false));
+            this.httpres.addHeader(new Header(name, value, false));
         }
         String lang = this.coyoteres.getContentLanguage();
         if (lang != null) {
-        	tmp.setHeader(new Header("Content-Language", lang, false));
+            this.httpres.setHeader(new Header("Content-Language", lang, false));
         }
         if (canResponseHaveBody(this.httpreq, this.httpres)) {
-            this.out = new CoyoteHttpEntity();
-            this.out.setContentLength(this.coyoteres.getContentLengthLong());
-        	tmp.setEntity(this.out);
+            BasicHttpEntity entity = new BasicHttpEntity();
+            entity.setContentLength(this.coyoteres.getContentLengthLong());
+            if (entity.getContentLength() < 0) {
+                entity.setChunked(true);
+            }
+            this.httpres.setEntity(entity);
         }
     }
 
     private void manageHttpConnection() throws IOException {
     	if (this.conn.isOpen()) {
-            ConnectionReuseStrategy connreuse = new DefaultConnectionReuseStrategy();
-            if (!connreuse.keepAlive(this.httpres)) {
+            if (!this.connStrategy.keepAlive(this.httpres)) {
                 this.conn.close();
             	LOG.debug("Connection closed");
                 this.coyotereq.getRequestProcessor().setStage(Constants.STAGE_ENDED);
@@ -470,8 +438,6 @@
         this.coyoteres.recycle();
         this.httpreq = null;
         this.httpres = null;
-        this.out = null;
-        this.in = null;
     }
     
     public void close() throws IOException {
@@ -498,9 +464,7 @@
                 return;
             }
             try {
-                prepareHttpResponse();
-                sendHttpResponse();
-                this.coyoteres.setCommitted(true);
+                commitResponse();
             } catch (IOException ex) {
                 this.coyoteres.setErrorException(ex);
             }
@@ -517,24 +481,16 @@
         } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) {
             LOG.debug("Action Flush");
             try {
-                if (!this.coyoteres.isCommitted()) {
-                    prepareHttpResponse();
-                    sendHttpResponse();
-                    this.coyoteres.setCommitted(true);
-                }
-                flushOutputBuffer();
+                commitResponse();
+                this.conn.flush();
             } catch (IOException ex) {
                 this.coyoteres.setErrorException(ex);
             }            
         } else if (actionCode == ActionCode.ACTION_CLOSE) {
             LOG.debug("Action Close");
             try {
-                if (!this.coyoteres.isCommitted()) {
-                    prepareHttpResponse();
-                    sendHttpResponse();
-                    this.coyoteres.setCommitted(true);
-                }
-                closeOutputBuffer();
+                commitResponse();
+                this.conn.closeOutput();
             } catch (IOException ex) {
                 this.coyoteres.setErrorException(ex);
             }            
@@ -557,38 +513,6 @@
         	throw new NotImplementedException("Action code " + actionCode + 
         			" not implemented"); 
         }
-	}
-
-	public int doRead(final ByteChunk chunk, final Request request) throws IOException {
-		if (chunk == null) {
-			throw new IllegalArgumentException("Byte chunk may not be null");
-		}
-		if (this.in != null) {
-			int l = this.in.getContent().read(this.inbuffer);
-			if (l >= 0) {
-				chunk.setBytes(this.inbuffer, 0, l);
-			}
-			return l;
-		} else {
-			return -1;
-		}
-	}
-
-	public int doWrite(final ByteChunk chunk, final Response response) throws IOException {
-		if (chunk == null) {
-			throw new IllegalArgumentException("Byte chunk may not be null");
-		}
-		if (!this.coyoteres.isCommitted()) {
-            prepareHttpResponse();
-            sendHttpResponse();
-            this.coyoteres.setCommitted(true);
-		}
-		if (this.out != null) {
-			this.out.writeBytes(chunk.getBytes(), chunk.getStart(), chunk.getLength()); 
-			return chunk.getLength();
-		} else {
-			return -1;
-		}
 	}
 
 	@Override



Mime
View raw message