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 2013/06/13 15:54:54 UTC

svn commit: r1492676 - in /httpcomponents/httpasyncclient/trunk: ./ httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/

Author: olegk
Date: Thu Jun 13 13:54:53 2013
New Revision: 1492676

URL: http://svn.apache.org/r1492676
Log:
HTTPASYNC-45: CachingHttpAsyncClient to override Future returned by the backend.
Contributed by James Leigh <james at 3roundstones dot com>

Added:
    httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/FutureHttpResponse.java   (with props)
Modified:
    httpcomponents/httpasyncclient/trunk/RELEASE_NOTES.txt
    httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpAsyncClient.java

Modified: httpcomponents/httpasyncclient/trunk/RELEASE_NOTES.txt
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/RELEASE_NOTES.txt?rev=1492676&r1=1492675&r2=1492676&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/RELEASE_NOTES.txt (original)
+++ httpcomponents/httpasyncclient/trunk/RELEASE_NOTES.txt Thu Jun 13 13:54:53 2013
@@ -1,3 +1,10 @@
+Change since Release 4.0 Beta 4
+-------------------
+
+* [HTTPASYNC-45] CachingHttpAsyncClient to override Future returned by the backend.
+  Contributed by James Leigh <james at 3roundstones dot com>
+
+
 Release 4.0 Beta 4
 -------------------
 

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpAsyncClient.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpAsyncClient.java?rev=1492676&r1=1492675&r2=1492676&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpAsyncClient.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpAsyncClient.java Thu Jun 13 13:54:53 2013
@@ -78,6 +78,7 @@ import org.apache.http.params.HttpParams
 import org.apache.http.protocol.HTTP;
 import org.apache.http.protocol.HttpContext;
 import org.apache.http.util.Args;
+import org.apache.http.util.EntityUtils;
 import org.apache.http.util.VersionInfo;
 
 @SuppressWarnings("deprecation")
@@ -400,24 +401,17 @@ public class CachingHttpAsyncClient impl
                 future.completed(resp);
                 return future;
             }
-            return revalidateCacheEntry(target, request, context, entry, new FutureCallback<HttpResponse> () {
-
-                public void cancelled() {
-                    futureCallback.cancelled();
-                }
-
-                public void completed(final HttpResponse httpResponse) {
-                    futureCallback.completed(httpResponse);
-                }
-
-                public void failed(final Exception e) {
-                    if(e instanceof IOException) {
-                        futureCallback.completed(handleRevalidationFailure(request, context, entry, now));
-                        return;
+            final FutureHttpResponse future = new FutureHttpResponse(futureCallback) {
+                public void failed(final Exception ex) {
+                    if(ex instanceof IOException) {
+                        super.completed(handleRevalidationFailure(request, context, entry, now));
+                    } else {
+                        super.failed(ex);
                     }
-                    futureCallback.failed(e);
                 }
-            });
+            };
+            future.setDelegate(revalidateCacheEntry(target, request, context, entry, future));
+            return future;
         } catch (final ProtocolException e) {
             throw new ClientProtocolException(e);
         }
@@ -662,30 +656,21 @@ public class CachingHttpAsyncClient impl
             final HttpHost target, final HttpRequestWrapper request, final HttpContext context,
             final FutureCallback<HttpResponse> futureCallback) {
         final Date requestDate = getCurrentDate();
-        this.log.debug("Calling the backend");
-        return this.backend.execute(target, request, context, new FutureCallback<HttpResponse>() {
-
-            public void cancelled() {
-                futureCallback.cancelled();
-            }
-
+        this.log.trace("Calling the backend");
+        final FutureHttpResponse future = new FutureHttpResponse(futureCallback) {
             public void completed(final HttpResponse httpResponse) {
-                httpResponse.addHeader("Via", generateViaHeader(httpResponse));
+                httpResponse.addHeader(HeaderConstants.VIA, generateViaHeader(httpResponse));
                 try {
                     final HttpResponse backendResponse = handleBackendResponse(target, request, requestDate, getCurrentDate(), httpResponse);
-                    futureCallback.completed(backendResponse);
+                    super.completed(backendResponse);
                 } catch (final IOException e) {
-                    futureCallback.failed(e);
-                    return;
+                    super.failed(e);
                 }
 
             }
-
-            public void failed(final Exception e) {
-                futureCallback.failed(e);
-            }
-
-        });
+        };
+        future.setDelegate(this.backend.execute(target, request, context, future));
+        return future;
     }
 
     private boolean revalidationResponseIsTooOld(final HttpResponse backendResponse,
@@ -716,11 +701,11 @@ public class CachingHttpAsyncClient impl
         final HttpRequest conditionalRequest = this.conditionalRequestBuilder.buildConditionalRequestFromVariants(request, variants);
 
         final Date requestDate = getCurrentDate();
-        //HttpResponse backendResponse =
-        return this.backend.execute(target, conditionalRequest, new FutureCallback<HttpResponse> () {
+        final FutureHttpResponse future = new FutureHttpResponse(futureCallback);
+        Future<HttpResponse> backendFuture = this.backend.execute(target, conditionalRequest, context, new FutureCallback<HttpResponse> () {
 
             public void cancelled() {
-                futureCallback.cancelled();
+                future.cancelled();
             }
 
             public void completed(final HttpResponse httpResponse) {
@@ -730,11 +715,10 @@ public class CachingHttpAsyncClient impl
 
                 if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_NOT_MODIFIED) {
                     try {
-                        final HttpResponse backendResponse = handleBackendResponse(target, request, requestDate, responseDate, httpResponse);
-                        futureCallback.completed(backendResponse);
+                        future.completed(handleBackendResponse(target, request, requestDate, responseDate, httpResponse));
                         return;
                     } catch (final IOException e) {
-                        futureCallback.failed(e);
+                        future.failed(e);
                         return;
                     }
                 }
@@ -742,21 +726,7 @@ public class CachingHttpAsyncClient impl
                 final Header resultEtagHeader = httpResponse.getFirstHeader(HeaderConstants.ETAG);
                 if (resultEtagHeader == null) {
                     CachingHttpAsyncClient.this.log.warn("304 response did not contain ETag");
-                    callBackend(target, request, context, new FutureCallback<HttpResponse>() {
-
-                        public void cancelled() {
-                            futureCallback.cancelled();
-                        }
-
-                        public void completed(final HttpResponse innerHttpResponse) {
-                            futureCallback.completed(innerHttpResponse);
-                        }
-
-                        public void failed(final Exception e) {
-                            futureCallback.failed(e);
-                        }
-
-                    });
+                    callBackend(target, request, context, future);
                     return;
                 }
 
@@ -764,27 +734,14 @@ public class CachingHttpAsyncClient impl
                 final Variant matchingVariant = variants.get(resultEtag);
                 if (matchingVariant == null) {
                     CachingHttpAsyncClient.this.log.debug("304 response did not contain ETag matching one sent in If-None-Match");
-                    callBackend(target, request, context, new FutureCallback<HttpResponse>() {
-
-                        public void cancelled() {
-                            futureCallback.cancelled();
-                        }
-
-                        public void completed(final HttpResponse innerHttpResponse) {
-                            futureCallback.completed(innerHttpResponse);
-                        }
-
-                        public void failed(final Exception e) {
-                            futureCallback.failed(e);
-                        }
-
-                    });
+                    callBackend(target, request, context, future);
                 }
 
                 final HttpCacheEntry matchedEntry = matchingVariant.getEntry();
 
                 if (revalidationResponseIsTooOld(httpResponse, matchedEntry)) {
-                    retryRequestUnconditionally(target, request, context, matchedEntry, futureCallback);
+                    EntityUtils.consumeQuietly(httpResponse.getEntity());
+                    retryRequestUnconditionally(target, request, context, matchedEntry, future);
                     return;
                 }
 
@@ -798,20 +755,20 @@ public class CachingHttpAsyncClient impl
                 tryToUpdateVariantMap(target, request, matchingVariant);
 
                 if (shouldSendNotModifiedResponse(request, responseEntry)) {
-                    final HttpResponse backendResponse = CachingHttpAsyncClient.this.responseGenerator.generateNotModifiedResponse(responseEntry);
-                    futureCallback.completed(backendResponse);
+                    future.completed(CachingHttpAsyncClient.this.responseGenerator.generateNotModifiedResponse(responseEntry));
                     return;
                 }
 
-                final HttpResponse backendResponse = resp;
-                futureCallback.completed(backendResponse);
+                future.completed(resp);
                 return;
             }
 
-            public void failed(final Exception e) {
-                futureCallback.failed(e);
+            public void failed(final Exception ex) {
+                future.failed(ex);
             }
         });
+        future.setDelegate(backendFuture);
+        return future;
     }
 
     private void retryRequestUnconditionally(final HttpHost target,
@@ -860,10 +817,11 @@ public class CachingHttpAsyncClient impl
 
         final HttpRequestWrapper conditionalRequest = this.conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry);
         final Date requestDate = getCurrentDate();
-        return this.backend.execute(target, conditionalRequest, context, new FutureCallback<HttpResponse>() {
+        final FutureHttpResponse future = new FutureHttpResponse(futureCallback);
+        future.setDelegate(this.backend.execute(target, conditionalRequest, context, new FutureCallback<HttpResponse>() {
 
             public void cancelled() {
-                futureCallback.cancelled();
+                future.cancelled();
             }
 
             public void completed(final HttpResponse httpResponse) {
@@ -875,35 +833,36 @@ public class CachingHttpAsyncClient impl
                         CachingHttpAsyncClient.this.backend.execute(target, unconditional, context, new FutureCallback<HttpResponse>() {
 
                             public void cancelled() {
-                                futureCallback.cancelled();
+                                future.cancelled();
                             }
 
                             public void completed(final HttpResponse innerHttpResponse) {
                                 final Date innerResponseDate = getCurrentDate();
                                 revalidateCacheEntryCompleted(target, request,
-                                        context, cacheEntry, futureCallback,
+                                        context, cacheEntry, future,
                                         conditionalRequest, innerRequestDate,
                                         innerHttpResponse, innerResponseDate);
                             }
 
-                            public void failed(final Exception e) {
-                                futureCallback.failed(e);
+                            public void failed(final Exception ex) {
+                                future.failed(ex);
                             }
 
                         });
                         return;
                     }
                     revalidateCacheEntryCompleted(target, request,
-                            context, cacheEntry, futureCallback,
+                            context, cacheEntry, future,
                             conditionalRequest, requestDate,
                             httpResponse, responseDate);
             }
 
-            public void failed(final Exception e) {
-                futureCallback.failed(e);
+            public void failed(final Exception ex) {
+                future.failed(ex);
             }
 
-        });
+        }));
+        return future;
     }
 
     private void revalidateCacheEntryCompleted(
@@ -911,7 +870,7 @@ public class CachingHttpAsyncClient impl
             final HttpRequestWrapper request,
             final HttpContext context,
             final HttpCacheEntry cacheEntry,
-            final FutureCallback<HttpResponse> futureCallback,
+            final FutureHttpResponse futureCallback,
             final HttpRequestWrapper conditionalRequest,
             final Date requestDate,
             final HttpResponse httpResponse,

Added: httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/FutureHttpResponse.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/FutureHttpResponse.java?rev=1492676&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/FutureHttpResponse.java (added)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/FutureHttpResponse.java Thu Jun 13 13:54:53 2013
@@ -0,0 +1,151 @@
+/*
+ * ====================================================================
+ * 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.impl.client.cache;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.concurrent.FutureCallback;
+
+/**
+ * Implementation that wraps a Future and overrides the result/exception.
+ *
+ * @author James Leigh
+ *
+ */
+class FutureHttpResponse implements Future<HttpResponse>,
+        FutureCallback<HttpResponse> {
+    private final FutureCallback<HttpResponse> callback;
+    private Future<HttpResponse> delegate;
+    private HttpResponse response;
+    private Throwable thrown;
+
+    public FutureHttpResponse(FutureCallback<HttpResponse> callback) {
+        this.callback = callback;
+    }
+
+    public String toString() {
+        return String.valueOf(response);
+    }
+
+    public synchronized Future<HttpResponse> getDelegate() {
+        return delegate;
+    }
+
+    public synchronized void setDelegate(Future<HttpResponse> delegate) {
+        this.delegate = delegate;
+    }
+
+    public boolean isCancelled() {
+        Future<?> delegate = getDelegate();
+        return delegate != null && delegate.isCancelled();
+    }
+
+    public boolean isDone() {
+        Future<?> delegate = getDelegate();
+        return delegate != null && getDelegate().isDone();
+    }
+
+    public HttpResponse get() throws InterruptedException, ExecutionException {
+        try {
+            getDelegate().get();
+        } catch (ExecutionException e) {
+            // ignore
+        }
+        HttpResponse result = getResponse();
+        Throwable thrown = getThrown();
+        if (thrown != null)
+            throw new ExecutionException(thrown);
+        return result;
+    }
+
+    public HttpResponse get(long timeout, TimeUnit unit)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        try {
+            getDelegate().get(timeout, unit);
+        } catch (ExecutionException e) {
+            // ignore
+        }
+        HttpResponse result = getResponse();
+        Throwable thrown = getThrown();
+        if (thrown != null)
+            throw new ExecutionException(thrown);
+        return result;
+    }
+
+    public void completed(final HttpResponse result) {
+        setResponse(result);
+        if (this.callback != null) {
+            this.callback.completed(result);
+        }
+    }
+
+    public void failed(final Exception exception) {
+        setThrown(exception);
+        if (this.callback != null) {
+            this.callback.failed(exception);
+        }
+    }
+
+    public boolean cancel(final boolean mayInterruptIfRunning) {
+        if (this.callback != null) {
+            this.callback.cancelled();
+        }
+        return getDelegate().cancel(mayInterruptIfRunning);
+    }
+
+    public boolean cancel() {
+        return cancel(true);
+    }
+
+    @Override
+    public void cancelled() {
+        if (this.callback != null) {
+            this.callback.cancelled();
+        }
+    }
+
+    private synchronized HttpResponse getResponse() {
+        return response;
+    }
+
+    private synchronized void setResponse(HttpResponse response) {
+        this.response = response;
+    }
+
+    private synchronized Throwable getThrown() {
+        return thrown;
+    }
+
+    private synchronized void setThrown(Throwable thrown) {
+        this.thrown = thrown;
+    }
+
+}

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/FutureHttpResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/FutureHttpResponse.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient-cache/src/main/java/org/apache/http/impl/client/cache/FutureHttpResponse.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain