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 2016/12/27 19:48:10 UTC

svn commit: r1776187 [2/21] - in /httpcomponents/httpclient/trunk: ./ httpclient5-cache/src/main/java/org/apache/hc/client5/http/cache/ httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ httpclient5-cache/src/test/java/org/apache/hc...

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheInvalidator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheInvalidator.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheInvalidator.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheInvalidator.java Tue Dec 27 19:48:07 2016
@@ -38,7 +38,8 @@ import org.apache.hc.client5.http.cache.
 import org.apache.hc.client5.http.cache.HttpCacheInvalidator;
 import org.apache.hc.client5.http.cache.HttpCacheStorage;
 import org.apache.hc.client5.http.utils.DateUtils;
-import org.apache.hc.core5.annotation.Immutable;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpHeaders;
 import org.apache.hc.core5.http.HttpHost;
@@ -51,7 +52,7 @@ import org.apache.hc.core5.http.HttpResp
  *
  * @since 4.1
  */
-@Immutable
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
 class CacheInvalidator implements HttpCacheInvalidator {
 
     private final HttpCacheStorage storage;
@@ -82,7 +83,7 @@ class CacheInvalidator implements HttpCa
      */
     @Override
     public void flushInvalidatedCacheEntries(final HttpHost host, final HttpRequest req)  {
-        final String theUri = cacheKeyGenerator.getURI(host, req);
+        final String theUri = cacheKeyGenerator.generateKey(host, req);
         final HttpCacheEntry parent = getEntry(theUri);
 
         if (requestShouldNotBeCached(req) || shouldInvalidateHeadCacheEntry(req, parent)) {
@@ -117,7 +118,7 @@ class CacheInvalidator implements HttpCa
     }
 
     private boolean requestIsGet(final HttpRequest req) {
-        return req.getRequestLine().getMethod().equals((HeaderConstants.GET_METHOD));
+        return req.getMethod().equals((HeaderConstants.GET_METHOD));
     }
 
     private boolean isAHeadCacheEntry(final HttpCacheEntry parentCacheEntry) {
@@ -142,7 +143,7 @@ class CacheInvalidator implements HttpCa
     }
 
     protected void flushUriIfSameHost(final URL requestURL, final URL targetURL) {
-        final URL canonicalTarget = getAbsoluteURL(cacheKeyGenerator.canonicalizeUri(targetURL.toString()));
+        final URL canonicalTarget = getAbsoluteURL(cacheKeyGenerator.generateKey(targetURL));
         if (canonicalTarget == null) {
             return;
         }
@@ -190,7 +191,7 @@ class CacheInvalidator implements HttpCa
     }
 
     protected boolean requestShouldNotBeCached(final HttpRequest req) {
-        final String method = req.getRequestLine().getMethod();
+        final String method = req.getMethod();
         return notGetOrHeadRequest(method);
     }
 
@@ -205,11 +206,11 @@ class CacheInvalidator implements HttpCa
     @Override
     public void flushInvalidatedCacheEntries(final HttpHost host,
             final HttpRequest request, final HttpResponse response) {
-        final int status = response.getStatusLine().getStatusCode();
+        final int status = response.getCode();
         if (status < 200 || status > 299) {
             return;
         }
-        final URL reqURL = getAbsoluteURL(cacheKeyGenerator.getURI(host, request));
+        final URL reqURL = getAbsoluteURL(cacheKeyGenerator.generateKey(host, request));
         if (reqURL == null) {
             return;
         }
@@ -225,7 +226,7 @@ class CacheInvalidator implements HttpCa
 
     private void flushLocationCacheEntry(final URL reqURL,
             final HttpResponse response, final URL location) {
-        final String cacheKey = cacheKeyGenerator.canonicalizeUri(location.toString());
+        final String cacheKey = cacheKeyGenerator.generateKey(location);
         final HttpCacheEntry entry = getEntry(cacheKey);
         if (entry == null) {
             return;

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheKeyGenerator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheKeyGenerator.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheKeyGenerator.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheKeyGenerator.java Tue Dec 27 19:48:07 2016
@@ -27,32 +27,56 @@
 package org.apache.hc.client5.http.impl.cache;
 
 import java.io.UnsupportedEncodingException;
-import java.net.MalformedURLException;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 
 import org.apache.hc.client5.http.cache.HeaderConstants;
 import org.apache.hc.client5.http.cache.HttpCacheEntry;
 import org.apache.hc.client5.http.utils.URIUtils;
-import org.apache.hc.core5.annotation.Immutable;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HeaderElement;
 import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.message.MessageSupport;
+import org.apache.hc.core5.net.URIBuilder;
 
 /**
  * @since 4.1
  */
-@Immutable
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
 class CacheKeyGenerator {
 
     private static final URI BASE_URI = URI.create("http://example.com/");
 
+    private URI normalize(final URI uri) throws URISyntaxException {
+        final URIBuilder builder = new URIBuilder(URIUtils.resolve(BASE_URI, uri)) ;
+        if (builder.getHost() != null) {
+            if (builder.getScheme() == null) {
+                builder.setScheme("http");
+            }
+            if (builder.getPort() == -1) {
+                if ("http".equalsIgnoreCase(builder.getScheme())) {
+                    builder.setPort(80);
+                } else if ("https".equalsIgnoreCase(builder.getScheme())) {
+                    builder.setPort(443);
+                }
+            }
+        }
+        if (builder.getPath() == null) {
+            builder.setPath("/");
+        }
+        return builder.build();
+    }
+
     /**
      * For a given {@link HttpHost} and {@link HttpRequest} get a URI from the
      * pair that I can use as an identifier KEY into my HttpCache
@@ -61,60 +85,40 @@ class CacheKeyGenerator {
      * @param req the {@link HttpRequest}
      * @return String the extracted URI
      */
-    public String getURI(final HttpHost host, final HttpRequest req) {
-        if (isRelativeRequest(req)) {
-            return canonicalizeUri(String.format("%s%s", host.toString(), req.getRequestLine().getUri()));
-        }
-        return canonicalizeUri(req.getRequestLine().getUri());
-    }
-
-    public String canonicalizeUri(final String uri) {
+    public String generateKey(final HttpHost host, final HttpRequest req) {
         try {
-            final URI normalized = URIUtils.resolve(BASE_URI, uri);
-            final URL u = new URL(normalized.toASCIIString());
-            final String protocol = u.getProtocol();
-            final String hostname = u.getHost();
-            final int port = canonicalizePort(u.getPort(), protocol);
-            final String path = u.getPath();
-            final String query = u.getQuery();
-            final String file = (query != null) ? (path + "?" + query) : path;
-            final URL out = new URL(protocol, hostname, port, file);
-            return out.toString();
-        } catch (final IllegalArgumentException e) {
-            return uri;
-        } catch (final MalformedURLException e) {
-            return uri;
+            URI uri = req.getUri();
+            if (!uri.isAbsolute()) {
+                uri = URIUtils.rewriteURI(uri, host);
+            }
+            return normalize(uri).toASCIIString();
+        } catch (URISyntaxException ex) {
+            return req.getRequestUri();
         }
     }
 
-    private int canonicalizePort(final int port, final String protocol) {
-        if (port == -1 && "http".equalsIgnoreCase(protocol)) {
-            return 80;
-        } else if (port == -1 && "https".equalsIgnoreCase(protocol)) {
-            return 443;
+    public String generateKey(final URL url) {
+        if (url == null) {
+            return null;
+        }
+        try {
+            return normalize(url.toURI()).toASCIIString();
+        } catch (URISyntaxException ex) {
+            return url.toString();
         }
-        return port;
-    }
-
-    private boolean isRelativeRequest(final HttpRequest req) {
-        final String requestUri = req.getRequestLine().getUri();
-        return ("*".equals(requestUri) || requestUri.startsWith("/"));
     }
 
     protected String getFullHeaderValue(final Header[] headers) {
         if (headers == null) {
             return "";
         }
-
         final StringBuilder buf = new StringBuilder("");
-        boolean first = true;
-        for (final Header hdr : headers) {
-            if (!first) {
+        for (int i = 0; i < headers.length; i++) {
+            final Header hdr = headers[i];
+            if (i > 0) {
                 buf.append(", ");
             }
             buf.append(hdr.getValue().trim());
-            first = false;
-
         }
         return buf.toString();
     }
@@ -129,11 +133,11 @@ class CacheKeyGenerator {
      * @param entry the parent entry used to track the variants
      * @return String the extracted variant URI
      */
-    public String getVariantURI(final HttpHost host, final HttpRequest req, final HttpCacheEntry entry) {
+    public String generateVariantURI(final HttpHost host, final HttpRequest req, final HttpCacheEntry entry) {
         if (!entry.hasVariants()) {
-            return getURI(host, req);
+            return generateKey(host, req);
         }
-        return getVariantKey(req, entry) + getURI(host, req);
+        return generateVariantKey(req, entry) + generateKey(host, req);
     }
 
     /**
@@ -145,12 +149,12 @@ class CacheKeyGenerator {
      * @param entry cache entry in question that has variants
      * @return a {@code String} variant key
      */
-    public String getVariantKey(final HttpRequest req, final HttpCacheEntry entry) {
+    public String generateVariantKey(final HttpRequest req, final HttpCacheEntry entry) {
         final List<String> variantHeaderNames = new ArrayList<>();
-        for (final Header varyHdr : entry.getHeaders(HeaderConstants.VARY)) {
-            for (final HeaderElement elt : varyHdr.getElements()) {
-                variantHeaderNames.add(elt.getName());
-            }
+        final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.VARY);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            variantHeaderNames.add(elt.getName());
         }
         Collections.sort(variantHeaderNames);
 

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheValidityPolicy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheValidityPolicy.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheValidityPolicy.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheValidityPolicy.java Tue Dec 27 19:48:07 2016
@@ -27,20 +27,24 @@
 package org.apache.hc.client5.http.impl.cache;
 
 import java.util.Date;
+import java.util.Iterator;
 
 import org.apache.hc.client5.http.cache.HeaderConstants;
 import org.apache.hc.client5.http.cache.HttpCacheEntry;
 import org.apache.hc.client5.http.utils.DateUtils;
-import org.apache.hc.core5.annotation.Immutable;
+import org.apache.hc.core5.http.message.MessageSupport;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HeaderElement;
 import org.apache.hc.core5.http.HttpHeaders;
 import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.MessageHeaders;
 
 /**
  * @since 4.1
  */
-@Immutable
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
 class CacheValidityPolicy {
 
     public static final long MAX_AGE = 2147483648L;
@@ -124,17 +128,17 @@ class CacheValidityPolicy {
     }
 
     public boolean mayReturnStaleWhileRevalidating(final HttpCacheEntry entry, final Date now) {
-        for (final Header h : entry.getHeaders(HeaderConstants.CACHE_CONTROL)) {
-            for(final HeaderElement elt : h.getElements()) {
-                if (HeaderConstants.STALE_WHILE_REVALIDATE.equalsIgnoreCase(elt.getName())) {
-                    try {
-                        final int allowedStalenessLifetime = Integer.parseInt(elt.getValue());
-                        if (getStalenessSecs(entry, now) <= allowedStalenessLifetime) {
-                            return true;
-                        }
-                    } catch (final NumberFormatException nfe) {
-                        // skip malformed directive
+        final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            if (HeaderConstants.STALE_WHILE_REVALIDATE.equalsIgnoreCase(elt.getName())) {
+                try {
+                    final int allowedStalenessLifetime = Integer.parseInt(elt.getValue());
+                    if (getStalenessSecs(entry, now) <= allowedStalenessLifetime) {
+                        return true;
                     }
+                } catch (final NumberFormatException nfe) {
+                    // skip malformed directive
                 }
             }
         }
@@ -142,29 +146,26 @@ class CacheValidityPolicy {
         return false;
     }
 
-    public boolean mayReturnStaleIfError(final HttpRequest request,
-            final HttpCacheEntry entry, final Date now) {
+    public boolean mayReturnStaleIfError(final HttpRequest request, final HttpCacheEntry entry, final Date now) {
         final long stalenessSecs = getStalenessSecs(entry, now);
-        return mayReturnStaleIfError(request.getHeaders(HeaderConstants.CACHE_CONTROL),
-                                     stalenessSecs)
-                || mayReturnStaleIfError(entry.getHeaders(HeaderConstants.CACHE_CONTROL),
-                                         stalenessSecs);
+        return mayReturnStaleIfError(request, HeaderConstants.CACHE_CONTROL, stalenessSecs)
+                || mayReturnStaleIfError(entry, HeaderConstants.CACHE_CONTROL, stalenessSecs);
     }
 
-    private boolean mayReturnStaleIfError(final Header[] headers, final long stalenessSecs) {
+    private boolean mayReturnStaleIfError(final MessageHeaders headers, final String name, final long stalenessSecs) {
         boolean result = false;
-        for(final Header h : headers) {
-            for(final HeaderElement elt : h.getElements()) {
-                if (HeaderConstants.STALE_IF_ERROR.equals(elt.getName())) {
-                    try {
-                        final int staleIfErrorSecs = Integer.parseInt(elt.getValue());
-                        if (stalenessSecs <= staleIfErrorSecs) {
-                            result = true;
-                            break;
-                        }
-                    } catch (final NumberFormatException nfe) {
-                        // skip malformed directive
+        final Iterator<HeaderElement> it = MessageSupport.iterate(headers, name);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            if (HeaderConstants.STALE_IF_ERROR.equals(elt.getName())) {
+                try {
+                    final int staleIfErrorSecs = Integer.parseInt(elt.getValue());
+                    if (stalenessSecs <= staleIfErrorSecs) {
+                        result = true;
+                        break;
                     }
+                } catch (final NumberFormatException nfe) {
+                    // skip malformed directive
                 }
             }
         }
@@ -259,19 +260,18 @@ class CacheValidityPolicy {
 
     protected long getMaxAge(final HttpCacheEntry entry) {
         long maxage = -1;
-        for (final Header hdr : entry.getHeaders(HeaderConstants.CACHE_CONTROL)) {
-            for (final HeaderElement elt : hdr.getElements()) {
-                if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())
-                        || "s-maxage".equals(elt.getName())) {
-                    try {
-                        final long currMaxAge = Long.parseLong(elt.getValue());
-                        if (maxage == -1 || currMaxAge < maxage) {
-                            maxage = currMaxAge;
-                        }
-                    } catch (final NumberFormatException nfe) {
-                        // be conservative if can't parse
-                        maxage = 0;
+        final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName()) || "s-maxage".equals(elt.getName())) {
+                try {
+                    final long currMaxAge = Long.parseLong(elt.getValue());
+                    if (maxage == -1 || currMaxAge < maxage) {
+                        maxage = currMaxAge;
                     }
+                } catch (final NumberFormatException nfe) {
+                    // be conservative if can't parse
+                    maxage = 0;
                 }
             }
         }
@@ -286,13 +286,12 @@ class CacheValidityPolicy {
         return DateUtils.parseDate(expiresHeader.getValue());
     }
 
-    public boolean hasCacheControlDirective(final HttpCacheEntry entry,
-            final String directive) {
-        for (final Header h : entry.getHeaders(HeaderConstants.CACHE_CONTROL)) {
-            for(final HeaderElement elt : h.getElements()) {
-                if (directive.equalsIgnoreCase(elt.getName())) {
-                    return true;
-                }
+    public boolean hasCacheControlDirective(final HttpCacheEntry entry, final String directive) {
+        final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            if (directive.equalsIgnoreCase(elt.getName())) {
+                return true;
             }
         }
         return false;

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheableRequestPolicy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheableRequestPolicy.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheableRequestPolicy.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheableRequestPolicy.java Tue Dec 27 19:48:07 2016
@@ -26,11 +26,14 @@
  */
 package org.apache.hc.client5.http.impl.cache;
 
+import java.util.Iterator;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.hc.core5.http.message.MessageSupport;
 import org.apache.hc.client5.http.cache.HeaderConstants;
-import org.apache.hc.core5.annotation.Immutable;
-import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.HeaderElement;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpVersion;
@@ -41,7 +44,7 @@ import org.apache.hc.core5.http.Protocol
  *
  * @since 4.1
  */
-@Immutable
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
 class CacheableRequestPolicy {
 
     private final Log log = LogFactory.getLog(getClass());
@@ -54,9 +57,9 @@ class CacheableRequestPolicy {
      * @return boolean Is it possible to serve this request from cache
      */
     public boolean isServableFromCache(final HttpRequest request) {
-        final String method = request.getRequestLine().getMethod();
+        final String method = request.getMethod();
 
-        final ProtocolVersion pv = request.getRequestLine().getProtocolVersion();
+        final ProtocolVersion pv = request.getVersion() != null ? request.getVersion() : HttpVersion.DEFAULT;
         if (HttpVersion.HTTP_1_1.compareToVersion(pv) != 0) {
             log.trace("non-HTTP/1.1 request was not serveable from cache");
             return false;
@@ -73,20 +76,18 @@ class CacheableRequestPolicy {
             return false;
         }
 
-        final Header[] cacheControlHeaders = request.getHeaders(HeaderConstants.CACHE_CONTROL);
-        for (final Header cacheControl : cacheControlHeaders) {
-            for (final HeaderElement cacheControlElement : cacheControl.getElements()) {
-                if (HeaderConstants.CACHE_CONTROL_NO_STORE.equalsIgnoreCase(cacheControlElement
-                        .getName())) {
-                    log.trace("Request with no-store was not serveable from cache");
-                    return false;
-                }
-
-                if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equalsIgnoreCase(cacheControlElement
-                        .getName())) {
-                    log.trace("Request with no-cache was not serveable from cache");
-                    return false;
-                }
+        final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
+        while (it.hasNext()) {
+            final HeaderElement cacheControlElement = it.next();
+            if (HeaderConstants.CACHE_CONTROL_NO_STORE.equalsIgnoreCase(cacheControlElement
+                    .getName())) {
+                log.trace("Request with no-store was not serveable from cache");
+                return false;
+            }
+            if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equalsIgnoreCase(cacheControlElement
+                    .getName())) {
+                log.trace("Request with no-cache was not serveable from cache");
+                return false;
             }
         }
 

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachedHttpResponseGenerator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachedHttpResponseGenerator.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachedHttpResponseGenerator.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachedHttpResponseGenerator.java Tue Dec 27 19:48:07 2016
@@ -30,25 +30,26 @@ import java.util.Date;
 
 import org.apache.hc.client5.http.cache.HeaderConstants;
 import org.apache.hc.client5.http.cache.HttpCacheEntry;
-import org.apache.hc.client5.http.methods.CloseableHttpResponse;
-import org.apache.hc.client5.http.methods.HttpRequestWrapper;
 import org.apache.hc.client5.http.utils.DateUtils;
-import org.apache.hc.core5.annotation.Immutable;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpEntity;
 import org.apache.hc.core5.http.HttpHeaders;
+import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.HttpVersion;
+import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
 import org.apache.hc.core5.http.message.BasicHeader;
-import org.apache.hc.core5.http.message.BasicHttpResponse;
 
 /**
  * Rebuilds an {@link HttpResponse} from a {@link net.sf.ehcache.CacheEntry}
  *
  * @since 4.1
  */
-@Immutable
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
 class CachedHttpResponseGenerator {
 
     private final CacheValidityPolicy validityStrategy;
@@ -63,16 +64,16 @@ class CachedHttpResponseGenerator {
     }
 
     /**
-     * If I was able to use a {@link CacheEntity} to response to the {@link org.apache.hc.core5.http.HttpRequest} then
+     * If I was able to use a {@link CacheEntity} to response to the {@link HttpRequest} then
      * generate an {@link HttpResponse} based on the cache entry.
-     * @param request {@link HttpRequestWrapper} to generate the response for
+     * @param request {@link HttpRequest} to generate the response for
      * @param entry {@link CacheEntity} to transform into an {@link HttpResponse}
      * @return {@link HttpResponse} that was constructed
      */
-    CloseableHttpResponse generateResponse(final HttpRequestWrapper request, final HttpCacheEntry entry) {
+    ClassicHttpResponse generateResponse(final HttpRequest request, final HttpCacheEntry entry) {
         final Date now = new Date();
-        final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, entry
-                .getStatusCode(), entry.getReasonPhrase());
+        final ClassicHttpResponse response = new BasicClassicHttpResponse(entry.getStatus());
+        response.setVersion(HttpVersion.DEFAULT);
 
         response.setHeaders(entry.getAllHeaders());
 
@@ -91,17 +92,16 @@ class CachedHttpResponseGenerator {
             }
         }
 
-        return Proxies.enhanceResponse(response);
+        return response;
     }
 
     /**
      * Generate a 304 - Not Modified response from a {@link CacheEntity}.  This should be
      * used to respond to conditional requests, when the entry exists or has been re-validated.
      */
-    CloseableHttpResponse generateNotModifiedResponse(final HttpCacheEntry entry) {
+    ClassicHttpResponse generateNotModifiedResponse(final HttpCacheEntry entry) {
 
-        final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
-                HttpStatus.SC_NOT_MODIFIED, "Not Modified");
+        final ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_NOT_MODIFIED, "Not Modified");
 
         // The response MUST include the following headers
         //  (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
@@ -143,7 +143,7 @@ class CachedHttpResponseGenerator {
             response.addHeader(varyHeader);
         }
 
-        return Proxies.enhanceResponse(response);
+        return response;
     }
 
     private void addMissingContentLengthHeader(final HttpResponse response, final HttpEntity entity) {
@@ -164,9 +164,8 @@ class CachedHttpResponseGenerator {
         return hdr != null;
     }
 
-    private boolean responseShouldContainEntity(final HttpRequestWrapper request, final HttpCacheEntry cacheEntry) {
-        return request.getRequestLine().getMethod().equals(HeaderConstants.GET_METHOD) &&
-               cacheEntry.getResource() != null;
+    private boolean responseShouldContainEntity(final HttpRequest request, final HttpCacheEntry cacheEntry) {
+        return request.getMethod().equals(HeaderConstants.GET_METHOD) && cacheEntry.getResource() != null;
     }
 
 }

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachedResponseSuitabilityChecker.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachedResponseSuitabilityChecker.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachedResponseSuitabilityChecker.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachedResponseSuitabilityChecker.java Tue Dec 27 19:48:07 2016
@@ -27,13 +27,16 @@
 package org.apache.hc.client5.http.impl.cache;
 
 import java.util.Date;
+import java.util.Iterator;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hc.client5.http.cache.HeaderConstants;
 import org.apache.hc.client5.http.cache.HttpCacheEntry;
 import org.apache.hc.client5.http.utils.DateUtils;
-import org.apache.hc.core5.annotation.Immutable;
+import org.apache.hc.core5.http.message.MessageSupport;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HeaderElement;
 import org.apache.hc.core5.http.HttpHost;
@@ -46,7 +49,7 @@ import org.apache.hc.core5.http.HttpStat
  *
  * @since 4.1
  */
-@Immutable
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
 class CachedResponseSuitabilityChecker {
 
     private final Log log = LogFactory.getLog(getClass());
@@ -102,25 +105,24 @@ class CachedResponseSuitabilityChecker {
 
     private long getMaxStale(final HttpRequest request) {
         long maxstale = -1;
-        for(final Header h : request.getHeaders(HeaderConstants.CACHE_CONTROL)) {
-            for(final HeaderElement elt : h.getElements()) {
-                if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
-                    if ((elt.getValue() == null || "".equals(elt.getValue().trim()))
-                            && maxstale == -1) {
-                        maxstale = Long.MAX_VALUE;
-                    } else {
-                        try {
-                            long val = Long.parseLong(elt.getValue());
-                            if (val < 0) {
-                                val = 0;
-                            }
-                            if (maxstale == -1 || val < maxstale) {
-                                maxstale = val;
-                            }
-                        } catch (final NumberFormatException nfe) {
-                            // err on the side of preserving semantic transparency
-                            maxstale = 0;
+        final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
+                if ((elt.getValue() == null || "".equals(elt.getValue().trim())) && maxstale == -1) {
+                    maxstale = Long.MAX_VALUE;
+                } else {
+                    try {
+                        long val = Long.parseLong(elt.getValue());
+                        if (val < 0) {
+                            val = 0;
+                        }
+                        if (maxstale == -1 || val < maxstale) {
+                            maxstale = val;
                         }
+                    } catch (final NumberFormatException nfe) {
+                        // err on the side of preserving semantic transparency
+                        maxstale = 0;
                     }
                 }
             }
@@ -158,7 +160,7 @@ class CachedResponseSuitabilityChecker {
             return false;
         }
 
-        if (!isConditional(request) && entry.getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
+        if (!isConditional(request) && entry.getStatus() == HttpStatus.SC_NOT_MODIFIED) {
             return false;
         }
 
@@ -171,65 +173,64 @@ class CachedResponseSuitabilityChecker {
                       "request method, entity or a 204 response");
             return false;
         }
+        final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elt.getName())) {
+                log.trace("Response contained NO CACHE directive, cache was not suitable");
+                return false;
+            }
 
-        for (final Header ccHdr : request.getHeaders(HeaderConstants.CACHE_CONTROL)) {
-            for (final HeaderElement elt : ccHdr.getElements()) {
-                if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elt.getName())) {
-                    log.trace("Response contained NO CACHE directive, cache was not suitable");
-                    return false;
-                }
+            if (HeaderConstants.CACHE_CONTROL_NO_STORE.equals(elt.getName())) {
+                log.trace("Response contained NO STORE directive, cache was not suitable");
+                return false;
+            }
 
-                if (HeaderConstants.CACHE_CONTROL_NO_STORE.equals(elt.getName())) {
-                    log.trace("Response contained NO STORE directive, cache was not suitable");
+            if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
+                try {
+                    final int maxage = Integer.parseInt(elt.getValue());
+                    if (validityStrategy.getCurrentAgeSecs(entry, now) > maxage) {
+                        log.trace("Response from cache was NOT suitable due to max age");
+                        return false;
+                    }
+                } catch (final NumberFormatException ex) {
+                    // err conservatively
+                    log.debug("Response from cache was malformed" + ex.getMessage());
                     return false;
                 }
+            }
 
-                if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
-                    try {
-                        final int maxage = Integer.parseInt(elt.getValue());
-                        if (validityStrategy.getCurrentAgeSecs(entry, now) > maxage) {
-                            log.trace("Response from cache was NOT suitable due to max age");
-                            return false;
-                        }
-                    } catch (final NumberFormatException ex) {
-                        // err conservatively
-                        log.debug("Response from cache was malformed" + ex.getMessage());
+            if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
+                try {
+                    final int maxstale = Integer.parseInt(elt.getValue());
+                    if (validityStrategy.getFreshnessLifetimeSecs(entry) > maxstale) {
+                        log.trace("Response from cache was not suitable due to Max stale freshness");
                         return false;
                     }
+                } catch (final NumberFormatException ex) {
+                    // err conservatively
+                    log.debug("Response from cache was malformed: " + ex.getMessage());
+                    return false;
                 }
+            }
 
-                if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
-                    try {
-                        final int maxstale = Integer.parseInt(elt.getValue());
-                        if (validityStrategy.getFreshnessLifetimeSecs(entry) > maxstale) {
-                            log.trace("Response from cache was not suitable due to Max stale freshness");
-                            return false;
-                        }
-                    } catch (final NumberFormatException ex) {
-                        // err conservatively
-                        log.debug("Response from cache was malformed: " + ex.getMessage());
+            if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())) {
+                try {
+                    final long minfresh = Long.parseLong(elt.getValue());
+                    if (minfresh < 0L) {
                         return false;
                     }
-                }
-
-                if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())) {
-                    try {
-                        final long minfresh = Long.parseLong(elt.getValue());
-                        if (minfresh < 0L) {
-                            return false;
-                        }
-                        final long age = validityStrategy.getCurrentAgeSecs(entry, now);
-                        final long freshness = validityStrategy.getFreshnessLifetimeSecs(entry);
-                        if (freshness - age < minfresh) {
-                            log.trace("Response from cache was not suitable due to min fresh " +
-                                    "freshness requirement");
-                            return false;
-                        }
-                    } catch (final NumberFormatException ex) {
-                        // err conservatively
-                        log.debug("Response from cache was malformed: " + ex.getMessage());
+                    final long age = validityStrategy.getCurrentAgeSecs(entry, now);
+                    final long freshness = validityStrategy.getFreshnessLifetimeSecs(entry);
+                    if (freshness - age < minfresh) {
+                        log.trace("Response from cache was not suitable due to min fresh " +
+                                "freshness requirement");
                         return false;
                     }
+                } catch (final NumberFormatException ex) {
+                    // err conservatively
+                    log.debug("Response from cache was malformed: " + ex.getMessage());
+                    return false;
                 }
             }
         }
@@ -239,11 +240,11 @@ class CachedResponseSuitabilityChecker {
     }
 
     private boolean isGet(final HttpRequest request) {
-        return request.getRequestLine().getMethod().equals(HeaderConstants.GET_METHOD);
+        return request.getMethod().equals(HeaderConstants.GET_METHOD);
     }
 
     private boolean entryIsNotA204Response(final HttpCacheEntry entry) {
-        return entry.getStatusCode() != HttpStatus.SC_NO_CONTENT;
+        return entry.getStatus() != HttpStatus.SC_NO_CONTENT;
     }
 
     private boolean cacheEntryDoesNotContainMethodAndEntity(final HttpCacheEntry entry) {
@@ -313,16 +314,12 @@ class CachedResponseSuitabilityChecker {
     private boolean etagValidatorMatches(final HttpRequest request, final HttpCacheEntry entry) {
         final Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG);
         final String etag = (etagHeader != null) ? etagHeader.getValue() : null;
-        final Header[] ifNoneMatch = request.getHeaders(HeaderConstants.IF_NONE_MATCH);
-        if (ifNoneMatch != null) {
-            for (final Header h : ifNoneMatch) {
-                for (final HeaderElement elt : h.getElements()) {
-                    final String reqEtag = elt.toString();
-                    if (("*".equals(reqEtag) && etag != null)
-                            || reqEtag.equals(etag)) {
-                        return true;
-                    }
-                }
+        final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.IF_NONE_MATCH);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            final String reqEtag = elt.toString();
+            if (("*".equals(reqEtag) && etag != null) || reqEtag.equals(etag)) {
+                return true;
             }
         }
         return false;

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java Tue Dec 27 19:48:07 2016
@@ -27,10 +27,9 @@
 package org.apache.hc.client5.http.impl.cache;
 
 import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
@@ -45,13 +44,13 @@ import org.apache.hc.client5.http.cache.
 import org.apache.hc.client5.http.cache.HttpCacheStorage;
 import org.apache.hc.client5.http.cache.ResourceFactory;
 import org.apache.hc.client5.http.impl.sync.ClientExecChain;
-import org.apache.hc.client5.http.methods.CloseableHttpResponse;
 import org.apache.hc.client5.http.methods.HttpExecutionAware;
-import org.apache.hc.client5.http.methods.HttpRequestWrapper;
+import org.apache.hc.client5.http.methods.RoutedHttpRequest;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
 import org.apache.hc.client5.http.utils.DateUtils;
-import org.apache.hc.client5.http.utils.URIUtils;
-import org.apache.hc.core5.annotation.ThreadSafe;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HeaderElement;
 import org.apache.hc.core5.http.HttpException;
@@ -62,10 +61,9 @@ import org.apache.hc.core5.http.HttpRequ
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.HttpVersion;
-import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.ProtocolVersion;
-import org.apache.hc.core5.http.RequestLine;
-import org.apache.hc.core5.http.message.BasicHttpResponse;
+import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
+import org.apache.hc.core5.http.message.MessageSupport;
 import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.http.protocol.HttpCoreContext;
 import org.apache.hc.core5.util.Args;
@@ -99,7 +97,7 @@ import org.apache.hc.core5.util.VersionI
  *
  * @since 4.3
  */
-@ThreadSafe // So long as the responseCache implementation is threadsafe
+@Contract(threading = ThreadingBehavior.SAFE) // So long as the responseCache implementation is threadsafe
 public class CachingExec implements ClientExecChain {
 
     private final static boolean SUPPORTS_RANGE_AND_CONTENT_RANGE_HEADERS = false;
@@ -223,27 +221,23 @@ public class CachingExec implements Clie
         return cacheUpdates.get();
     }
 
-    public CloseableHttpResponse execute(
-            final HttpRoute route,
-            final HttpRequestWrapper request) throws IOException, HttpException {
-        return execute(route, request, HttpClientContext.create(), null);
+    public ClassicHttpResponse execute(final RoutedHttpRequest request) throws IOException, HttpException {
+        return execute(request, HttpClientContext.create(), null);
     }
 
-    public CloseableHttpResponse execute(
-            final HttpRoute route,
-            final HttpRequestWrapper request,
+    public ClassicHttpResponse execute(
+            final RoutedHttpRequest request,
             final HttpClientContext context) throws IOException, HttpException {
-        return execute(route, request, context, null);
+        return execute(request, context, null);
     }
 
     @Override
-    public CloseableHttpResponse execute(
-            final HttpRoute route,
-            final HttpRequestWrapper request,
+    public ClassicHttpResponse execute(
+            final RoutedHttpRequest request,
             final HttpClientContext context,
             final HttpExecutionAware execAware) throws IOException, HttpException {
 
-        final HttpHost target = context.getTargetHost();
+        final HttpHost target = request.getTargetHost();
         final String via = generateViaHeader(request.getOriginal());
 
         // default response context
@@ -251,42 +245,41 @@ public class CachingExec implements Clie
 
         if (clientRequestsOurOptions(request)) {
             setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
-            return Proxies.enhanceResponse(new OptionsHttp11Response());
+            return new OptionsHttp11Response();
         }
 
-        final HttpResponse fatalErrorResponse = getFatallyNoncompliantResponse(request, context);
+        final ClassicHttpResponse fatalErrorResponse = getFatallyNoncompliantResponse(request, context);
         if (fatalErrorResponse != null) {
-            return Proxies.enhanceResponse(fatalErrorResponse);
+            return fatalErrorResponse;
         }
 
         requestCompliance.makeRequestCompliant(request);
         request.addHeader("Via",via);
 
-        flushEntriesInvalidatedByRequest(context.getTargetHost(), request);
+        flushEntriesInvalidatedByRequest(target, request);
 
         if (!cacheableRequestPolicy.isServableFromCache(request)) {
             log.debug("Request is not servable from cache");
-            return callBackend(route, request, context, execAware);
+            return callBackend(request, context, execAware);
         }
 
         final HttpCacheEntry entry = satisfyFromCache(target, request);
         if (entry == null) {
             log.debug("Cache miss");
-            return handleCacheMiss(route, request, context, execAware);
+            return handleCacheMiss(request, context, execAware);
         } else {
-            return handleCacheHit(route, request, context, execAware, entry);
+            return handleCacheHit(request, context, execAware, entry);
         }
     }
 
-    private CloseableHttpResponse handleCacheHit(
-            final HttpRoute route,
-            final HttpRequestWrapper request,
+    private ClassicHttpResponse handleCacheHit(
+            final RoutedHttpRequest request,
             final HttpClientContext context,
             final HttpExecutionAware execAware,
             final HttpCacheEntry entry) throws IOException, HttpException {
-        final HttpHost target = context.getTargetHost();
+        final HttpHost target = request.getTargetHost();
         recordCacheHit(target, request);
-        CloseableHttpResponse out = null;
+        ClassicHttpResponse out;
         final Date now = getCurrentDate();
         if (suitabilityChecker.canCachedResponseBeUsed(target, request, entry, now)) {
             log.debug("Cache hit");
@@ -294,24 +287,23 @@ public class CachingExec implements Clie
         } else if (!mayCallBackend(request)) {
             log.debug("Cache entry not suitable but only-if-cached requested");
             out = generateGatewayTimeout(context);
-        } else if (!(entry.getStatusCode() == HttpStatus.SC_NOT_MODIFIED
+        } else if (!(entry.getStatus() == HttpStatus.SC_NOT_MODIFIED
                 && !suitabilityChecker.isConditional(request))) {
             log.debug("Revalidating cache entry");
-            return revalidateCacheEntry(route, request, context, execAware, entry, now);
+            return revalidateCacheEntry(request, context, execAware, entry, now);
         } else {
             log.debug("Cache entry not usable; calling backend");
-            return callBackend(route, request, context, execAware);
+            return callBackend(request, context, execAware);
         }
+        final HttpRoute route = request.getRoute();
         context.setAttribute(HttpClientContext.HTTP_ROUTE, route);
-        context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, target);
         context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
         context.setAttribute(HttpCoreContext.HTTP_RESPONSE, out);
         return out;
     }
 
-    private CloseableHttpResponse revalidateCacheEntry(
-            final HttpRoute route,
-            final HttpRequestWrapper request,
+    private ClassicHttpResponse revalidateCacheEntry(
+            final RoutedHttpRequest request,
             final HttpClientContext context,
             final HttpExecutionAware execAware,
             final HttpCacheEntry entry,
@@ -322,41 +314,37 @@ public class CachingExec implements Clie
                 && !staleResponseNotAllowed(request, entry, now)
                 && validityPolicy.mayReturnStaleWhileRevalidating(entry, now)) {
                 log.trace("Serving stale with asynchronous revalidation");
-                final CloseableHttpResponse resp = generateCachedResponse(request, context, entry, now);
-                asynchRevalidator.revalidateCacheEntry(this, route, request, context, execAware, entry);
+                final ClassicHttpResponse resp = generateCachedResponse(request, context, entry, now);
+                asynchRevalidator.revalidateCacheEntry(this, request, context, execAware, entry);
                 return resp;
             }
-            return revalidateCacheEntry(route, request, context, execAware, entry);
+            return revalidateCacheEntry(request, context, execAware, entry);
         } catch (final IOException ioex) {
             return handleRevalidationFailure(request, context, entry, now);
         }
     }
 
-    private CloseableHttpResponse handleCacheMiss(
-            final HttpRoute route,
-            final HttpRequestWrapper request,
+    private ClassicHttpResponse handleCacheMiss(
+            final RoutedHttpRequest request,
             final HttpClientContext context,
             final HttpExecutionAware execAware) throws IOException, HttpException {
-        final HttpHost target = context.getTargetHost();
+        final HttpHost target = request.getTargetHost();
         recordCacheMiss(target, request);
 
         if (!mayCallBackend(request)) {
-            return Proxies.enhanceResponse(
-                    new BasicHttpResponse(
-                            HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"));
+            return new BasicClassicHttpResponse(HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout");
         }
 
         final Map<String, Variant> variants = getExistingCacheVariants(target, request);
         if (variants != null && !variants.isEmpty()) {
-            return negotiateResponseFromVariants(route, request, context,
-                    execAware, variants);
+            return negotiateResponseFromVariants(request, context, execAware, variants);
         }
 
-        return callBackend(route, request, context, execAware);
+        return callBackend(request, context, execAware);
     }
 
     private HttpCacheEntry satisfyFromCache(
-            final HttpHost target, final HttpRequestWrapper request) {
+            final HttpHost target, final RoutedHttpRequest request) {
         HttpCacheEntry entry = null;
         try {
             entry = responseCache.getCacheEntry(target, request);
@@ -366,10 +354,10 @@ public class CachingExec implements Clie
         return entry;
     }
 
-    private HttpResponse getFatallyNoncompliantResponse(
-            final HttpRequestWrapper request,
+    private ClassicHttpResponse getFatallyNoncompliantResponse(
+            final RoutedHttpRequest request,
             final HttpContext context) {
-        HttpResponse fatalErrorResponse = null;
+        ClassicHttpResponse fatalErrorResponse = null;
         final List<RequestProtocolError> fatalError = requestCompliance.requestIsFatallyNonCompliant(request);
 
         for (final RequestProtocolError error : fatalError) {
@@ -381,7 +369,7 @@ public class CachingExec implements Clie
 
     private Map<String, Variant> getExistingCacheVariants(
             final HttpHost target,
-            final HttpRequestWrapper request) {
+            final RoutedHttpRequest request) {
         Map<String,Variant> variants = null;
         try {
             variants = responseCache.getVariantCacheEntriesWithEtags(target, request);
@@ -391,19 +379,17 @@ public class CachingExec implements Clie
         return variants;
     }
 
-    private void recordCacheMiss(final HttpHost target, final HttpRequestWrapper request) {
+    private void recordCacheMiss(final HttpHost target, final RoutedHttpRequest request) {
         cacheMisses.getAndIncrement();
         if (log.isTraceEnabled()) {
-            final RequestLine rl = request.getRequestLine();
-            log.trace("Cache miss [host: " + target + "; uri: " + rl.getUri() + "]");
+            log.trace("Cache miss [host: " + target + "; uri: " + request.getRequestUri() + "]");
         }
     }
 
-    private void recordCacheHit(final HttpHost target, final HttpRequestWrapper request) {
+    private void recordCacheHit(final HttpHost target, final RoutedHttpRequest request) {
         cacheHits.getAndIncrement();
         if (log.isTraceEnabled()) {
-            final RequestLine rl = request.getRequestLine();
-            log.trace("Cache hit [host: " + target + "; uri: " + rl.getUri() + "]");
+            log.trace("Cache hit [host: " + target + "; uri: " + request.getRequestUri() + "]");
         }
     }
 
@@ -414,7 +400,7 @@ public class CachingExec implements Clie
 
     private void flushEntriesInvalidatedByRequest(
             final HttpHost target,
-            final HttpRequestWrapper request) {
+            final RoutedHttpRequest request) {
         try {
             responseCache.flushInvalidatedCacheEntriesFor(target, request);
         } catch (final IOException ioe) {
@@ -422,9 +408,9 @@ public class CachingExec implements Clie
         }
     }
 
-    private CloseableHttpResponse generateCachedResponse(final HttpRequestWrapper request,
+    private ClassicHttpResponse generateCachedResponse(final RoutedHttpRequest request,
             final HttpContext context, final HttpCacheEntry entry, final Date now) {
-        final CloseableHttpResponse cachedResponse;
+        final ClassicHttpResponse cachedResponse;
         if (request.containsHeader(HeaderConstants.IF_NONE_MATCH)
                 || request.containsHeader(HeaderConstants.IF_MODIFIED_SINCE)) {
             cachedResponse = responseGenerator.generateNotModifiedResponse(entry);
@@ -438,8 +424,8 @@ public class CachingExec implements Clie
         return cachedResponse;
     }
 
-    private CloseableHttpResponse handleRevalidationFailure(
-            final HttpRequestWrapper request,
+    private ClassicHttpResponse handleRevalidationFailure(
+            final RoutedHttpRequest request,
             final HttpContext context,
             final HttpCacheEntry entry,
             final Date now) {
@@ -450,26 +436,24 @@ public class CachingExec implements Clie
         }
     }
 
-    private CloseableHttpResponse generateGatewayTimeout(
+    private ClassicHttpResponse generateGatewayTimeout(
             final HttpContext context) {
         setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
-        return Proxies.enhanceResponse(new BasicHttpResponse(
-                HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT,
-                "Gateway Timeout"));
+        return new BasicClassicHttpResponse(HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout");
     }
 
-    private CloseableHttpResponse unvalidatedCacheHit(
-            final HttpRequestWrapper request,
+    private ClassicHttpResponse unvalidatedCacheHit(
+            final RoutedHttpRequest request,
             final HttpContext context,
             final HttpCacheEntry entry) {
-        final CloseableHttpResponse cachedResponse = responseGenerator.generateResponse(request, entry);
+        final ClassicHttpResponse cachedResponse = responseGenerator.generateResponse(request, entry);
         setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
         cachedResponse.addHeader(HeaderConstants.WARNING, "111 localhost \"Revalidation failed\"");
         return cachedResponse;
     }
 
     private boolean staleResponseNotAllowed(
-            final HttpRequestWrapper request,
+            final RoutedHttpRequest request,
             final HttpCacheEntry entry,
             final Date now) {
         return validityPolicy.mustRevalidate(entry)
@@ -477,39 +461,39 @@ public class CachingExec implements Clie
             || explicitFreshnessRequest(request, entry, now);
     }
 
-    private boolean mayCallBackend(final HttpRequestWrapper request) {
-        for (final Header h: request.getHeaders(HeaderConstants.CACHE_CONTROL)) {
-            for (final HeaderElement elt : h.getElements()) {
-                if ("only-if-cached".equals(elt.getName())) {
-                    log.trace("Request marked only-if-cached");
-                    return false;
-                }
+    private boolean mayCallBackend(final RoutedHttpRequest request) {
+        final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            if ("only-if-cached".equals(elt.getName())) {
+                log.trace("Request marked only-if-cached");
+                return false;
             }
         }
         return true;
     }
 
     private boolean explicitFreshnessRequest(
-            final HttpRequestWrapper request,
+            final RoutedHttpRequest request,
             final HttpCacheEntry entry,
             final Date now) {
-        for(final Header h : request.getHeaders(HeaderConstants.CACHE_CONTROL)) {
-            for(final HeaderElement elt : h.getElements()) {
-                if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
-                    try {
-                        final int maxstale = Integer.parseInt(elt.getValue());
-                        final long age = validityPolicy.getCurrentAgeSecs(entry, now);
-                        final long lifetime = validityPolicy.getFreshnessLifetimeSecs(entry);
-                        if (age - lifetime > maxstale) {
-                            return true;
-                        }
-                    } catch (final NumberFormatException nfe) {
+        final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
+                try {
+                    final int maxstale = Integer.parseInt(elt.getValue());
+                    final long age = validityPolicy.getCurrentAgeSecs(entry, now);
+                    final long lifetime = validityPolicy.getFreshnessLifetimeSecs(entry);
+                    if (age - lifetime > maxstale) {
                         return true;
                     }
-                } else if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())
-                            || HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
+                } catch (final NumberFormatException nfe) {
                     return true;
                 }
+            } else if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())
+                    || HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
+                return true;
             }
         }
         return false;
@@ -517,7 +501,7 @@ public class CachingExec implements Clie
 
     private String generateViaHeader(final HttpMessage msg) {
 
-        final ProtocolVersion pv = msg.getProtocolVersion();
+        final ProtocolVersion pv = msg.getVersion() != null ? msg.getVersion() : HttpVersion.DEFAULT;
         final String existingEntry = viaHeaders.get(pv);
         if (existingEntry != null) {
             return existingEntry;
@@ -562,13 +546,11 @@ public class CachingExec implements Clie
     }
 
     boolean clientRequestsOurOptions(final HttpRequest request) {
-        final RequestLine line = request.getRequestLine();
-
-        if (!HeaderConstants.OPTIONS_METHOD.equals(line.getMethod())) {
+        if (!HeaderConstants.OPTIONS_METHOD.equals(request.getMethod())) {
             return false;
         }
 
-        if (!"*".equals(line.getUri())) {
+        if (!"*".equals(request.getRequestUri())) {
             return false;
         }
 
@@ -579,16 +561,15 @@ public class CachingExec implements Clie
         return true;
     }
 
-    CloseableHttpResponse callBackend(
-            final HttpRoute route,
-            final HttpRequestWrapper request,
+    ClassicHttpResponse callBackend(
+            final RoutedHttpRequest request,
             final HttpClientContext context,
             final HttpExecutionAware execAware) throws IOException, HttpException  {
 
         final Date requestDate = getCurrentDate();
 
         log.trace("Calling the backend");
-        final CloseableHttpResponse backendResponse = backend.execute(route, request, context, execAware);
+        final ClassicHttpResponse backendResponse = backend.execute(request, context, execAware);
         try {
             backendResponse.addHeader("Via", generateViaHeader(backendResponse));
             return handleBackendResponse(request, context, requestDate, getCurrentDate(),
@@ -620,24 +601,22 @@ public class CachingExec implements Clie
         return false;
     }
 
-    CloseableHttpResponse negotiateResponseFromVariants(
-            final HttpRoute route,
-            final HttpRequestWrapper request,
+    ClassicHttpResponse negotiateResponseFromVariants(
+            final RoutedHttpRequest request,
             final HttpClientContext context,
             final HttpExecutionAware execAware,
             final Map<String, Variant> variants) throws IOException, HttpException {
-        final HttpRequestWrapper conditionalRequest = conditionalRequestBuilder
+        final RoutedHttpRequest conditionalRequest = conditionalRequestBuilder
             .buildConditionalRequestFromVariants(request, variants);
 
         final Date requestDate = getCurrentDate();
-        final CloseableHttpResponse backendResponse = backend.execute(
-                route, conditionalRequest, context, execAware);
+        final ClassicHttpResponse backendResponse = backend.execute(conditionalRequest, context, execAware);
         try {
             final Date responseDate = getCurrentDate();
 
             backendResponse.addHeader("Via", generateViaHeader(backendResponse));
 
-            if (backendResponse.getStatusLine().getStatusCode() != HttpStatus.SC_NOT_MODIFIED) {
+            if (backendResponse.getCode() != HttpStatus.SC_NOT_MODIFIED) {
                 return handleBackendResponse(request, context, requestDate, responseDate,
                         backendResponse);
             }
@@ -647,7 +626,7 @@ public class CachingExec implements Clie
                 log.warn("304 response did not contain ETag");
                 IOUtils.consume(backendResponse.getEntity());
                 backendResponse.close();
-                return callBackend(route, request, context, execAware);
+                return callBackend(request, context, execAware);
             }
 
             final String resultEtag = resultEtagHeader.getValue();
@@ -656,7 +635,7 @@ public class CachingExec implements Clie
                 log.debug("304 response did not contain ETag matching one sent in If-None-Match");
                 IOUtils.consume(backendResponse.getEntity());
                 backendResponse.close();
-                return callBackend(route, request, context, execAware);
+                return callBackend(request, context, execAware);
             }
 
             final HttpCacheEntry matchedEntry = matchingVariant.getEntry();
@@ -664,18 +643,18 @@ public class CachingExec implements Clie
             if (revalidationResponseIsTooOld(backendResponse, matchedEntry)) {
                 IOUtils.consume(backendResponse.getEntity());
                 backendResponse.close();
-                return retryRequestUnconditionally(route, request, context, execAware, matchedEntry);
+                return retryRequestUnconditionally(request, context, execAware);
             }
 
             recordCacheUpdate(context);
 
             final HttpCacheEntry responseEntry = getUpdatedVariantEntry(
-                context.getTargetHost(), conditionalRequest, requestDate, responseDate,
+                request.getTargetHost(), conditionalRequest, requestDate, responseDate,
                     backendResponse, matchingVariant, matchedEntry);
             backendResponse.close();
 
-            final CloseableHttpResponse resp = responseGenerator.generateResponse(request, responseEntry);
-            tryToUpdateVariantMap(context.getTargetHost(), request, matchingVariant);
+            final ClassicHttpResponse resp = responseGenerator.generateResponse(request, responseEntry);
+            tryToUpdateVariantMap(request.getTargetHost(), request, matchingVariant);
 
             if (shouldSendNotModifiedResponse(request, responseEntry)) {
                 return responseGenerator.generateNotModifiedResponse(responseEntry);
@@ -687,23 +666,20 @@ public class CachingExec implements Clie
         }
     }
 
-    private CloseableHttpResponse retryRequestUnconditionally(
-            final HttpRoute route,
-            final HttpRequestWrapper request,
+    private ClassicHttpResponse retryRequestUnconditionally(
+            final RoutedHttpRequest request,
             final HttpClientContext context,
-            final HttpExecutionAware execAware,
-            final HttpCacheEntry matchedEntry) throws IOException, HttpException {
-        final HttpRequestWrapper unconditional = conditionalRequestBuilder
-            .buildUnconditionalRequest(request, matchedEntry);
-        return callBackend(route, unconditional, context, execAware);
+            final HttpExecutionAware execAware) throws IOException, HttpException {
+        final RoutedHttpRequest unconditional = conditionalRequestBuilder.buildUnconditionalRequest(request);
+        return callBackend(unconditional, context, execAware);
     }
 
     private HttpCacheEntry getUpdatedVariantEntry(
             final HttpHost target,
-            final HttpRequestWrapper conditionalRequest,
+            final RoutedHttpRequest conditionalRequest,
             final Date requestDate,
             final Date responseDate,
-            final CloseableHttpResponse backendResponse,
+            final ClassicHttpResponse backendResponse,
             final Variant matchingVariant,
             final HttpCacheEntry matchedEntry) throws IOException {
         HttpCacheEntry responseEntry = matchedEntry;
@@ -720,7 +696,7 @@ public class CachingExec implements Clie
 
     private void tryToUpdateVariantMap(
             final HttpHost target,
-            final HttpRequestWrapper request,
+            final RoutedHttpRequest request,
             final Variant matchingVariant) {
         try {
             responseCache.reuseVariantEntryFor(target, request, matchingVariant);
@@ -730,53 +706,42 @@ public class CachingExec implements Clie
     }
 
     private boolean shouldSendNotModifiedResponse(
-            final HttpRequestWrapper request,
+            final RoutedHttpRequest request,
             final HttpCacheEntry responseEntry) {
         return (suitabilityChecker.isConditional(request)
                 && suitabilityChecker.allConditionalsMatch(request, responseEntry, new Date()));
     }
 
-    CloseableHttpResponse revalidateCacheEntry(
-            final HttpRoute route,
-            final HttpRequestWrapper request,
+    ClassicHttpResponse revalidateCacheEntry(
+            final RoutedHttpRequest request,
             final HttpClientContext context,
             final HttpExecutionAware execAware,
             final HttpCacheEntry cacheEntry) throws IOException, HttpException {
 
-        final HttpRequestWrapper conditionalRequest = conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry);
-        final URI uri = conditionalRequest.getURI();
-        if (uri != null) {
-            try {
-                conditionalRequest.setURI(URIUtils.rewriteURIForRoute(uri, route));
-            } catch (final URISyntaxException ex) {
-                throw new ProtocolException("Invalid URI: " + uri, ex);
-            }
-        }
+        final RoutedHttpRequest conditionalRequest = conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry);
 
         Date requestDate = getCurrentDate();
-        CloseableHttpResponse backendResponse = backend.execute(
-                route, conditionalRequest, context, execAware);
+        ClassicHttpResponse backendResponse = backend.execute(conditionalRequest, context, execAware);
         Date responseDate = getCurrentDate();
 
         if (revalidationResponseIsTooOld(backendResponse, cacheEntry)) {
             backendResponse.close();
-            final HttpRequestWrapper unconditional = conditionalRequestBuilder
-                .buildUnconditionalRequest(request, cacheEntry);
+            final RoutedHttpRequest unconditional = conditionalRequestBuilder.buildUnconditionalRequest(request);
             requestDate = getCurrentDate();
-            backendResponse = backend.execute(route, unconditional, context, execAware);
+            backendResponse = backend.execute(unconditional, context, execAware);
             responseDate = getCurrentDate();
         }
 
         backendResponse.addHeader(HeaderConstants.VIA, generateViaHeader(backendResponse));
 
-        final int statusCode = backendResponse.getStatusLine().getStatusCode();
+        final int statusCode = backendResponse.getCode();
         if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
             recordCacheUpdate(context);
         }
 
         if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
             final HttpCacheEntry updatedEntry = responseCache.updateCacheEntry(
-                    context.getTargetHost(), request, cacheEntry,
+                    request.getTargetHost(), request, cacheEntry,
                     backendResponse, requestDate, responseDate);
             if (suitabilityChecker.isConditional(request)
                     && suitabilityChecker.allConditionalsMatch(request, updatedEntry, new Date())) {
@@ -790,7 +755,7 @@ public class CachingExec implements Clie
             && !staleResponseNotAllowed(request, cacheEntry, getCurrentDate())
             && validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)) {
             try {
-                final CloseableHttpResponse cachedResponse = responseGenerator.generateResponse(request, cacheEntry);
+                final ClassicHttpResponse cachedResponse = responseGenerator.generateResponse(request, cacheEntry);
                 cachedResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"");
                 return cachedResponse;
             } finally {
@@ -808,23 +773,22 @@ public class CachingExec implements Clie
                 || statusCode == HttpStatus.SC_GATEWAY_TIMEOUT;
     }
 
-    CloseableHttpResponse handleBackendResponse(
-            final HttpRequestWrapper request,
+    ClassicHttpResponse handleBackendResponse(
+            final RoutedHttpRequest request,
             final HttpClientContext context,
             final Date requestDate,
             final Date responseDate,
-            final CloseableHttpResponse backendResponse) throws IOException {
+            final ClassicHttpResponse backendResponse) throws IOException {
 
         log.trace("Handling Backend response");
         responseCompliance.ensureProtocolCompliance(request, backendResponse);
 
-        final HttpHost target = context.getTargetHost();
+        final HttpHost target = request.getTargetHost();
         final boolean cacheable = responseCachingPolicy.isResponseCacheable(request, backendResponse);
         responseCache.flushInvalidatedCacheEntriesFor(target, request, backendResponse);
         if (cacheable && !alreadyHaveNewerCacheEntry(target, request, backendResponse)) {
             storeRequestIfModifiedSinceFor304Response(request, backendResponse);
-            return responseCache.cacheAndReturnResponse(target, request,
-                    backendResponse, requestDate, responseDate);
+            return responseCache.cacheAndReturnResponse(target, request, backendResponse, requestDate, responseDate);
         }
         if (!cacheable) {
             try {
@@ -846,7 +810,7 @@ public class CachingExec implements Clie
      */
     private void storeRequestIfModifiedSinceFor304Response(
             final HttpRequest request, final HttpResponse backendResponse) {
-        if (backendResponse.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
+        if (backendResponse.getCode() == HttpStatus.SC_NOT_MODIFIED) {
             final Header h = request.getFirstHeader("If-Modified-Since");
             if (h != null) {
                 backendResponse.addHeader("Last-Modified", h.getValue());
@@ -854,7 +818,7 @@ public class CachingExec implements Clie
         }
     }
 
-    private boolean alreadyHaveNewerCacheEntry(final HttpHost target, final HttpRequestWrapper request,
+    private boolean alreadyHaveNewerCacheEntry(final HttpHost target, final RoutedHttpRequest request,
             final HttpResponse backendResponse) {
         HttpCacheEntry existing = null;
         try {

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClients.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClients.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClients.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClients.java Tue Dec 27 19:48:07 2016
@@ -30,7 +30,8 @@ package org.apache.hc.client5.http.impl.
 import java.io.File;
 
 import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
-import org.apache.hc.core5.annotation.Immutable;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 
 /**
  * Factory methods for {@link CloseableHttpClient} instances
@@ -38,7 +39,7 @@ import org.apache.hc.core5.annotation.Im
  *
  * @since 4.3
  */
-@Immutable
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
 public class CachingHttpClients {
 
     private CachingHttpClients() {

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CombinedEntity.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CombinedEntity.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CombinedEntity.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CombinedEntity.java Tue Dec 27 19:48:07 2016
@@ -33,11 +33,9 @@ import java.io.OutputStream;
 import java.io.SequenceInputStream;
 
 import org.apache.hc.client5.http.cache.Resource;
-import org.apache.hc.core5.annotation.NotThreadSafe;
-import org.apache.hc.core5.http.entity.AbstractHttpEntity;
+import org.apache.hc.core5.http.io.entity.AbstractHttpEntity;
 import org.apache.hc.core5.util.Args;
 
-@NotThreadSafe
 class CombinedEntity extends AbstractHttpEntity {
 
     private final Resource resource;
@@ -82,6 +80,11 @@ class CombinedEntity extends AbstractHtt
         }
     }
 
+    @Override
+    public void close() throws IOException {
+        dispose();
+    }
+
     private void dispose() {
         this.resource.dispose();
     }

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ConditionalRequestBuilder.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ConditionalRequestBuilder.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ConditionalRequestBuilder.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ConditionalRequestBuilder.java Tue Dec 27 19:48:07 2016
@@ -26,12 +26,15 @@
  */
 package org.apache.hc.client5.http.impl.cache;
 
+import java.util.Iterator;
 import java.util.Map;
 
 import org.apache.hc.client5.http.cache.HeaderConstants;
 import org.apache.hc.client5.http.cache.HttpCacheEntry;
-import org.apache.hc.client5.http.methods.HttpRequestWrapper;
-import org.apache.hc.core5.annotation.Immutable;
+import org.apache.hc.client5.http.methods.RoutedHttpRequest;
+import org.apache.hc.core5.http.message.MessageSupport;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HeaderElement;
 import org.apache.hc.core5.http.ProtocolException;
@@ -39,7 +42,7 @@ import org.apache.hc.core5.http.Protocol
 /**
  * @since 4.1
  */
-@Immutable
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
 class ConditionalRequestBuilder {
 
     /**
@@ -53,9 +56,9 @@ class ConditionalRequestBuilder {
      * @return the wrapped request
      * @throws ProtocolException when I am unable to build a new origin request.
      */
-    public HttpRequestWrapper buildConditionalRequest(final HttpRequestWrapper request, final HttpCacheEntry cacheEntry)
+    public RoutedHttpRequest buildConditionalRequest(final RoutedHttpRequest request, final HttpCacheEntry cacheEntry)
             throws ProtocolException {
-        final HttpRequestWrapper newRequest = HttpRequestWrapper.wrap(request.getOriginal(), request.getTarget());
+        final RoutedHttpRequest newRequest = RoutedHttpRequest.adapt(request.getOriginal(), request.getRoute());
         newRequest.setHeaders(request.getAllHeaders());
         final Header eTag = cacheEntry.getFirstHeader(HeaderConstants.ETAG);
         if (eTag != null) {
@@ -66,13 +69,13 @@ class ConditionalRequestBuilder {
             newRequest.setHeader(HeaderConstants.IF_MODIFIED_SINCE, lastModified.getValue());
         }
         boolean mustRevalidate = false;
-        for(final Header h : cacheEntry.getHeaders(HeaderConstants.CACHE_CONTROL)) {
-            for(final HeaderElement elt : h.getElements()) {
-                if (HeaderConstants.CACHE_CONTROL_MUST_REVALIDATE.equalsIgnoreCase(elt.getName())
+        final Iterator<HeaderElement> it = MessageSupport.iterate(cacheEntry, HeaderConstants.CACHE_CONTROL);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            if (HeaderConstants.CACHE_CONTROL_MUST_REVALIDATE.equalsIgnoreCase(elt.getName())
                     || HeaderConstants.CACHE_CONTROL_PROXY_REVALIDATE.equalsIgnoreCase(elt.getName())) {
-                    mustRevalidate = true;
-                    break;
-                }
+                mustRevalidate = true;
+                break;
             }
         }
         if (mustRevalidate) {
@@ -93,9 +96,9 @@ class ConditionalRequestBuilder {
      * @param variants
      * @return the wrapped request
      */
-    public HttpRequestWrapper buildConditionalRequestFromVariants(final HttpRequestWrapper request,
-            final Map<String, Variant> variants) {
-        final HttpRequestWrapper newRequest = HttpRequestWrapper.wrap(request.getOriginal(), request.getTarget());
+    public RoutedHttpRequest buildConditionalRequestFromVariants(final RoutedHttpRequest request,
+                                                                 final Map<String, Variant> variants) {
+        final RoutedHttpRequest newRequest = RoutedHttpRequest.adapt(request.getOriginal(), request.getRoute());
         newRequest.setHeaders(request.getAllHeaders());
 
         // we do not support partial content so all etags are used
@@ -121,11 +124,10 @@ class ConditionalRequestBuilder {
      * our current cache entry. In this case, the protocol recommendation
      * is to retry the validation and force syncup with the origin.
      * @param request client request we are trying to satisfy
-     * @param entry existing cache entry we are trying to validate
      * @return an unconditional validation request
      */
-    public HttpRequestWrapper buildUnconditionalRequest(final HttpRequestWrapper request, final HttpCacheEntry entry) {
-        final HttpRequestWrapper newRequest = HttpRequestWrapper.wrap(request.getOriginal(), request.getTarget());
+    public RoutedHttpRequest buildUnconditionalRequest(final RoutedHttpRequest request) {
+        final RoutedHttpRequest newRequest = RoutedHttpRequest.adapt(request.getOriginal(), request.getRoute());
         newRequest.setHeaders(request.getAllHeaders());
         newRequest.addHeader(HeaderConstants.CACHE_CONTROL,HeaderConstants.CACHE_CONTROL_NO_CACHE);
         newRequest.addHeader(HeaderConstants.PRAGMA,HeaderConstants.CACHE_CONTROL_NO_CACHE);

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/DefaultFailureCache.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/DefaultFailureCache.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/DefaultFailureCache.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/DefaultFailureCache.java Tue Dec 27 19:48:07 2016
@@ -30,7 +30,8 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
-import org.apache.hc.core5.annotation.ThreadSafe;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 
 /**
  * Implements a bounded failure cache. The oldest entries are discarded when
@@ -38,7 +39,7 @@ import org.apache.hc.core5.annotation.Th
  *
  * @since 4.3
  */
-@ThreadSafe
+@Contract(threading = ThreadingBehavior.SAFE)
 public class DefaultFailureCache implements FailureCache {
 
     static final int DEFAULT_MAX_SIZE = 1000;

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/DefaultHttpCacheEntrySerializer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/DefaultHttpCacheEntrySerializer.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/DefaultHttpCacheEntrySerializer.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/DefaultHttpCacheEntrySerializer.java Tue Dec 27 19:48:07 2016
@@ -35,7 +35,8 @@ import java.io.OutputStream;
 import org.apache.hc.client5.http.cache.HttpCacheEntry;
 import org.apache.hc.client5.http.cache.HttpCacheEntrySerializationException;
 import org.apache.hc.client5.http.cache.HttpCacheEntrySerializer;
-import org.apache.hc.core5.annotation.Immutable;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 
 /**
  * {@link HttpCacheEntrySerializer} implementation that uses the default (native)
@@ -45,7 +46,7 @@ import org.apache.hc.core5.annotation.Im
  *
  * @since 4.1
  */
-@Immutable
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
 public class DefaultHttpCacheEntrySerializer implements HttpCacheEntrySerializer {
 
     @Override

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ExponentialBackOffSchedulingStrategy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ExponentialBackOffSchedulingStrategy.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ExponentialBackOffSchedulingStrategy.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ExponentialBackOffSchedulingStrategy.java Tue Dec 27 19:48:07 2016
@@ -30,7 +30,8 @@ import java.util.concurrent.ScheduledExe
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.hc.core5.annotation.ThreadSafe;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -56,7 +57,7 @@ import org.apache.hc.core5.util.Args;
  *
  * @since 4.3
  */
-@ThreadSafe
+@Contract(threading = ThreadingBehavior.SAFE)
 public class ExponentialBackOffSchedulingStrategy implements SchedulingStrategy {
 
     public static final long DEFAULT_BACK_OFF_RATE = 10;

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/FailureCacheValue.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/FailureCacheValue.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/FailureCacheValue.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/FailureCacheValue.java Tue Dec 27 19:48:07 2016
@@ -26,14 +26,15 @@
  */
 package org.apache.hc.client5.http.impl.cache;
 
-import org.apache.hc.core5.annotation.Immutable;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 
 /**
  * The error count with a creation timestamp and its associated key.
  *
  * @since 4.3
  */
-@Immutable
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
 public class FailureCacheValue {
 
     private final long creationTimeInNanos;

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/FileResource.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/FileResource.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/FileResource.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/FileResource.java Tue Dec 27 19:48:07 2016
@@ -32,14 +32,15 @@ import java.io.IOException;
 import java.io.InputStream;
 
 import org.apache.hc.client5.http.cache.Resource;
-import org.apache.hc.core5.annotation.ThreadSafe;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 
 /**
  * Cache resource backed by a file.
  *
  * @since 4.1
  */
-@ThreadSafe
+@Contract(threading = ThreadingBehavior.SAFE)
 public class FileResource implements Resource {
 
     private static final long serialVersionUID = 4132244415919043397L;