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 2011/04/29 13:10:23 UTC

svn commit: r1097769 - in /httpcomponents/httpasyncclient/trunk: ./ httpasyncclient/ httpasyncclient/src/examples/org/apache/http/examples/nio/client/ httpasyncclient/src/main/java/org/apache/http/impl/nio/client/ httpasyncclient/src/main/java/org/apac...

Author: olegk
Date: Fri Apr 29 11:10:23 2011
New Revision: 1097769

URL: http://svn.apache.org/viewvc?rev=1097769&view=rev
Log:
Zero copy request producers / response consumers

Added:
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/examples/org/apache/http/examples/nio/client/ZeroCopyHttpExchange.java   (with props)
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseZeroCopyRequestProducer.java   (with props)
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyConsumer.java   (with props)
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPost.java   (with props)
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPut.java   (with props)
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestZeroCopy.java   (with props)
Modified:
    httpcomponents/httpasyncclient/trunk/httpasyncclient/pom.xml
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/DefaultAsyncRequestDirector.java
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/HttpAsyncResponseConsumer.java
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/AbstractHttpAsyncResponseConsumer.java
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseHttpAsyncEntityRequestProducer.java
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/HttpAsyncPost.java
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/HttpAsyncPut.java
    httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestAsyncConsumers.java
    httpcomponents/httpasyncclient/trunk/pom.xml

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/pom.xml
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/pom.xml?rev=1097769&r1=1097768&r2=1097769&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/pom.xml (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/pom.xml Fri Apr 29 11:10:23 2011
@@ -67,6 +67,18 @@
       <version>${junit.version}</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>${commons-io.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <version>${mockito.version}</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <properties>

Added: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/examples/org/apache/http/examples/nio/client/ZeroCopyHttpExchange.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/examples/org/apache/http/examples/nio/client/ZeroCopyHttpExchange.java?rev=1097769&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/examples/org/apache/http/examples/nio/client/ZeroCopyHttpExchange.java (added)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/examples/org/apache/http/examples/nio/client/ZeroCopyHttpExchange.java Fri Apr 29 11:10:23 2011
@@ -0,0 +1,70 @@
+/*
+ * ====================================================================
+ * 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.examples.nio.client;
+
+import java.io.File;
+import java.util.concurrent.Future;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
+import org.apache.http.nio.client.HttpAsyncClient;
+import org.apache.http.nio.client.methods.ZeroCopyConsumer;
+import org.apache.http.nio.client.methods.ZeroCopyPost;
+
+public class ZeroCopyHttpExchange {
+
+    public static void main(String[] args) throws Exception {
+        HttpAsyncClient httpclient = new DefaultHttpAsyncClient();
+        httpclient.start();
+        try {
+            File upload = new File(args[0]);
+            File download = new File(args[1]);
+            ZeroCopyPost httpost = new ZeroCopyPost("http://localhost:8080/", upload, "text/plain");
+            ZeroCopyConsumer<File> consumer = new ZeroCopyConsumer<File>(download) {
+
+                @Override
+                protected File process(final HttpResponse response, final File file) throws Exception {
+                    if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
+                        throw new ClientProtocolException("Upload failed: " + response.getStatusLine());
+                    }
+                    return file;
+                }
+
+            };
+            Future<File> future = httpclient.execute(httpost, consumer, null);
+            File result = future.get();
+            System.out.println("Response file length: " + result.length());
+            System.out.println("Shutting down");
+        } finally {
+            httpclient.shutdown();
+        }
+        System.out.println("Done");
+    }
+
+}

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/examples/org/apache/http/examples/nio/client/ZeroCopyHttpExchange.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/examples/org/apache/http/examples/nio/client/ZeroCopyHttpExchange.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/examples/org/apache/http/examples/nio/client/ZeroCopyHttpExchange.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/DefaultAsyncRequestDirector.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/DefaultAsyncRequestDirector.java?rev=1097769&r1=1097768&r2=1097769&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/DefaultAsyncRequestDirector.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/DefaultAsyncRequestDirector.java Fri Apr 29 11:10:23 2011
@@ -336,7 +336,13 @@ class DefaultAsyncRequestDirector<T> imp
             if (this.finalResponse != null) {
                 this.responseConsumer.responseCompleted();
                 this.log.debug("Response processed");
-                this.resultCallback.completed(this.responseConsumer.getResult(), this);
+                T result = this.responseConsumer.getResult();
+                Exception ex = this.responseConsumer.getException();
+                if (ex == null) {
+                    this.resultCallback.completed(result, this);
+                } else {
+                    this.resultCallback.failed(ex, this);
+                }
                 releaseResources();
             } else {
                 if (this.followup != null) {
@@ -382,6 +388,10 @@ class DefaultAsyncRequestDirector<T> imp
         return this.responseConsumer.getResult();
     }
 
+    public Exception getException() {
+        return this.responseConsumer.getException();
+    }
+
     private synchronized void connectionRequestCompleted(final ManagedClientConnection conn) {
         if (this.log.isDebugEnabled()) {
             this.log.debug("Connection request suceeded: " + conn);

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/HttpAsyncResponseConsumer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/HttpAsyncResponseConsumer.java?rev=1097769&r1=1097768&r2=1097769&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/HttpAsyncResponseConsumer.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/HttpAsyncResponseConsumer.java Fri Apr 29 11:10:23 2011
@@ -47,4 +47,6 @@ public interface HttpAsyncResponseConsum
 
     T getResult();
 
+    Exception getException();
+
 }

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/AbstractHttpAsyncResponseConsumer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/AbstractHttpAsyncResponseConsumer.java?rev=1097769&r1=1097768&r2=1097769&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/AbstractHttpAsyncResponseConsumer.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/AbstractHttpAsyncResponseConsumer.java Fri Apr 29 11:10:23 2011
@@ -79,7 +79,7 @@ public abstract class AbstractHttpAsyncR
         try {
             this.result = buildResult();
         } catch (Exception ex) {
-            failed(ex);
+            this.ex = ex;
         } finally {
             releaseResources();
         }

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseHttpAsyncEntityRequestProducer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseHttpAsyncEntityRequestProducer.java?rev=1097769&r1=1097768&r2=1097769&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseHttpAsyncEntityRequestProducer.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseHttpAsyncEntityRequestProducer.java Fri Apr 29 11:10:23 2011
@@ -27,7 +27,6 @@
 package org.apache.http.nio.client.methods;
 
 import java.io.Closeable;
-import java.io.File;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
@@ -42,7 +41,6 @@ import org.apache.http.nio.ContentEncode
 import org.apache.http.nio.IOControl;
 import org.apache.http.nio.client.HttpAsyncRequestProducer;
 import org.apache.http.nio.entity.NByteArrayEntity;
-import org.apache.http.nio.entity.NFileEntity;
 import org.apache.http.nio.entity.NStringEntity;
 import org.apache.http.nio.entity.ProducingNHttpEntity;
 import org.apache.http.protocol.HTTP;
@@ -86,16 +84,6 @@ abstract class BaseHttpAsyncEntityReques
         this.producer = entity;
     }
 
-    protected BaseHttpAsyncEntityRequestProducer(
-            final URI requestURI, final File content, final String contentType) {
-        super();
-        if (requestURI == null) {
-            throw new IllegalArgumentException("Request URI may not be null");
-        }
-        this.requestURI = requestURI;
-        this.producer = new NFileEntity(content, contentType);
-    }
-
     protected abstract HttpEntityEnclosingRequest createRequest(final URI requestURI, final HttpEntity entity);
 
     public HttpRequest generateRequest() throws IOException, HttpException {

Added: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseZeroCopyRequestProducer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseZeroCopyRequestProducer.java?rev=1097769&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseZeroCopyRequestProducer.java (added)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseZeroCopyRequestProducer.java Fri Apr 29 11:10:23 2011
@@ -0,0 +1,130 @@
+/*
+ * ====================================================================
+ * 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.client.methods;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.channels.FileChannel;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.client.utils.URIUtils;
+import org.apache.http.entity.BasicHttpEntity;
+import org.apache.http.nio.ContentEncoder;
+import org.apache.http.nio.ContentEncoderChannel;
+import org.apache.http.nio.FileContentEncoder;
+import org.apache.http.nio.IOControl;
+import org.apache.http.nio.client.HttpAsyncRequestProducer;
+
+abstract class BaseZeroCopyRequestProducer implements HttpAsyncRequestProducer, Closeable {
+
+    private final URI requestURI;
+    private final File file;
+    private final String contentType;
+
+    private FileChannel fileChannel;
+    private long idx = -1;
+
+    protected BaseZeroCopyRequestProducer(
+            final URI requestURI, final File file, final String contentType) {
+        super();
+        if (requestURI == null) {
+            throw new IllegalArgumentException("Request URI may not be null");
+        }
+        if (file == null) {
+            throw new IllegalArgumentException("Source file may not be null");
+        }
+        this.requestURI = requestURI;
+        this.file = file;
+        this.contentType = contentType;
+    }
+
+    protected abstract HttpEntityEnclosingRequest createRequest(final URI requestURI, final HttpEntity entity);
+
+    public HttpRequest generateRequest() throws IOException, HttpException {
+        BasicHttpEntity entity = new BasicHttpEntity();
+        entity.setChunked(false);
+        entity.setContentLength(this.file.length());
+        entity.setContentType(this.contentType);
+        return createRequest(this.requestURI, entity);
+    }
+
+    public synchronized HttpHost getTarget() {
+        return URIUtils.extractHost(this.requestURI);
+    }
+
+    public synchronized void produceContent(
+            final ContentEncoder encoder, final IOControl ioctrl) throws IOException {
+        if (this.fileChannel == null) {
+            FileInputStream in = new FileInputStream(this.file);
+            this.fileChannel = in.getChannel();
+            this.idx = 0;
+        }
+        long transferred;
+        if (encoder instanceof FileContentEncoder) {
+            transferred = ((FileContentEncoder)encoder).transfer(
+                    this.fileChannel, this.idx, Integer.MAX_VALUE);
+        } else {
+            transferred = this.fileChannel.transferTo(
+                    this.idx, Integer.MAX_VALUE, new ContentEncoderChannel(encoder));
+        }
+        if (transferred > 0) {
+            this.idx += transferred;
+        }
+
+        if (this.idx >= this.fileChannel.size()) {
+            encoder.complete();
+            this.fileChannel.close();
+            this.fileChannel = null;
+        }
+    }
+
+    public synchronized boolean isRepeatable() {
+        return true;
+    }
+
+    public synchronized void resetRequest() {
+        try {
+            close();
+        } catch (IOException ignore) {
+        }
+    }
+
+    public synchronized void close() throws IOException {
+        if (this.fileChannel != null) {
+            this.fileChannel.close();
+            this.fileChannel = null;
+        }
+    }
+
+}

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseZeroCopyRequestProducer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseZeroCopyRequestProducer.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/BaseZeroCopyRequestProducer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/HttpAsyncPost.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/HttpAsyncPost.java?rev=1097769&r1=1097768&r2=1097769&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/HttpAsyncPost.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/HttpAsyncPost.java Fri Apr 29 11:10:23 2011
@@ -26,7 +26,6 @@
  */
 package org.apache.http.nio.client.methods;
 
-import java.io.File;
 import java.net.URI;
 
 import org.apache.http.HttpEntity;
@@ -39,10 +38,6 @@ public class HttpAsyncPost extends BaseH
         super(requestURI, content, contentType);
     }
 
-    public HttpAsyncPost(final URI requestURI, final File content, final String contentType) {
-        super(requestURI, content, contentType);
-    }
-
     public HttpAsyncPost(final URI requestURI, final String content, String mimeType, String charset) {
         super(requestURI, content, mimeType, charset);
     }
@@ -55,10 +50,6 @@ public class HttpAsyncPost extends BaseH
         super(URI.create(requestURI), content, contentType);
     }
 
-    public HttpAsyncPost(final String requestURI, final File content, final String contentType) {
-        super(URI.create(requestURI), content, contentType);
-    }
-
     public HttpAsyncPost(final String requestURI, final String content, String mimeType, String charset) {
         super(URI.create(requestURI), content, mimeType, charset);
     }

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/HttpAsyncPut.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/HttpAsyncPut.java?rev=1097769&r1=1097768&r2=1097769&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/HttpAsyncPut.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/HttpAsyncPut.java Fri Apr 29 11:10:23 2011
@@ -26,7 +26,6 @@
  */
 package org.apache.http.nio.client.methods;
 
-import java.io.File;
 import java.net.URI;
 
 import org.apache.http.HttpEntity;
@@ -39,10 +38,6 @@ public class HttpAsyncPut extends BaseHt
         super(requestURI, content, contentType);
     }
 
-    public HttpAsyncPut(final URI requestURI, final File content, final String contentType) {
-        super(requestURI, content, contentType);
-    }
-
     public HttpAsyncPut(final URI requestURI, final String content, String mimeType, String charset) {
         super(requestURI, content, mimeType, charset);
     }
@@ -55,10 +50,6 @@ public class HttpAsyncPut extends BaseHt
         super(URI.create(requestURI), content, contentType);
     }
 
-    public HttpAsyncPut(final String requestURI, final File content, final String contentType) {
-        super(URI.create(requestURI), content, contentType);
-    }
-
     public HttpAsyncPut(final String requestURI, final String content, String mimeType, String charset) {
         super(URI.create(requestURI), content, mimeType, charset);
     }

Added: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyConsumer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyConsumer.java?rev=1097769&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyConsumer.java (added)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyConsumer.java Fri Apr 29 11:10:23 2011
@@ -0,0 +1,104 @@
+/*
+ * ====================================================================
+ * 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.client.methods;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.nio.ContentDecoder;
+import org.apache.http.nio.ContentDecoderChannel;
+import org.apache.http.nio.FileContentDecoder;
+import org.apache.http.nio.IOControl;
+
+public abstract class ZeroCopyConsumer<T> extends AbstractHttpAsyncResponseConsumer<T> {
+
+    private final File file;
+
+    private HttpResponse response;
+    private FileChannel fileChannel;
+    private long idx = -1;
+
+    public ZeroCopyConsumer(final File file) {
+        super();
+        if (file == null) {
+            throw new IllegalArgumentException("File may nor be null");
+        }
+        this.file = file;
+    }
+
+    @Override
+    protected void onResponseReceived(final HttpResponse response) {
+        this.response = response;
+    }
+
+    @Override
+    protected void onContentReceived(
+            final ContentDecoder decoder, final IOControl ioctrl) throws IOException {
+        if (this.fileChannel == null) {
+            FileOutputStream out = new FileOutputStream(this.file);
+            this.fileChannel = out.getChannel();
+            this.idx = 0;
+        }
+        long transferred;
+        if (decoder instanceof FileContentDecoder) {
+            transferred = ((FileContentDecoder)decoder).transfer(
+                    this.fileChannel, this.idx, Integer.MAX_VALUE);
+        } else {
+            transferred = this.fileChannel.transferFrom(
+                    new ContentDecoderChannel(decoder), this.idx, Integer.MAX_VALUE);
+        }
+        if (transferred > 0) {
+            this.idx += transferred;
+        }
+        if (decoder.isCompleted()) {
+            this.fileChannel.close();
+            this.fileChannel = null;
+        }
+    }
+
+    protected abstract T process(final HttpResponse response, final File file) throws Exception;
+
+    @Override
+    protected T buildResult() throws Exception {
+        return process(this.response, this.file);
+    }
+
+    @Override
+    protected void onCleanup() {
+        if (this.fileChannel != null) {
+            try {
+                this.fileChannel.close();
+            } catch (IOException ignore) {
+            }
+            this.fileChannel = null;
+        }
+    }
+
+}

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyConsumer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyConsumer.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyConsumer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPost.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPost.java?rev=1097769&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPost.java (added)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPost.java Fri Apr 29 11:10:23 2011
@@ -0,0 +1,53 @@
+/*
+ * ====================================================================
+ * 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.client.methods;
+
+import java.io.File;
+import java.net.URI;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.client.methods.HttpPost;
+
+public class ZeroCopyPost extends BaseZeroCopyRequestProducer {
+
+    public ZeroCopyPost(final URI requestURI, final File content, final String contentType) {
+        super(requestURI, content, contentType);
+    }
+
+    public ZeroCopyPost(final String requestURI, final File content, final String contentType) {
+        super(URI.create(requestURI), content, contentType);
+    }
+
+    @Override
+    protected HttpEntityEnclosingRequest createRequest(final URI requestURI, final HttpEntity entity) {
+        HttpPost httppost = new HttpPost(requestURI);
+        httppost.setEntity(entity);
+        return httppost;
+    }
+
+}

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPost.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPost.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPost.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPut.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPut.java?rev=1097769&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPut.java (added)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPut.java Fri Apr 29 11:10:23 2011
@@ -0,0 +1,53 @@
+/*
+ * ====================================================================
+ * 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.client.methods;
+
+import java.io.File;
+import java.net.URI;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.client.methods.HttpPut;
+
+public class ZeroCopyPut extends BaseZeroCopyRequestProducer {
+
+    public ZeroCopyPut(final URI requestURI, final File content, final String contentType) {
+        super(requestURI, content, contentType);
+    }
+
+    public ZeroCopyPut(final String requestURI, final File content, final String contentType) {
+        super(URI.create(requestURI), content, contentType);
+    }
+
+    @Override
+    protected HttpEntityEnclosingRequest createRequest(final URI requestURI, final HttpEntity entity) {
+        HttpPut httpput = new HttpPut(requestURI);
+        httpput.setEntity(entity);
+        return httpput;
+    }
+
+}

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPut.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPut.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/methods/ZeroCopyPut.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestAsyncConsumers.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestAsyncConsumers.java?rev=1097769&r1=1097768&r2=1097769&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestAsyncConsumers.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestAsyncConsumers.java Fri Apr 29 11:10:23 2011
@@ -29,15 +29,18 @@ package org.apache.http.nio.client.metho
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.apache.http.HttpException;
 import org.apache.http.HttpHost;
 import org.apache.http.HttpResponse;
 import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
 import org.apache.http.impl.nio.conn.PoolingClientConnectionManager;
 import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
 import org.apache.http.localserver.ServerTestBase;
+import org.apache.http.nio.ContentDecoder;
 import org.apache.http.nio.IOControl;
 import org.apache.http.nio.client.HttpAsyncClient;
 import org.apache.http.nio.conn.scheme.Scheme;
@@ -48,6 +51,7 @@ import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 public class TestAsyncConsumers extends ServerTestBase {
 
@@ -204,4 +208,72 @@ public class TestAsyncConsumers extends 
         }
     }
 
+    @Test
+    public void testResourceReleaseOnSuccess() throws Exception {
+        StringBuilder sb = new StringBuilder();
+        for (int i= 0; i < 25; i++) {
+            sb.append("blah blah blah blah\r\n");
+            sb.append("yada yada yada yada\r\n");
+        }
+        String s = sb.toString();
+
+        this.httpclient.start();
+        HttpAsyncPost httppost = new HttpAsyncPost(this.target.toURI() + "/echo/stuff", s);
+        AsyncCharConsumer<String> consumer = Mockito.spy(new BufferingCharConsumer());
+        Future<String> future = this.httpclient.execute(httppost, consumer, null);
+        String result = future.get();
+        Assert.assertEquals(s, result);
+        Mockito.verify(consumer).responseCompleted();
+        Mockito.verify(consumer).buildResult();
+        Mockito.verify(consumer).releaseResources();
+        Mockito.verify(consumer).onCleanup();
+    }
+
+    @Test
+    public void testResourceReleaseOnException() throws Exception {
+        this.httpclient.start();
+
+        HttpAsyncPost httppost = new HttpAsyncPost(this.target.toURI() + "/echo/stuff", "stuff");
+        AsyncCharConsumer<String> consumer = Mockito.spy(new BufferingCharConsumer());
+        Mockito.doThrow(new IOException("Kaboom")).when(consumer).consumeContent(
+                Mockito.any(ContentDecoder.class), Mockito.any(IOControl.class));
+
+        Future<String> future = this.httpclient.execute(httppost, consumer, null);
+        try {
+            future.get();
+            Assert.fail("ExecutionException expected");
+        } catch (ExecutionException ex) {
+            Throwable t = ex.getCause();
+            Assert.assertNotNull(t);
+            Assert.assertTrue(t instanceof IOException);
+            Assert.assertEquals("Kaboom", t.getMessage());
+        }
+        Mockito.verify(consumer).failed(Mockito.any(IOException.class));
+        Mockito.verify(consumer).releaseResources();
+        Mockito.verify(consumer).onCleanup();
+    }
+
+    @Test
+    public void testResourceReleaseOnBuildFailure() throws Exception {
+        this.httpclient.start();
+
+        HttpAsyncPost httppost = new HttpAsyncPost(this.target.toURI() + "/echo/stuff", "stuff");
+        AsyncCharConsumer<String> consumer = Mockito.spy(new BufferingCharConsumer());
+        Mockito.doThrow(new HttpException("Kaboom")).when(consumer).buildResult();
+
+        Future<String> future = this.httpclient.execute(httppost, consumer, null);
+        try {
+            future.get();
+            Assert.fail("ExecutionException expected");
+        } catch (ExecutionException ex) {
+            Throwable t = ex.getCause();
+            Assert.assertNotNull(t);
+            Assert.assertTrue(t instanceof HttpException);
+            Assert.assertEquals("Kaboom", t.getMessage());
+        }
+        Mockito.verify(consumer).responseCompleted();
+        Mockito.verify(consumer).releaseResources();
+        Mockito.verify(consumer).onCleanup();
+    }
+
 }

Added: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestZeroCopy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestZeroCopy.java?rev=1097769&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestZeroCopy.java (added)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestZeroCopy.java Fri Apr 29 11:10:23 2011
@@ -0,0 +1,286 @@
+/*
+ * ====================================================================
+ * 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.client.methods;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.util.concurrent.Future;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.LineIterator;
+import org.apache.commons.io.output.FileWriterWithEncoding;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.BasicHttpEntity;
+import org.apache.http.entity.FileEntity;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
+import org.apache.http.impl.nio.conn.PoolingClientConnectionManager;
+import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
+import org.apache.http.localserver.ServerTestBase;
+import org.apache.http.nio.client.HttpAsyncClient;
+import org.apache.http.nio.conn.scheme.Scheme;
+import org.apache.http.nio.conn.scheme.SchemeRegistry;
+import org.apache.http.nio.reactor.ConnectingIOReactor;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.apache.http.util.EntityUtils;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestZeroCopy extends ServerTestBase {
+
+    private static final String[] TEXT = {
+        "blah blah blah blah blah blah blah blah blah blah blah blah blah blah",
+        "yada yada yada yada yada yada yada yada yada yada yada yada yada yada",
+        "da da da da da da da da da da da da da da da da da da da da da da da da",
+        "nyet nyet nyet nyet nyet nyet nyet nyet nyet nyet nyet nyet nyet nyet"
+    };
+
+    private static Charset ASCII = Charset.forName("ascii");
+    private static File TEST_FILE;
+    private File tmpfile;
+
+    private HttpHost target;
+    private PoolingClientConnectionManager sessionManager;
+    private HttpAsyncClient httpclient;
+
+    @BeforeClass
+    public static void createSrcFile() throws Exception {
+        File tmpdir = FileUtils.getTempDirectory();
+        TEST_FILE = new File(tmpdir, "src.test");
+        FileWriterWithEncoding out = new FileWriterWithEncoding(TEST_FILE, ASCII);
+        try {
+            for (int i = 0; i < 500; i++) {
+                for (String line: TEXT) {
+                    out.write(line);
+                    out.write("\r\n");
+                }
+            }
+        } finally {
+            out.close();
+        }
+    }
+
+    @AfterClass
+    public static void deleteSrcFile() throws Exception {
+        if (TEST_FILE != null) {
+            TEST_FILE.delete();
+            TEST_FILE = null;
+        }
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        int port = this.localServer.getServiceAddress().getPort();
+        this.target = new HttpHost("localhost", port);
+
+        ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(2, new BasicHttpParams());
+        SchemeRegistry schemeRegistry = new SchemeRegistry();
+        schemeRegistry.register(new Scheme("http", 80, null));
+        this.sessionManager = new PoolingClientConnectionManager(ioReactor, schemeRegistry);
+        this.httpclient = new DefaultHttpAsyncClient(this.sessionManager);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        this.httpclient.shutdown();
+        super.tearDown();
+    }
+
+    @After
+    public void cleanUp() throws Exception {
+        if (this.tmpfile != null && this.tmpfile.exists()) {
+            this.tmpfile.delete();
+        }
+    }
+
+    static class TestZeroCopyPost extends BaseZeroCopyRequestProducer {
+
+        private final boolean forceChunking;
+
+        protected TestZeroCopyPost(final String requestURI, final boolean forceChunking) {
+            super(URI.create(requestURI), TEST_FILE, "text/plain");
+            this.forceChunking = forceChunking;
+        }
+
+        @Override
+        protected HttpEntityEnclosingRequest createRequest(final URI requestURI, final HttpEntity entity) {
+            HttpPost httppost = new HttpPost(requestURI);
+            if (this.forceChunking) {
+                BasicHttpEntity chunkedEntity = new BasicHttpEntity();
+                chunkedEntity.setChunked(true);
+                httppost.setEntity(chunkedEntity);
+            } else {
+                httppost.setEntity(entity);
+            }
+            return httppost;
+        }
+
+    }
+
+    static class TestZeroCopyConsumer extends ZeroCopyConsumer<Integer> {
+
+        public TestZeroCopyConsumer(final File file) {
+            super(file);
+        }
+
+        @Override
+        protected Integer process(final HttpResponse response, final File file) throws Exception {
+            return response.getStatusLine().getStatusCode();
+        }
+
+    }
+
+    static class TestHandler implements HttpRequestHandler {
+
+        private boolean forceChunking;
+
+        TestHandler(boolean forceChunking) {
+            super();
+            this.forceChunking = forceChunking;
+        }
+
+        public void handle(
+                final HttpRequest request,
+                final HttpResponse response,
+                final HttpContext context) throws HttpException, IOException {
+            HttpEntity requestEntity = null;
+            if (request instanceof HttpEntityEnclosingRequest) {
+                requestEntity = ((HttpEntityEnclosingRequest) request).getEntity();
+            }
+            if (requestEntity == null) {
+                response.setEntity(new StringEntity("Empty content"));
+                return;
+            }
+
+            boolean ok = true;
+
+            InputStream instream = requestEntity.getContent();
+            try {
+                LineIterator it = IOUtils.lineIterator(instream,
+                        EntityUtils.getContentCharSet(requestEntity));
+                int count = 0;
+                while (it.hasNext()) {
+                    String line = it.next();
+                    int i = count % TEXT.length;
+                    String expected = TEXT[i];
+                    if (!line.equals(expected)) {
+                        ok = false;
+                        break;
+                    }
+                    count++;
+                }
+            } finally {
+                instream.close();
+            }
+            if (ok) {
+                FileEntity responseEntity = new FileEntity(TEST_FILE, "text/plian");
+                if (this.forceChunking) {
+                    responseEntity.setChunked(true);
+                }
+                response.setEntity(responseEntity);
+            } else {
+                response.setEntity(new StringEntity("Invalid content"));
+            }
+        }
+    }
+
+    @Test
+    public void testTwoWayZeroCopy() throws Exception {
+        this.localServer.register("/bounce", new TestHandler(false));
+        File tmpdir = FileUtils.getTempDirectory();
+        this.tmpfile = new File(tmpdir, "dst.test");
+        this.httpclient.start();
+        TestZeroCopyPost httppost = new TestZeroCopyPost(this.target.toURI() + "/bounce", false);
+        TestZeroCopyConsumer consumer = new TestZeroCopyConsumer(this.tmpfile);
+        Future<Integer> future = this.httpclient.execute(httppost, consumer, null);
+        Integer status = future.get();
+        Assert.assertNotNull(status);
+        Assert.assertEquals(HttpStatus.SC_OK, status.intValue());
+        InputStream instream = new FileInputStream(this.tmpfile);
+        try {
+            LineIterator it = IOUtils.lineIterator(instream, ASCII.name());
+            int count = 0;
+            while (it.hasNext()) {
+                String line = it.next();
+                int i = count % TEXT.length;
+                String expected = TEXT[i];
+                Assert.assertEquals(expected, line);
+                count++;
+            }
+        } finally {
+            instream.close();
+        }
+    }
+
+    @Test
+    public void testZeroCopyFallback() throws Exception {
+        this.localServer.register("/bounce", new TestHandler(true));
+        File tmpdir = FileUtils.getTempDirectory();
+        this.tmpfile = new File(tmpdir, "dst.test");
+        this.httpclient.start();
+        TestZeroCopyPost httppost = new TestZeroCopyPost(this.target.toURI() + "/bounce", true);
+        TestZeroCopyConsumer consumer = new TestZeroCopyConsumer(this.tmpfile);
+        Future<Integer> future = this.httpclient.execute(httppost, consumer, null);
+        Integer status = future.get();
+        Assert.assertNotNull(status);
+        Assert.assertEquals(HttpStatus.SC_OK, status.intValue());
+        InputStream instream = new FileInputStream(this.tmpfile);
+        try {
+            LineIterator it = IOUtils.lineIterator(instream, ASCII.name());
+            int count = 0;
+            while (it.hasNext()) {
+                String line = it.next();
+                int i = count % TEXT.length;
+                String expected = TEXT[i];
+                Assert.assertEquals(expected, line);
+                count++;
+            }
+        } finally {
+            instream.close();
+        }
+    }
+
+}

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestZeroCopy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestZeroCopy.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/nio/client/methods/TestZeroCopy.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpasyncclient/trunk/pom.xml
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/pom.xml?rev=1097769&r1=1097768&r2=1097769&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/pom.xml (original)
+++ httpcomponents/httpasyncclient/trunk/pom.xml Fri Apr 29 11:10:23 2011
@@ -75,7 +75,9 @@
     <httpcore.version>4.1</httpcore.version>
     <httpclient.version>4.1.1</httpclient.version>
     <commons-logging.version>1.1.1</commons-logging.version>
+    <commons-io.version>2.0.1</commons-io.version>
     <junit.version>4.8.1</junit.version>
+    <mockito.version>1.8.5</mockito.version>
   </properties>
 
   <modules>