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 2007/01/24 20:40:56 UTC
svn commit: r499542 - in
/jakarta/httpcomponents/httpcore/trunk/module-nio/src:
examples/org/apache/http/nio/examples/ main/java/org/apache/http/nio/
main/java/org/apache/http/nio/impl/
main/java/org/apache/http/nio/impl/entity/ main/java/org/apache/ht...
Author: olegk
Date: Wed Jan 24 11:40:55 2007
New Revision: 499542
URL: http://svn.apache.org/viewvc?view=rev&rev=499542
Log:
Major changes in the client-side NIO protocol layer in preparation for resolution of HTTPCORE-26
Changelog:
* Added an interface intended to be used to control the execution of HTTP requests on the client side
* Added an HTTP client handler implementation that buffers the content of HTTP messages entirely in memory and executes HTTP requests on the main I/O thread.
Added:
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java (with props)
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/HttpRequestExecutionHandler.java (with props)
Modified:
jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/NHttpClient.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpClientHandler.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/DefaultNHttpClientConnection.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/entity/BufferedContent.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpServiceHandler.java
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/NHttpClient.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/NHttpClient.java?view=diff&rev=499542&r1=499541&r2=499542
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/NHttpClient.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/NHttpClient.java Wed Jan 24 11:40:55 2007
@@ -1,30 +1,23 @@
package org.apache.http.nio.examples;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.WritableByteChannel;
-import org.apache.http.ConnectionReuseStrategy;
-import org.apache.http.HttpConnection;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
-import org.apache.http.HttpRequestFactory;
import org.apache.http.HttpResponse;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpParams;
-import org.apache.http.impl.DefaultHttpRequestFactory;
-import org.apache.http.nio.ContentDecoder;
-import org.apache.http.nio.ContentEncoder;
-import org.apache.http.nio.NHttpClientConnection;
-import org.apache.http.nio.NHttpClientHandler;
+import org.apache.http.message.HttpGet;
import org.apache.http.nio.impl.DefaultClientIOEventDispatch;
import org.apache.http.nio.impl.reactor.DefaultConnectingIOReactor;
+import org.apache.http.nio.protocol.BufferingHttpClientHandler;
+import org.apache.http.nio.protocol.EventListener;
+import org.apache.http.nio.protocol.HttpRequestExecutionHandler;
import org.apache.http.nio.reactor.ConnectingIOReactor;
import org.apache.http.nio.reactor.IOEventDispatch;
import org.apache.http.nio.reactor.SessionRequest;
@@ -32,10 +25,8 @@
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpProcessor;
-import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpExecutionContext;
-import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
@@ -71,7 +62,21 @@
null,
new HttpHost("www.apache.org"));
- NHttpClientHandler handler = new MyNHttpClientHandler(reqs, params);
+ BasicHttpProcessor httpproc = new BasicHttpProcessor();
+ httpproc.addInterceptor(new RequestContent());
+ httpproc.addInterceptor(new RequestTargetHost());
+ httpproc.addInterceptor(new RequestConnControl());
+ httpproc.addInterceptor(new RequestUserAgent());
+ httpproc.addInterceptor(new RequestExpectContinue());
+
+ BufferingHttpClientHandler handler = new BufferingHttpClientHandler(
+ httpproc,
+ new MyHttpRequestExecutionHandler(),
+ new DefaultConnectionReuseStrategy(),
+ params);
+
+ handler.setEventListener(new EventLogger());
+
IOEventDispatch ioEventDispatch = new DefaultClientIOEventDispatch(handler, params);
try {
@@ -84,151 +89,74 @@
System.out.println("Shutdown");
}
- static class MyNHttpClientHandler implements NHttpClientHandler {
+ static class MyHttpRequestExecutionHandler implements HttpRequestExecutionHandler {
- private final SessionRequest[] reqs;
- private final HttpParams params;
- private final HttpRequestFactory requestFactory;
- private final HttpProcessor httpProcessor;
- private final ByteBuffer inbuf;
- private final ConnectionReuseStrategy connStrategy;
-
- private int connCount = 0;
-
- public MyNHttpClientHandler(final SessionRequest[] reqs, final HttpParams params) {
- super();
- this.reqs = reqs;
- this.params = params;
- this.requestFactory = new DefaultHttpRequestFactory();
- BasicHttpProcessor httpproc = new BasicHttpProcessor();
- httpproc.addInterceptor(new RequestContent());
- httpproc.addInterceptor(new RequestTargetHost());
- httpproc.addInterceptor(new RequestConnControl());
- httpproc.addInterceptor(new RequestUserAgent());
- httpproc.addInterceptor(new RequestExpectContinue());
- this.httpProcessor = httpproc;
- this.inbuf = ByteBuffer.allocateDirect(2048);
- this.connStrategy = new DefaultConnectionReuseStrategy();
+ public void initalizeContext(final HttpContext context, final Object attachment) {
+ HttpHost targetHost = (HttpHost) attachment;
+ context.setAttribute(HttpExecutionContext.HTTP_TARGET_HOST, targetHost);
}
-
- private void shutdownConnection(final HttpConnection conn) {
- try {
- conn.shutdown();
- } catch (IOException ignore) {
+
+ public HttpRequest submitRequest(final HttpContext context) {
+ HttpHost targetHost = (HttpHost) context.getAttribute(
+ HttpExecutionContext.HTTP_TARGET_HOST);
+ Integer countObj = (Integer) context.getAttribute(
+ "request-count");
+ int counter = 0;
+ if (countObj != null) {
+ counter = countObj.intValue();
+ }
+ counter++;
+ context.setAttribute("request-count", new Integer(counter));
+ if (counter < 3) {
+ System.out.println("--------------");
+ System.out.println("Sending request to " + targetHost);
+ System.out.println("--------------");
+ return new HttpGet("/");
+ } else {
+ // Return null to terminate the connection
+ return null;
}
}
- public void connected(final NHttpClientConnection conn, final Object attachment) {
+ public void handleResponse(final HttpResponse response, final HttpContext context) {
+ HttpEntity entity = response.getEntity();
try {
- HttpContext context = conn.getContext();
-
- HttpHost targetHost = (HttpHost) attachment;
-
- context.setAttribute(HttpExecutionContext.HTTP_CONNECTION, conn);
- context.setAttribute(HttpExecutionContext.HTTP_TARGET_HOST, targetHost);
+ String content = EntityUtils.toString(entity);
- HttpRequest request = this.requestFactory.newHttpRequest("GET", "/");
- request.getParams().setDefaults(this.params);
-
- this.httpProcessor.process(request, context);
-
- conn.submitRequest(request);
-
- context.setAttribute(HttpExecutionContext.HTTP_REQUEST, request);
-
+ System.out.println("--------------");
+ System.out.println(response.getStatusLine());
+ System.out.println("--------------");
+ System.out.println("Document length: " + content.length());
+ System.out.println("--------------");
} catch (IOException ex) {
- shutdownConnection(conn);
System.err.println("I/O error: " + ex.getMessage());
- } catch (HttpException ex) {
- shutdownConnection(conn);
- System.err.println("Unexpected HTTP protocol error: " + ex.getMessage());
- }
- }
-
- public void closed(final NHttpClientConnection conn) {
- System.out.println("Connection closed");
- this.connCount++;
- if (this.connCount >= this.reqs.length) {
- System.exit(0);
}
}
+
+ }
+
+ static class EventLogger implements EventListener {
- public void exception(final NHttpClientConnection conn, final HttpException ex) {
- System.err.println("HTTP protocol error: " + ex.getMessage());
- shutdownConnection(conn);
- }
-
- public void exception(final NHttpClientConnection conn, final IOException ex) {
- System.err.println("I/O error: " + ex.getMessage());
- shutdownConnection(conn);
+ public void connectionOpen(final InetAddress address) {
+ System.out.println("Connection open: " + address);
}
- public void inputReady(final NHttpClientConnection conn, final ContentDecoder decoder) {
- HttpResponse response = conn.getHttpResponse();
- HttpContext context = conn.getContext();
- HttpHost targetHost = (HttpHost) context
- .getAttribute(HttpExecutionContext.HTTP_TARGET_HOST);
- WritableByteChannel channel = (WritableByteChannel) context
- .getAttribute("in-channel");
-
- try {
- while (decoder.read(this.inbuf) > 0) {
- this.inbuf.flip();
- channel.write(this.inbuf);
- this.inbuf.compact();
- }
- if (decoder.isCompleted()) {
- HttpEntity entity = response.getEntity();
-
- ByteArrayOutputStream bytestream = (ByteArrayOutputStream) context
- .getAttribute("in-buffer");
- byte[] content = bytestream.toByteArray();
-
- String charset = EntityUtils.getContentCharSet(entity);
- if (charset == null) {
- charset = HTTP.DEFAULT_CONTENT_CHARSET;
- }
-
- System.out.println("--------------");
- System.out.println("Target: " + targetHost);
- System.out.println("--------------");
- System.out.println(response.getStatusLine());
- System.out.println("--------------");
- System.out.println(new String(content, charset));
- System.out.println("--------------");
-
- if (!this.connStrategy.keepAlive(response, context)) {
- conn.close();
- }
- }
-
- } catch (IOException ex) {
- shutdownConnection(conn);
- System.err.println("I/O error: " + ex.getMessage());
- }
+ public void connectionTimeout(final InetAddress address) {
+ System.out.println("Connection timed out: " + address);
}
- public void outputReady(final NHttpClientConnection conn, final ContentEncoder encoder) {
+ public void connectionClosed(InetAddress address) {
+ System.out.println("Connection closed: " + address);
}
- public void responseReceived(final NHttpClientConnection conn) {
- HttpResponse response = conn.getHttpResponse();
-
- if (response.getStatusLine().getStatusCode() >= 200) {
- ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
- WritableByteChannel channel = Channels.newChannel(bytestream);
-
- HttpContext context = conn.getContext();
- context.setAttribute("in-buffer", bytestream);
- context.setAttribute("in-channel", channel);
- }
+ public void fatalIOException(IOException ex) {
+ System.err.println("I/O error: " + ex.getMessage());
}
- public void timeout(final NHttpClientConnection conn) {
- System.err.println("Timeout");
- shutdownConnection(conn);
+ public void fatalProtocolException(HttpException ex) {
+ System.err.println("HTTP error: " + ex.getMessage());
}
- }
-
+ }
+
}
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpClientHandler.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpClientHandler.java?view=diff&rev=499542&r1=499541&r2=499542
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpClientHandler.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/NHttpClientHandler.java Wed Jan 24 11:40:55 2007
@@ -52,6 +52,15 @@
void connected(NHttpClientConnection conn, Object attachment);
/**
+ * Triggered when the connection is ready to send an HTTP request.
+ *
+ * @see NHttpClientConnection
+ *
+ * @param conn HTTP connection that contains an HTTP response
+ */
+ void requestReady(NHttpClientConnection conn);
+
+ /**
* Triggered when an HTTP response is received. The connection
* passed as a parameter to this method is guaranteed to return
* a valid HTTP response object.
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/DefaultNHttpClientConnection.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/DefaultNHttpClientConnection.java?view=diff&rev=499542&r1=499541&r2=499542
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/DefaultNHttpClientConnection.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/DefaultNHttpClientConnection.java Wed Jan 24 11:40:55 2007
@@ -150,6 +150,10 @@
// Finally set buffered output flag
this.hasBufferedOutput = this.contentEncoder != null && this.outbuf.hasData();
}
+
+ if (this.request == null && !this.closed) {
+ handler.requestReady(this);
+ }
}
public void submitRequest(final HttpRequest request) throws HttpException {
@@ -179,8 +183,8 @@
if (request instanceof HttpEntityEnclosingRequest) {
prepareEncoder(request);
+ this.request = request;
}
- this.request = request;
this.session.setEvent(EventMask.WRITE);
}
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java?view=diff&rev=499542&r1=499541&r2=499542
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java Wed Jan 24 11:40:55 2007
@@ -134,27 +134,19 @@
}
public void requestInput() {
- if (this.contentDecoder != null) {
- this.session.setEvent(EventMask.READ);
- }
+ this.session.setEvent(EventMask.READ);
}
public void requestOutput() {
- if (this.contentEncoder != null) {
- this.session.setEvent(EventMask.WRITE);
- }
+ this.session.setEvent(EventMask.WRITE);
}
public void suspendInput() {
- if (this.contentDecoder != null) {
- this.session.clearEvent(EventMask.READ);
- }
+ this.session.clearEvent(EventMask.READ);
}
public void suspendOutput() {
- if (this.contentEncoder != null) {
- this.session.clearEvent(EventMask.WRITE);
- }
+ this.session.clearEvent(EventMask.WRITE);
}
protected HttpEntity prepareDecoder(final HttpMessage message) throws HttpException {
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/entity/BufferedContent.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/entity/BufferedContent.java?view=diff&rev=499542&r1=499541&r2=499542
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/entity/BufferedContent.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/entity/BufferedContent.java Wed Jan 24 11:40:55 2007
@@ -34,6 +34,7 @@
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpResponse;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.nio.impl.ContentInputBuffer;
@@ -47,6 +48,7 @@
if (entity == null) {
throw new IllegalArgumentException("HTTP entity may not be null");
}
+ this.wrappedEntity = entity;
setContent(new ContentInputStream(buffer));
}
@@ -72,8 +74,22 @@
if (request == null) {
throw new IllegalArgumentException("HTTP request may not be null");
}
- BufferedContent entity = new BufferedContent(request.getEntity(), buffer);
- request.setEntity(entity);
+ if (request.getEntity() != null) {
+ BufferedContent entity = new BufferedContent(request.getEntity(), buffer);
+ request.setEntity(entity);
+ }
+ }
+
+ public static void wrapEntity(
+ final HttpResponse response,
+ final ContentInputBuffer buffer) {
+ if (response == null) {
+ throw new IllegalArgumentException("HTTP response may not be null");
+ }
+ if (response.getEntity() != null) {
+ BufferedContent entity = new BufferedContent(response.getEntity(), buffer);
+ response.setEntity(entity);
+ }
}
}
Added: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java?view=auto&rev=499542
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java (added)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java Wed Jan 24 11:40:55 2007
@@ -0,0 +1,353 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * 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.nio.protocol;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetAddress;
+
+import org.apache.http.ConnectionReuseStrategy;
+import org.apache.http.HttpConnection;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpException;
+import org.apache.http.HttpInetConnection;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.nio.ContentDecoder;
+import org.apache.http.nio.ContentEncoder;
+import org.apache.http.nio.NHttpClientConnection;
+import org.apache.http.nio.NHttpClientHandler;
+import org.apache.http.nio.impl.InputBuffer;
+import org.apache.http.nio.impl.OutputBuffer;
+import org.apache.http.nio.impl.entity.BufferedContent;
+import org.apache.http.nio.impl.entity.ContentOutputStream;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpExecutionContext;
+import org.apache.http.protocol.HttpProcessor;
+
+/**
+ * HTTP client handler implementation that buffers the content of HTTP messages
+ * entirely in memory and executes HTTP requests on the main I/O thread.
+ *
+ * <p>This service handler should be used only when dealing with HTTP messages
+ * that are known to be limited in length</p>
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ */
+public class BufferingHttpClientHandler implements NHttpClientHandler {
+
+ private static final String IN_BUF = "http.nio.in-buffer";
+ private static final String OUT_BUF = "http.nio.out-buffer";
+
+ private HttpParams params;
+ private HttpProcessor httpProcessor;
+ private HttpRequestExecutionHandler execHandler;
+ private ConnectionReuseStrategy connStrategy;
+ private EventListener eventListener;
+
+ public BufferingHttpClientHandler(
+ final HttpProcessor httpProcessor,
+ final HttpRequestExecutionHandler execHandler,
+ final ConnectionReuseStrategy connStrategy,
+ final HttpParams params) {
+ super();
+ if (httpProcessor == null) {
+ throw new IllegalArgumentException("HTTP processor may not be null.");
+ }
+ if (execHandler == null) {
+ throw new IllegalArgumentException("HTTP request execution handler may not be null.");
+ }
+ if (connStrategy == null) {
+ throw new IllegalArgumentException("Connection reuse strategy may not be null");
+ }
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ this.httpProcessor = httpProcessor;
+ this.execHandler = execHandler;
+ this.connStrategy = connStrategy;
+ this.params = params;
+ }
+
+ public void setEventListener(final EventListener eventListener) {
+ this.eventListener = eventListener;
+ }
+
+ private void shutdownConnection(final HttpConnection conn) {
+ try {
+ conn.shutdown();
+ } catch (IOException ignore) {
+ }
+ }
+
+ public void connected(final NHttpClientConnection conn, final Object attachment) {
+ HttpContext context = conn.getContext();
+
+ initialize(conn, attachment);
+
+ InputBuffer inbuffer = new InputBuffer(2048);
+ OutputBuffer outbuffer = new OutputBuffer(2048);
+
+ context.setAttribute(IN_BUF, inbuffer);
+ context.setAttribute(OUT_BUF, outbuffer);
+
+ if (this.eventListener != null) {
+ InetAddress address = null;
+ if (conn instanceof HttpInetConnection) {
+ address = ((HttpInetConnection) conn).getRemoteAddress();
+ }
+ this.eventListener.connectionOpen(address);
+ }
+
+ requestReady(conn);
+ }
+
+ public void closed(final NHttpClientConnection conn) {
+ if (this.eventListener != null) {
+ InetAddress address = null;
+ if (conn instanceof HttpInetConnection) {
+ address = ((HttpInetConnection) conn).getRemoteAddress();
+ }
+ this.eventListener.connectionClosed(address);
+ }
+ }
+
+ public void exception(final NHttpClientConnection conn, final HttpException ex) {
+ shutdownConnection(conn);
+ if (this.eventListener != null) {
+ this.eventListener.fatalProtocolException(ex);
+ }
+ }
+
+ public void exception(final NHttpClientConnection conn, final IOException ex) {
+ shutdownConnection(conn);
+ if (this.eventListener != null) {
+ this.eventListener.fatalIOException(ex);
+ }
+ }
+
+ public void requestReady(final NHttpClientConnection conn) {
+ HttpContext context = conn.getContext();
+
+ OutputBuffer outbuffer = (OutputBuffer) context.getAttribute(OUT_BUF);
+
+ try {
+
+ submitRequest(conn, outbuffer);
+
+ } catch (IOException ex) {
+ shutdownConnection(conn);
+ if (this.eventListener != null) {
+ this.eventListener.fatalIOException(ex);
+ }
+ } catch (HttpException ex) {
+ shutdownConnection(conn);
+ if (this.eventListener != null) {
+ this.eventListener.fatalProtocolException(ex);
+ }
+ }
+ }
+
+ public void inputReady(final NHttpClientConnection conn, final ContentDecoder decoder) {
+ HttpContext context = conn.getContext();
+
+ InputBuffer inbuffer = (InputBuffer) context.getAttribute(IN_BUF);
+ OutputBuffer outbuffer = (OutputBuffer) context.getAttribute(OUT_BUF);
+
+ try {
+
+ inbuffer.consumeContent(decoder);
+ if (decoder.isCompleted()) {
+
+ processResponse(conn, inbuffer);
+ // Clean up buffers just in case
+ inbuffer.clear();
+ outbuffer.clear();
+ // Ready for another request
+ conn.requestOutput();
+ }
+
+ } catch (IOException ex) {
+ shutdownConnection(conn);
+ if (this.eventListener != null) {
+ this.eventListener.fatalIOException(ex);
+ }
+ } catch (HttpException ex) {
+ shutdownConnection(conn);
+ if (this.eventListener != null) {
+ this.eventListener.fatalProtocolException(ex);
+ }
+ }
+ }
+
+ public void outputReady(final NHttpClientConnection conn, final ContentEncoder encoder) {
+ HttpContext context = conn.getContext();
+ OutputBuffer outbuffer = (OutputBuffer) context.getAttribute(OUT_BUF);
+
+ try {
+
+ outbuffer.produceContent(encoder);
+
+ } catch (IOException ex) {
+ shutdownConnection(conn);
+ if (this.eventListener != null) {
+ this.eventListener.fatalIOException(ex);
+ }
+ }
+ }
+
+ public void responseReceived(final NHttpClientConnection conn) {
+ HttpContext context = conn.getContext();
+ HttpResponse response = conn.getHttpResponse();
+ HttpRequest request = (HttpRequest) context.getAttribute(
+ HttpExecutionContext.HTTP_REQUEST);
+
+ InputBuffer inbuffer = (InputBuffer) context.getAttribute(IN_BUF);
+ OutputBuffer outbuffer = (OutputBuffer) context.getAttribute(OUT_BUF);
+
+ if (response.getStatusLine().getStatusCode() < HttpStatus.SC_OK) {
+ // Just ignore 1xx responses;
+ return;
+ }
+
+ if (!canResponseHaveBody(request, response)) {
+ try {
+
+ processResponse(conn, inbuffer);
+ // Clean up buffers just in case
+ inbuffer.clear();
+ outbuffer.clear();
+ // Ready for another request
+ conn.requestOutput();
+
+ } catch (IOException ex) {
+ shutdownConnection(conn);
+ if (this.eventListener != null) {
+ this.eventListener.fatalIOException(ex);
+ }
+ } catch (HttpException ex) {
+ shutdownConnection(conn);
+ if (this.eventListener != null) {
+ this.eventListener.fatalProtocolException(ex);
+ }
+ }
+ }
+ }
+
+ public void timeout(final NHttpClientConnection conn) {
+ shutdownConnection(conn);
+ if (this.eventListener != null) {
+ InetAddress address = null;
+ if (conn instanceof HttpInetConnection) {
+ address = ((HttpInetConnection) conn).getRemoteAddress();
+ }
+ this.eventListener.connectionTimeout(address);
+ }
+ }
+
+ private void initialize(
+ final NHttpClientConnection conn,
+ final Object attachment) {
+ HttpContext context = conn.getContext();
+
+ context.setAttribute(HttpExecutionContext.HTTP_CONNECTION, conn);
+ this.execHandler.initalizeContext(context, attachment);
+ }
+
+ private void submitRequest(
+ final NHttpClientConnection conn,
+ final OutputBuffer outbuffer) throws IOException, HttpException {
+
+ HttpContext context = conn.getContext();
+ HttpRequest request = this.execHandler.submitRequest(context);
+ if (request == null) {
+ return;
+ }
+
+ request.getParams().setDefaults(this.params);
+
+ context.setAttribute(HttpExecutionContext.HTTP_REQUEST, request);
+
+ this.httpProcessor.process(request, context);
+
+ conn.submitRequest(request);
+
+ if (request instanceof HttpEntityEnclosingRequest) {
+ HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
+ if (entity != null) {
+ OutputStream outstream = new ContentOutputStream(outbuffer);
+ entity.writeTo(outstream);
+ outstream.flush();
+ }
+ }
+
+ }
+
+ protected boolean canResponseHaveBody(
+ final HttpRequest request, final HttpResponse response) {
+
+ if ("HEAD".equalsIgnoreCase(request.getRequestLine().getMethod())) {
+ return false;
+ }
+
+ int status = response.getStatusLine().getStatusCode();
+ return status >= HttpStatus.SC_OK
+ && status != HttpStatus.SC_NO_CONTENT
+ && status != HttpStatus.SC_NOT_MODIFIED
+ && status != HttpStatus.SC_RESET_CONTENT;
+ }
+
+ private void processResponse(
+ final NHttpClientConnection conn,
+ final InputBuffer inbuffer) throws IOException, HttpException {
+
+ HttpContext context = conn.getContext();
+ HttpResponse response = conn.getHttpResponse();
+ // Create a wrapper entity instead of the original one
+ BufferedContent.wrapEntity(response, inbuffer);
+
+ context.setAttribute(HttpExecutionContext.HTTP_RESPONSE, response);
+
+ this.httpProcessor.process(response, context);
+
+ this.execHandler.handleResponse(response, context);
+
+ if (!this.connStrategy.keepAlive(response, context)) {
+ conn.close();
+ }
+
+ }
+}
\ No newline at end of file
Propchange: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpServiceHandler.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpServiceHandler.java?view=diff&rev=499542&r1=499541&r2=499542
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpServiceHandler.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpServiceHandler.java Wed Jan 24 11:40:55 2007
@@ -367,9 +367,11 @@
if (response.getEntity() != null) {
HttpEntity entity = response.getEntity();
- OutputStream outstream = new ContentOutputStream(outbuffer);
- entity.writeTo(outstream);
- outstream.flush();
+ if (entity != null) {
+ OutputStream outstream = new ContentOutputStream(outbuffer);
+ entity.writeTo(outstream);
+ outstream.flush();
+ }
}
}
Added: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/HttpRequestExecutionHandler.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/HttpRequestExecutionHandler.java?view=auto&rev=499542
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/HttpRequestExecutionHandler.java (added)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/HttpRequestExecutionHandler.java Wed Jan 24 11:40:55 2007
@@ -0,0 +1,87 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * 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.nio.protocol;
+
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.nio.reactor.ConnectingIOReactor;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * HTTP request execution handler can be used by client-side protocol handlers
+ * to trigger the submission of a new HTTP request and the processing of an
+ * HTTP response.
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ */
+public interface HttpRequestExecutionHandler {
+
+ /**
+ * Triggered when a new connection has been established and the
+ * HTTP context needs to be initialized.
+ *
+ * <p>The attachment object is the same object which was passed
+ * to the connecting I/O reactor when the connection request was
+ * made. The attachment may optionally contain some state information
+ * required in order to correctly initalize the HTTP context.
+ *
+ * @see ConnectingIOReactor#connect(java.net.SocketAddress, java.net.SocketAddress, Object)
+ *
+ * @param context the actual HTTP context
+ * @param attachment the object passed to the connecting I/O reactor
+ * upon the request for a new connection.
+ */
+ void initalizeContext(HttpContext context, Object attachment);
+
+ /**
+ * Triggered when the underlying connection is ready to send a new
+ * HTTP request to the target host. This method may return
+ * <code>null</null> if the client is not yet ready to send a
+ * request. In this case the connection will remain open and
+ * can be activated at a later point.
+ *
+ * @param context the actual HTTP context
+ * @return an HTTP request to be sent or <code>null</null> if no
+ * request needs to be sent
+ */
+ HttpRequest submitRequest(HttpContext context);
+
+ /**
+ * Triggered when an HTTP response is ready to be processed.
+ *
+ * @param response the HTTP response to be processed
+ * @param context the actual HTTP context
+ */
+ void handleResponse(HttpResponse response, HttpContext context);
+
+}
Propchange: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/HttpRequestExecutionHandler.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/HttpRequestExecutionHandler.java
------------------------------------------------------------------------------
svn:mime-type = text/plain