You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2005/07/27 22:54:48 UTC

svn commit: r225630 - in /jakarta/httpclient/trunk/src: ./ org/ org/apache/ org/apache/http/ org/apache/http/coyote/

Author: olegk
Date: Wed Jul 27 13:54:40 2005
New Revision: 225630

URL: http://svn.apache.org/viewcvs?rev=225630&view=rev
Log:
Initial import of the coyote HTTP connector based on HttpCommon classes

The connector appears functional if run outside Tomcat, even though only the most fundamental functions are implemented at the moment. The code is still largely untested.

Added:
    jakarta/httpclient/trunk/src/
    jakarta/httpclient/trunk/src/org/
    jakarta/httpclient/trunk/src/org/apache/
    jakarta/httpclient/trunk/src/org/apache/http/
    jakarta/httpclient/trunk/src/org/apache/http/coyote/
    jakarta/httpclient/trunk/src/org/apache/http/coyote/ConnectionListener.java   (with props)
    jakarta/httpclient/trunk/src/org/apache/http/coyote/DefaultHttpConnectionManager.java   (with props)
    jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpConnectionManager.java   (with props)
    jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProcessor.java   (with props)
    jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProtocolHandler.java   (with props)
    jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessingListener.java   (with props)
    jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessor.java   (with props)

Added: jakarta/httpclient/trunk/src/org/apache/http/coyote/ConnectionListener.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/src/org/apache/http/coyote/ConnectionListener.java?rev=225630&view=auto
==============================================================================
--- jakarta/httpclient/trunk/src/org/apache/http/coyote/ConnectionListener.java (added)
+++ jakarta/httpclient/trunk/src/org/apache/http/coyote/ConnectionListener.java Wed Jul 27 13:54:40 2005
@@ -0,0 +1,116 @@
+/*
+ * $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;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.HttpServerConnection;
+import org.apache.http.impl.DefaultHttpParams;
+import org.apache.http.impl.DefaultHttpServerConnection;
+import org.apache.http.params.HttpParams;
+
+/**
+ * <p>
+ * </p>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @version $Revision$
+ */
+public class ConnectionListener implements IOProcessor {
+
+    private static Log LOG = LogFactory.getLog(ConnectionListener.class);
+	
+    private volatile boolean destroyed = false;
+    
+    private final ServerSocketChannel serverchannel;
+    private final HttpConnectionManager connmanager;
+    
+    public ConnectionListener(int port, final HttpConnectionManager connmanager) 
+            throws IOException {
+    	super();
+        if (connmanager == null) {
+            throw new IllegalArgumentException("Connection manager may not be null");
+        }
+        this.connmanager = connmanager;
+        this.serverchannel = ServerSocketChannel.open();
+        this.serverchannel.socket().bind(new InetSocketAddress(port));
+    }
+
+    public void run() {
+    	if (LOG.isInfoEnabled()) {
+            LOG.info("Listening on port " + this.serverchannel.socket().getLocalPort());
+    	}
+        try {
+            while (this.serverchannel.isOpen() && !Thread.interrupted()) {
+                try {
+                    SocketChannel channel = this.serverchannel.accept();
+                    Socket socket = channel.socket();
+                    HttpServerConnection conn = new DefaultHttpServerConnection();
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("Incoming connection from " + socket.getRemoteSocketAddress());
+                    }
+                    HttpParams defaparams = new DefaultHttpParams(); 
+                    conn.bind(socket, defaparams);
+                    this.connmanager.process(conn);
+                } catch (Throwable ex) {
+                    break;
+                }
+            }
+        } finally {
+            destroy();
+        }
+    }
+    
+	public void close() throws IOException {
+        this.serverchannel.close();
+	}
+    
+    public void destroy() {
+        this.destroyed = true;
+        try {
+            close();
+        } catch (IOException ex) {
+            if (LOG.isWarnEnabled()) {
+                LOG.warn("I/O error closing listener", ex);
+            }
+        }
+    }
+
+    public boolean isDestroyed() {
+        return this.destroyed;
+    }
+    
+}

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/ConnectionListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/ConnectionListener.java
------------------------------------------------------------------------------
    svn:executable = 

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/ConnectionListener.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/ConnectionListener.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/httpclient/trunk/src/org/apache/http/coyote/DefaultHttpConnectionManager.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/src/org/apache/http/coyote/DefaultHttpConnectionManager.java?rev=225630&view=auto
==============================================================================
--- jakarta/httpclient/trunk/src/org/apache/http/coyote/DefaultHttpConnectionManager.java (added)
+++ jakarta/httpclient/trunk/src/org/apache/http/coyote/DefaultHttpConnectionManager.java Wed Jul 27 13:54:40 2005
@@ -0,0 +1,122 @@
+/*
+ * $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;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.HttpServerConnection;
+import org.apache.http.params.HttpParams;
+
+/**
+ * <p>
+ * </p>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @version $Revision$
+ */
+public class DefaultHttpConnectionManager implements HttpConnectionManager {
+
+    private static Log LOG = LogFactory.getLog(DefaultHttpConnectionManager.class);
+    
+    private final HttpParams params;
+    private final Executor executor;
+    private final List<IOProcessor> processors;
+    
+    public DefaultHttpConnectionManager(final HttpParams params, final Executor executor) {
+        super();
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may not be null");
+        }
+        if (executor == null) {
+            throw new IllegalArgumentException("Executor may not be null");
+        }
+        this.params = params;
+        this.executor = executor;
+        this.processors = new LinkedList<IOProcessor>();
+    }
+
+    private synchronized void cleanup() {
+        for (Iterator<IOProcessor> i = this.processors.iterator(); i.hasNext(); ) {
+            IOProcessor processor = i.next();
+            if (processor.isDestroyed()) {
+                i.remove();
+            }
+        }
+    }
+    
+    private synchronized void addProcessor(final IOProcessor processor) {
+        if (processor == null) {
+            return;
+        }
+        this.processors.add(processor);
+    }
+    
+    private synchronized void removeProcessor(final IOProcessor processor) {
+        if (processor == null) {
+            return;
+        }
+        this.processors.remove(processor);
+    }
+    
+    public void process(final HttpServerConnection conn) {
+        if (conn == null) {
+            throw new IllegalArgumentException("HTTP connection may not be null");
+        }
+        // Evict destroyed processors
+        cleanup();
+        
+        IOProcessingListener listener = new IOProcessingListener() {
+          
+            public void completed(IOProcessor processor) {
+                removeProcessor(processor);
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug(processor + " processor terminated");
+                }
+            }
+            
+        };
+        HttpProcessor processor = new HttpProcessor(conn, this.params, listener);
+        addProcessor(processor);
+        this.executor.execute(processor);
+    }
+    
+    public synchronized void shutdown() {
+        for (IOProcessor processor: this.processors) {
+            processor.destroy();
+        }
+        this.processors.clear();
+    }
+	
+}

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/DefaultHttpConnectionManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/DefaultHttpConnectionManager.java
------------------------------------------------------------------------------
    svn:executable = 

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/DefaultHttpConnectionManager.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/DefaultHttpConnectionManager.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpConnectionManager.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpConnectionManager.java?rev=225630&view=auto
==============================================================================
--- jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpConnectionManager.java (added)
+++ jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpConnectionManager.java Wed Jul 27 13:54:40 2005
@@ -0,0 +1,47 @@
+/*
+ * $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;
+
+import org.apache.http.HttpServerConnection;
+
+/**
+ * <p>
+ * </p>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @version $Revision$
+ */
+public interface HttpConnectionManager {
+
+    void process(HttpServerConnection incoming);
+    
+    void shutdown();
+    
+}

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpConnectionManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpConnectionManager.java
------------------------------------------------------------------------------
    svn:executable = 

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpConnectionManager.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpConnectionManager.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProcessor.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProcessor.java?rev=225630&view=auto
==============================================================================
--- jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProcessor.java (added)
+++ jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProcessor.java Wed Jul 27 13:54:40 2005
@@ -0,0 +1,245 @@
+/*
+ * $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;
+
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+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.HttpMutableResponse;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpServerConnection;
+import org.apache.http.HttpStatus;
+import org.apache.http.MethodNotSupportedException;
+import org.apache.http.ProtocolException;
+import org.apache.http.entity.EntityConsumer;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.BasicHttpResponse;
+import org.apache.http.impl.ConnectionReuseStrategy;
+import org.apache.http.impl.DefaultConnectionReuseStrategy;
+import org.apache.http.impl.DefaultHttpParams;
+import org.apache.http.params.HttpConnectionParams;
+import org.apache.http.params.HttpParams;
+
+/**
+ * <p>
+ * </p>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @version $Revision$
+ */
+public class HttpProcessor implements IOProcessor {
+
+    private static Log LOG = LogFactory.getLog(HttpProcessor.class);
+	
+    private volatile boolean destroyed = false;
+    
+    private final HttpServerConnection conn;
+    private final HttpParams params;
+    private final IOProcessingListener listener;
+    
+    public HttpProcessor(
+            final HttpServerConnection conn,
+            final HttpParams parentparams,
+            final IOProcessingListener listener) {
+    	super();
+        if (conn == null) {
+            throw new IllegalArgumentException("HTTP connection may not be null");
+        }
+        this.conn = conn;
+        this.params = new DefaultHttpParams();
+        this.params.setDefaults(parentparams);
+        this.params.setIntParameter(HttpConnectionParams.SO_TIMEOUT, 5000);
+        this.listener = listener;
+    }
+
+    public HttpProcessor(final HttpServerConnection conn, final HttpParams params) {
+        this(conn, params, null);
+    }
+
+    public void run() {
+        try {
+            while (this.conn.isOpen() && !Thread.interrupted()) {
+                try {
+                    process();
+                } catch (IOException ex) {
+                    LOG.warn("I/O error processing HTTP request", ex);
+                    break;
+                } catch (Throwable ex) {
+                    LOG.error("Runtime error processing HTTP request", ex);
+                    break;
+                }
+            }
+        } finally {
+            destroy();
+            if (this.listener != null) {
+                this.listener.completed(this);
+            }
+        }
+    }
+
+    private void process() throws IOException {
+        BasicHttpResponse response = new BasicHttpResponse();
+        try {
+            HttpRequest request = this.conn.receiveRequest(this.params);
+            LOG.debug("HTTP request received");
+            handleRequest(request, response);
+        } catch (ConnectionClosedException ex) {
+        	LOG.debug("Client closed connection");
+            this.conn.close();
+            return;
+        } catch (HttpException ex) {
+            handleException(ex, response);
+        } catch (IOException ex) {
+        	LOG.warn("I/O error receiving HTTP request", ex);
+            this.conn.close();
+            return;
+        }
+        try {
+            this.conn.sendResponse(response);
+            LOG.debug("HTTP response sent");
+        } catch (HttpException ex) {
+        	LOG.debug("Malformed HTTP response: " + ex.getMessage());
+            this.conn.close();
+        } catch (IOException ex) {
+        	LOG.warn("I/O error sending HTTP response", ex);
+            this.conn.close();
+            return;
+        }
+        ConnectionReuseStrategy connreuse = new DefaultConnectionReuseStrategy();
+        if (!connreuse.keepAlive(response)) {
+            this.conn.close();
+        	LOG.debug("Connection closed");
+        } else {
+        	LOG.debug("Connection kept alive");
+        }
+    }
+    
+    public void close() throws IOException {
+        this.conn.close();
+    }
+    
+	public void destroy() {
+        this.destroyed = true;
+        try {
+            close();
+        } catch (IOException ex) {
+        	LOG.warn("I/O error closing connection", ex);
+        }
+	}
+    
+    public boolean isDestroyed() {
+        return this.destroyed;
+    }
+	    
+    private void handleException(final HttpException ex, final HttpMutableResponse response) {
+        if (ex instanceof MethodNotSupportedException) {
+            response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED);
+        } else if (ex instanceof ProtocolException) {
+            response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
+        } else {
+            response.setStatusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
+        }
+        response.setHeader(new Header("Server", "Jakarta HttpCommons"));
+        response.setHeader(new Header("Connection", "Close"));
+    }
+    
+    public void handleRequest(final HttpRequest request,
+			final HttpMutableResponse response) throws IOException {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("<html>");
+		buffer.append("<body>");
+		buffer.append("<p>Request method: ");
+		buffer.append(request.getRequestLine().getMethod());
+		buffer.append("</p>");
+		buffer.append("<p>Request URI: ");
+		buffer.append(request.getRequestLine().getUri());
+		buffer.append("</p>");
+		buffer.append("<p>Request Version: ");
+		buffer.append(request.getRequestLine().getHttpVersion());
+		buffer.append("</p>");
+		if (request instanceof HttpEntityEnclosingRequest) {
+			HttpEntity entity = ((HttpEntityEnclosingRequest) request)
+					.getEntity();
+			buffer.append("<p>Content Type: ");
+			buffer.append(entity.getContentType());
+			buffer.append("</p>");
+			buffer.append("<p>Content Chunk-coded: ");
+			buffer.append(entity.isChunked());
+			buffer.append("</p>");
+			EntityConsumer consume = new EntityConsumer(
+					(HttpEntityEnclosingRequest) request);
+			if (entity.getContentType() != null
+					&& entity.getContentType().toLowerCase()
+							.startsWith("text/")) {
+				buffer.append("<p>");
+				buffer.append(consume.asString());
+				buffer.append("</p>");
+			} else {
+				byte[] raw = consume.asByteArray();
+				buffer.append("<p>");
+				for (int i = 0; i < raw.length; i++) {
+					buffer.append(Integer.toHexString(raw[i]).toLowerCase());
+					if (i % 20 == 19) {
+						buffer.append("<br>");
+					} else {
+						buffer.append(" ");
+					}
+				}
+				buffer.append("</p>");
+			}
+		}
+		buffer.append("</body>");
+		buffer.append("</html>");
+		StringEntity body = new StringEntity(buffer.toString());
+		body.setContentType("text/html; charset=UTF-8");
+
+		response.setStatusCode(HttpStatus.SC_OK);
+		response.setHeader(new Header("Server", "Jakarta HttpCommons"));
+		response.setHeader(new Header("Connection", "Keep-Alive"));
+		if (body.isChunked() || body.getContentLength() < 0) {
+			response.setHeader(new Header("Transfer-Encoding", "chunked"));
+		} else {
+			response.setHeader(new Header("Content-Length", Long.toString(body
+					.getContentLength())));
+		}
+		if (body.getContentType() != null) {
+			response
+					.setHeader(new Header("Content-Type", body.getContentType()));
+		}
+		response.setEntity(body);
+	}
+       
+}

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProcessor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProcessor.java
------------------------------------------------------------------------------
    svn:executable = 

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProcessor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProtocolHandler.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProtocolHandler.java?rev=225630&view=auto
==============================================================================
--- jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProtocolHandler.java (added)
+++ jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProtocolHandler.java Wed Jul 27 13:54:40 2005
@@ -0,0 +1,130 @@
+/*
+ * $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;
+
+import java.util.Iterator;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.coyote.Adapter;
+import org.apache.coyote.ProtocolHandler;
+import org.apache.http.impl.DefaultHttpParams;
+import org.apache.http.params.HttpParams;
+
+/**
+ * <p>
+ * </p>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @version $Revision$
+ */
+public class HttpProtocolHandler implements ProtocolHandler  {
+
+    private static Log LOG = LogFactory.getLog(HttpProtocolHandler.class);
+    
+    private final HttpParams params;
+    
+	private ConnectionListener listener = null;
+	private ExecutorService listenerExecutor = null;
+    private HttpConnectionManager connmanager = null;
+	private ExecutorService requestExecutor = null;
+	
+	public HttpProtocolHandler() {
+		super();
+		this.params = new DefaultHttpParams(); 
+	}
+
+	public void init() throws Exception {
+        this.requestExecutor = Executors.newFixedThreadPool(20);
+        this.connmanager = new DefaultHttpConnectionManager(this.params, this.requestExecutor); 
+        this.listenerExecutor = Executors.newSingleThreadExecutor();
+        this.listener = new ConnectionListener(8080, this.connmanager);
+	}
+
+    public void destroy() throws Exception {
+        // Attempt to terminate the listener nicely
+        LOG.info("Shut down listener");
+        this.listenerExecutor.shutdown();
+        this.listenerExecutor.awaitTermination(5000, TimeUnit.MILLISECONDS);
+        if (!this.listenerExecutor.isTerminated()) {
+            // Terminate the listener forcibly
+            LOG.info("Destroy listener");
+            this.listener.destroy();
+            // Leave it up to the garbage collector to clean up the mess
+            this.listener = null;
+        }
+        // Attempt to terminate the active processors nicely
+        LOG.info("Shut down HTTP processors");
+        this.requestExecutor.shutdown();
+        this.requestExecutor.awaitTermination(5000, TimeUnit.MILLISECONDS);
+        if (!this.requestExecutor.isTerminated()) {
+            // Terminate the active processors forcibly
+            LOG.info("Destroy processors");
+            this.connmanager.shutdown();
+            // Leave it up to the garbage collector to clean up the mess
+            this.connmanager = null;
+        }
+        LOG.info("HTTP protocol handler shut down");
+    }
+
+	public void start() throws Exception {
+		this.listenerExecutor.execute(this.listener);
+	}
+	
+	public void pause() throws Exception {
+        // Not implemented. What is it for, anyway?
+	}
+
+	public void resume() throws Exception {
+        // Not implemented. What is it for, anyway?
+	}
+
+	public Adapter getAdapter() {
+		return null;
+	}
+
+	public Object getAttribute(String name) {
+		return null;
+	}
+
+	public Iterator getAttributeNames() {
+		return null;
+	}
+
+	public void setAdapter(Adapter adapter) {
+	}
+
+	public void setAttribute(String name, Object value) {
+	}
+
+}

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProtocolHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProtocolHandler.java
------------------------------------------------------------------------------
    svn:executable = 

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProtocolHandler.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/HttpProtocolHandler.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessingListener.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessingListener.java?rev=225630&view=auto
==============================================================================
--- jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessingListener.java (added)
+++ jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessingListener.java Wed Jul 27 13:54:40 2005
@@ -0,0 +1,43 @@
+/*
+ * $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;
+
+/**
+ * <p>
+ * </p>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @version $Revision$
+ */
+public interface IOProcessingListener {
+
+    void completed(IOProcessor processor);
+    
+}

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessingListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessingListener.java
------------------------------------------------------------------------------
    svn:executable = 

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessingListener.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessingListener.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessor.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessor.java?rev=225630&view=auto
==============================================================================
--- jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessor.java (added)
+++ jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessor.java Wed Jul 27 13:54:40 2005
@@ -0,0 +1,47 @@
+/*
+ * $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;
+
+import java.io.Closeable;
+
+/**
+ * <p>
+ * </p>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @version $Revision$
+ */
+public interface IOProcessor extends Runnable, Closeable {
+
+    boolean isDestroyed();
+    
+    void destroy();
+    
+}

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessor.java
------------------------------------------------------------------------------
    svn:executable = 

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpclient/trunk/src/org/apache/http/coyote/IOProcessor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain