hc-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject svn commit: r1793308 [9/11] - in /httpcomponents/httpclient/trunk: httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/ httpclient5-cache/src/test/java/org/apache/...
Date Mon, 01 May 2017 11:11:11 GMT
Modified: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ProtocolExec.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ProtocolExec.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ProtocolExec.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ProtocolExec.java Mon May  1 11:11:09 2017
@@ -28,19 +28,24 @@
 package org.apache.hc.client5.http.impl.sync;
 
 import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
 
 import org.apache.hc.client5.http.HttpRoute;
-import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.auth.CredentialsStore;
-import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
-import org.apache.hc.client5.http.config.AuthSchemes;
+import org.apache.hc.client5.http.auth.util.CredentialSupport;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
-import org.apache.hc.client5.http.sync.methods.HttpExecutionAware;
+import org.apache.hc.client5.http.sync.ExecChain;
+import org.apache.hc.client5.http.sync.ExecChainHandler;
+import org.apache.hc.client5.http.utils.URIUtils;
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.protocol.HttpCoreContext;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.net.URIAuthority;
@@ -61,47 +66,46 @@ import org.apache.hc.core5.util.Args;
  * @since 4.3
  */
 @Contract(threading = ThreadingBehavior.IMMUTABLE)
-public class ProtocolExec implements ClientExecChain {
+final class ProtocolExec implements ExecChainHandler {
 
-    private final ClientExecChain requestExecutor;
     private final HttpProcessor httpProcessor;
 
-    public ProtocolExec(final ClientExecChain requestExecutor, final HttpProcessor httpProcessor) {
-        Args.notNull(requestExecutor, "HTTP client request executor");
+    public ProtocolExec(final HttpProcessor httpProcessor) {
         Args.notNull(httpProcessor, "HTTP protocol processor");
-        this.requestExecutor = requestExecutor;
         this.httpProcessor = httpProcessor;
     }
 
     @Override
     public ClassicHttpResponse execute(
-            final RoutedHttpRequest request,
-            final HttpClientContext context,
-            final HttpExecutionAware execAware) throws IOException, HttpException {
+            final ClassicHttpRequest request,
+            final ExecChain.Scope scope,
+            final ExecChain chain) throws IOException, HttpException {
         Args.notNull(request, "HTTP request");
-        Args.notNull(context, "HTTP context");
+        Args.notNull(scope, "Scope");
+
+        final HttpRoute route = scope.route;
+        final HttpClientContext context = scope.clientContext;
+
+        if (route.getProxyHost() != null && !route.isTunnelled()) {
+            try {
+                URI uri = request.getUri();
+                if (!uri.isAbsolute()) {
+                    final HttpHost target = route.getTargetHost();
+                    uri = URIUtils.rewriteURI(uri, target, true);
+                } else {
+                    uri = URIUtils.rewriteURI(uri);
+                }
+                request.setPath(uri.toASCIIString());
+            } catch (final URISyntaxException ex) {
+                throw new ProtocolException("Invalid URI: " + request.getRequestUri(), ex);
+            }
+        }
 
-        final HttpRoute route = request.getRoute();
         final URIAuthority authority = request.getAuthority();
         if (authority != null) {
-            final String userinfo = authority.getUserInfo();
-            if (userinfo != null) {
-                final CredentialsProvider credsProvider = context.getCredentialsProvider();
-                if (credsProvider instanceof CredentialsStore) {
-                    final int atColon = userinfo.indexOf(':');
-                    final String userName;
-                    final char[] password;
-                    if (atColon >= 0) {
-                        userName = userinfo.substring(0, atColon);
-                        password = userinfo.substring(atColon + 1).toCharArray();
-                    } else {
-                        userName = userinfo.substring(0, atColon);
-                        password = null;
-                    }
-                    ((CredentialsStore) credsProvider).setCredentials(
-                            new AuthScope(authority.getHostName(), authority.getPort(), null, AuthSchemes.BASIC),
-                            new UsernamePasswordCredentials(userName, password));
-                }
+            final CredentialsProvider credsProvider = context.getCredentialsProvider();
+            if (credsProvider instanceof CredentialsStore) {
+                CredentialSupport.extractFromAuthority(authority, (CredentialsStore) credsProvider);
             }
         }
 
@@ -111,7 +115,7 @@ public class ProtocolExec implements Cli
 
         this.httpProcessor.process(request, request.getEntity(), context);
 
-        final ClassicHttpResponse response = this.requestExecutor.execute(request, context, execAware);
+        final ClassicHttpResponse response = chain.proceed(request, scope);
         try {
             // Run response protocol interceptors
             context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);

Modified: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/RedirectExec.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/RedirectExec.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/RedirectExec.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/RedirectExec.java Mon May  1 11:11:09 2017
@@ -29,10 +29,10 @@ package org.apache.hc.client5.http.impl.
 
 import java.io.IOException;
 import java.net.URI;
-import java.net.URISyntaxException;
 import java.util.List;
 
 import org.apache.hc.client5.http.HttpRoute;
+import org.apache.hc.client5.http.StandardMethods;
 import org.apache.hc.client5.http.auth.AuthExchange;
 import org.apache.hc.client5.http.auth.AuthScheme;
 import org.apache.hc.client5.http.config.RequestConfig;
@@ -40,7 +40,10 @@ import org.apache.hc.client5.http.protoc
 import org.apache.hc.client5.http.protocol.RedirectException;
 import org.apache.hc.client5.http.protocol.RedirectStrategy;
 import org.apache.hc.client5.http.routing.HttpRoutePlanner;
-import org.apache.hc.client5.http.sync.methods.HttpExecutionAware;
+import org.apache.hc.client5.http.sync.ExecChain;
+import org.apache.hc.client5.http.sync.ExecChainHandler;
+import org.apache.hc.client5.http.sync.methods.HttpGet;
+import org.apache.hc.client5.http.sync.methods.RequestBuilder;
 import org.apache.hc.client5.http.utils.URIUtils;
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
@@ -48,6 +51,7 @@ import org.apache.hc.core5.http.ClassicH
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.io.entity.EntityUtils;
 import org.apache.hc.core5.util.Args;
@@ -66,34 +70,32 @@ import org.apache.logging.log4j.Logger;
  * @since 4.3
  */
 @Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL)
-public class RedirectExec implements ClientExecChain {
+final class RedirectExec implements ExecChainHandler {
 
     private final Logger log = LogManager.getLogger(getClass());
 
-    private final ClientExecChain requestExecutor;
     private final RedirectStrategy redirectStrategy;
     private final HttpRoutePlanner routePlanner;
 
     public RedirectExec(
-            final ClientExecChain requestExecutor,
             final HttpRoutePlanner routePlanner,
             final RedirectStrategy redirectStrategy) {
         super();
-        Args.notNull(requestExecutor, "HTTP client request executor");
         Args.notNull(routePlanner, "HTTP route planner");
         Args.notNull(redirectStrategy, "HTTP redirect strategy");
-        this.requestExecutor = requestExecutor;
         this.routePlanner = routePlanner;
         this.redirectStrategy = redirectStrategy;
     }
 
     @Override
     public ClassicHttpResponse execute(
-            final RoutedHttpRequest request,
-            final HttpClientContext context,
-            final HttpExecutionAware execAware) throws IOException, HttpException {
+            final ClassicHttpRequest request,
+            final ExecChain.Scope scope,
+            final ExecChain chain) throws IOException, HttpException {
         Args.notNull(request, "HTTP request");
-        Args.notNull(context, "HTTP context");
+        Args.notNull(scope, "Scope");
+
+        final HttpClientContext context = scope.clientContext;
 
         final List<URI> redirectLocations = context.getRedirectLocations();
         if (redirectLocations != null) {
@@ -102,36 +104,48 @@ public class RedirectExec implements Cli
 
         final RequestConfig config = context.getRequestConfig();
         final int maxRedirects = config.getMaxRedirects() > 0 ? config.getMaxRedirects() : 50;
-        HttpRoute currentRoute = request.getRoute();
-        RoutedHttpRequest currentRequest = request;
+        ClassicHttpRequest currentRequest = request;
+        ExecChain.Scope currentScope = scope;
         for (int redirectCount = 0;;) {
-            final ClassicHttpResponse response = requestExecutor.execute(currentRequest, context, execAware);
+            final ClassicHttpResponse response = chain.proceed(currentRequest, currentScope);
             try {
-                if (config.isRedirectsEnabled() &&
-                        this.redirectStrategy.isRedirected(currentRequest.getOriginal(), response, context)) {
+                if (config.isRedirectsEnabled() && this.redirectStrategy.isRedirected(request, response, context)) {
 
                     if (redirectCount >= maxRedirects) {
                         throw new RedirectException("Maximum redirects ("+ maxRedirects + ") exceeded");
                     }
                     redirectCount++;
 
-                    final ClassicHttpRequest redirect = this.redirectStrategy.getRedirect(
-                            currentRequest.getOriginal(), response, context);
-                    final URI redirectUri;
-                    try {
-                        redirectUri = redirect.getUri();
-                    } catch (final URISyntaxException ex) {
-                        // Should not happen
-                        throw new ProtocolException(ex.getMessage(), ex);
+                    final URI redirectUri = this.redirectStrategy.getLocationURI(currentRequest, response, context);
+                    final ClassicHttpRequest originalRequest = scope.originalRequest;
+                    ClassicHttpRequest redirect = null;
+                    final int statusCode = response.getCode();
+                    switch (statusCode) {
+                        case HttpStatus.SC_MOVED_PERMANENTLY:
+                        case HttpStatus.SC_MOVED_TEMPORARILY:
+                        case HttpStatus.SC_SEE_OTHER:
+                            if (!StandardMethods.isSafe(request.getMethod())) {
+                                final HttpGet httpGet = new HttpGet(redirectUri);
+                                httpGet.setHeaders(originalRequest.getAllHeaders());
+                                redirect = httpGet;
+                            } else {
+                                redirect = null;
+                            }
+                    }
+                    if (redirect == null) {
+                        redirect = RequestBuilder.copy(originalRequest).setUri(redirectUri).build();
                     }
+
                     final HttpHost newTarget = URIUtils.extractHost(redirectUri);
                     if (newTarget == null) {
                         throw new ProtocolException("Redirect URI does not specify a valid host name: " +
                                 redirectUri);
                     }
 
-                    // Reset virtual host and auth states if redirecting to another host
-                    if (!currentRoute.getTargetHost().equals(newTarget)) {
+                    HttpRoute currentRoute = currentScope.route;
+                    final boolean crossSiteRedirect = !currentRoute.getTargetHost().equals(newTarget);
+                    if (crossSiteRedirect) {
+
                         final AuthExchange targetAuthExchange = context.getAuthExchange(currentRoute.getTargetHost());
                         this.log.debug("Resetting target auth state");
                         targetAuthExchange.reset();
@@ -143,13 +157,18 @@ public class RedirectExec implements Cli
                                 proxyAuthExchange.reset();
                             }
                         }
+                        currentRoute = this.routePlanner.determineRoute(newTarget, context);
+                        currentScope = new ExecChain.Scope(
+                                currentRoute,
+                                currentScope.originalRequest,
+                                currentScope.execRuntime,
+                                currentScope.clientContext);
                     }
 
-                    currentRoute = this.routePlanner.determineRoute(newTarget, context);
                     if (this.log.isDebugEnabled()) {
                         this.log.debug("Redirecting to '" + redirectUri + "' via " + currentRoute);
                     }
-                    currentRequest = RoutedHttpRequest.adapt(redirect, currentRoute);
+                    currentRequest = redirect;
                     RequestEntityProxy.enhance(currentRequest);
 
                     EntityUtils.consume(response.getEntity());

Copied: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/RequestFailedException.java (from r1793305, httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/auth/CredentialsStore.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/RequestFailedException.java?p2=httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/RequestFailedException.java&p1=httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/auth/CredentialsStore.java&r1=1793305&r2=1793308&rev=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/auth/CredentialsStore.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/RequestFailedException.java Mon May  1 11:11:09 2017
@@ -24,34 +24,29 @@
  * <http://www.apache.org/>.
  *
  */
-package org.apache.hc.client5.http.auth;
+
+package org.apache.hc.client5.http.impl.sync;
+
+import java.io.InterruptedIOException;
 
 /**
- * Abstract store of authentication credentials.
- * <p>
- * Implementations of this interface must be thread-safe. Access to shared
- * data must be synchronized as methods of this interface may be executed
- * from multiple threads.
+ * Signals that the request has been aborted or failed due to an expected condition.
  *
- * @since 4.0
+ * @since 5.0
  */
-public interface CredentialsStore extends CredentialsProvider {
+public class RequestFailedException extends InterruptedIOException {
+
+    private static final long serialVersionUID = 4973849966012490112L;
+
+    public RequestFailedException(final String message) {
+        super(message);
+    }
 
-    /**
-     * Sets the {@link Credentials credentials} for the given authentication
-     * scope. Any previous credentials for the given scope will be overwritten.
-     *
-     * @param authscope the {@link AuthScope authentication scope}
-     * @param credentials the authentication {@link Credentials credentials}
-     * for the given scope.
-     *
-     * @see #getCredentials(AuthScope, HttpContext)
-     */
-    void setCredentials(AuthScope authscope, Credentials credentials);
-
-    /**
-     * Clears all credentials.
-     */
-    void clear();
+    public RequestFailedException(final String message, final Throwable cause) {
+        super(message);
+        if (cause != null) {
+            initCause(cause);
+        }
+    }
 
 }

Modified: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ResponseEntityProxy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ResponseEntityProxy.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ResponseEntityProxy.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ResponseEntityProxy.java Mon May  1 11:11:09 2017
@@ -32,6 +32,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.SocketException;
 
+import org.apache.hc.client5.http.sync.ExecRuntime;
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.HttpEntity;
 import org.apache.hc.core5.http.io.EofSensorInputStream;
@@ -45,35 +46,38 @@ import org.apache.hc.core5.http.io.entit
  */
 class ResponseEntityProxy extends HttpEntityWrapper implements EofSensorWatcher {
 
-    private final EndpointHolder endpointHolder;
+    private final ExecRuntime execRuntime;
 
-    public static void enchance(final ClassicHttpResponse response, final EndpointHolder connHolder) {
+    public static void enchance(final ClassicHttpResponse response, final ExecRuntime execRuntime) {
         final HttpEntity entity = response.getEntity();
-        if (entity != null && entity.isStreaming() && connHolder != null) {
-            response.setEntity(new ResponseEntityProxy(entity, connHolder));
+        if (entity != null && entity.isStreaming() && execRuntime != null) {
+            response.setEntity(new ResponseEntityProxy(entity, execRuntime));
         }
     }
 
-    ResponseEntityProxy(final HttpEntity entity, final EndpointHolder endpointHolder) {
+    ResponseEntityProxy(final HttpEntity entity, final ExecRuntime execRuntime) {
         super(entity);
-        this.endpointHolder = endpointHolder;
+        this.execRuntime = execRuntime;
     }
 
     private void cleanup() throws IOException {
-        if (this.endpointHolder != null) {
-            this.endpointHolder.close();
+        if (this.execRuntime != null) {
+            if (this.execRuntime.isConnected()) {
+                this.execRuntime.disconnect();
+            }
+            this.execRuntime.discardConnection();
         }
     }
 
-    private void abortConnection() {
-        if (this.endpointHolder != null) {
-            this.endpointHolder.abortConnection();
+    private void discardConnection() {
+        if (this.execRuntime != null) {
+            this.execRuntime.discardConnection();
         }
     }
 
     public void releaseConnection() {
-        if (this.endpointHolder != null) {
-            this.endpointHolder.releaseConnection();
+        if (this.execRuntime != null) {
+            this.execRuntime.releaseConnection();
         }
     }
 
@@ -95,7 +99,7 @@ class ResponseEntityProxy extends HttpEn
             }
             releaseConnection();
         } catch (IOException | RuntimeException ex) {
-            abortConnection();
+            discardConnection();
             throw ex;
         } finally {
             cleanup();
@@ -112,7 +116,7 @@ class ResponseEntityProxy extends HttpEn
             }
             releaseConnection();
         } catch (IOException | RuntimeException ex) {
-            abortConnection();
+            discardConnection();
             throw ex;
         } finally {
             cleanup();
@@ -123,7 +127,7 @@ class ResponseEntityProxy extends HttpEn
     @Override
     public boolean streamClosed(final InputStream wrapped) throws IOException {
         try {
-            final boolean open = endpointHolder != null && !endpointHolder.isReleased();
+            final boolean open = execRuntime != null && execRuntime.isConnectionAcquired();
             // this assumes that closing the stream will
             // consume the remainder of the response body:
             try {
@@ -137,7 +141,7 @@ class ResponseEntityProxy extends HttpEn
                 }
             }
         } catch (IOException | RuntimeException ex) {
-            abortConnection();
+            discardConnection();
             throw ex;
         } finally {
             cleanup();

Modified: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/RetryExec.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/RetryExec.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/RetryExec.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/RetryExec.java Mon May  1 11:11:09 2017
@@ -30,14 +30,16 @@ package org.apache.hc.client5.http.impl.
 import java.io.IOException;
 
 import org.apache.hc.client5.http.HttpRoute;
+import org.apache.hc.client5.http.impl.ExecSupport;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
 import org.apache.hc.client5.http.protocol.NonRepeatableRequestException;
+import org.apache.hc.client5.http.sync.ExecChain;
+import org.apache.hc.client5.http.sync.ExecChainHandler;
 import org.apache.hc.client5.http.sync.HttpRequestRetryHandler;
-import org.apache.hc.client5.http.sync.methods.HttpExecutionAware;
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
-import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.NoHttpResponseException;
 import org.apache.hc.core5.util.Args;
@@ -57,38 +59,34 @@ import org.apache.logging.log4j.Logger;
  * @since 4.3
  */
 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
-public class RetryExec implements ClientExecChain {
+final class RetryExec implements ExecChainHandler {
 
     private final Logger log = LogManager.getLogger(getClass());
 
-    private final ClientExecChain requestExecutor;
     private final HttpRequestRetryHandler retryHandler;
 
     public RetryExec(
-            final ClientExecChain requestExecutor,
             final HttpRequestRetryHandler retryHandler) {
-        Args.notNull(requestExecutor, "HTTP request executor");
         Args.notNull(retryHandler, "HTTP request retry handler");
-        this.requestExecutor = requestExecutor;
         this.retryHandler = retryHandler;
     }
 
     @Override
     public ClassicHttpResponse execute(
-            final RoutedHttpRequest request,
-            final HttpClientContext context,
-            final HttpExecutionAware execAware) throws IOException, HttpException {
+            final ClassicHttpRequest request,
+            final ExecChain.Scope scope,
+            final ExecChain chain) throws IOException, HttpException {
         Args.notNull(request, "HTTP request");
-        Args.notNull(context, "HTTP context");
-        final Header[] origheaders = request.getAllHeaders();
+        Args.notNull(scope, "Scope");
+        final HttpRoute route = scope.route;
+        final HttpClientContext context = scope.clientContext;
+        ClassicHttpRequest currentRequest = request;
         for (int execCount = 1;; execCount++) {
             try {
-                return this.requestExecutor.execute(request, context, execAware);
+                return chain.proceed(currentRequest, scope);
             } catch (final IOException ex) {
-                final HttpRoute route = request.getRoute();
-                if (execAware != null && execAware.isAborted()) {
-                    this.log.debug("Request has been aborted");
-                    throw ex;
+                if (scope.execRuntime.isExecutionAborted()) {
+                    throw new RequestFailedException("Request aborted");
                 }
                 if (retryHandler.retryRequest(request, ex, execCount, context)) {
                     if (this.log.isInfoEnabled()) {
@@ -106,7 +104,7 @@ public class RetryExec implements Client
                         throw new NonRepeatableRequestException("Cannot retry request " +
                                 "with a non-repeatable request entity", ex);
                     }
-                    request.setHeaders(origheaders);
+                    currentRequest = ExecSupport.copy(scope.originalRequest);
                     if (this.log.isInfoEnabled()) {
                         this.log.info("Retrying request to " + route);
                     }

Modified: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ServiceUnavailableRetryExec.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ServiceUnavailableRetryExec.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ServiceUnavailableRetryExec.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ServiceUnavailableRetryExec.java Mon May  1 11:11:09 2017
@@ -30,13 +30,15 @@ package org.apache.hc.client5.http.impl.
 import java.io.IOException;
 import java.io.InterruptedIOException;
 
+import org.apache.hc.client5.http.impl.ExecSupport;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.client5.http.sync.ExecChain;
+import org.apache.hc.client5.http.sync.ExecChainHandler;
 import org.apache.hc.client5.http.sync.ServiceUnavailableRetryStrategy;
-import org.apache.hc.client5.http.sync.methods.HttpExecutionAware;
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
-import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.util.Args;
 import org.apache.logging.log4j.LogManager;
@@ -55,31 +57,30 @@ import org.apache.logging.log4j.Logger;
  * @since 4.3
  */
 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
-public class ServiceUnavailableRetryExec implements ClientExecChain {
+final class ServiceUnavailableRetryExec implements ExecChainHandler {
 
     private final Logger log = LogManager.getLogger(getClass());
 
-    private final ClientExecChain requestExecutor;
     private final ServiceUnavailableRetryStrategy retryStrategy;
 
     public ServiceUnavailableRetryExec(
-            final ClientExecChain requestExecutor,
             final ServiceUnavailableRetryStrategy retryStrategy) {
         super();
-        Args.notNull(requestExecutor, "HTTP request executor");
         Args.notNull(retryStrategy, "Retry strategy");
-        this.requestExecutor = requestExecutor;
         this.retryStrategy = retryStrategy;
     }
 
     @Override
     public ClassicHttpResponse execute(
-            final RoutedHttpRequest request,
-            final HttpClientContext context,
-            final HttpExecutionAware execAware) throws IOException, HttpException {
-        final Header[] origheaders = request.getAllHeaders();
+            final ClassicHttpRequest request,
+            final ExecChain.Scope scope,
+            final ExecChain chain) throws IOException, HttpException {
+        Args.notNull(request, "HTTP request");
+        Args.notNull(scope, "Scope");
+        final HttpClientContext context = scope.clientContext;
+        ClassicHttpRequest currentRequest = request;
         for (int c = 1;; c++) {
-            final ClassicHttpResponse response = this.requestExecutor.execute(request, context, execAware);
+            final ClassicHttpResponse response = chain.proceed(currentRequest, scope);
             try {
                 if (this.retryStrategy.retryRequest(response, c, context)) {
                     response.close();
@@ -95,7 +96,7 @@ public class ServiceUnavailableRetryExec
                             throw new InterruptedIOException();
                         }
                     }
-                    request.setHeaders(origheaders);
+                    currentRequest = ExecSupport.copy(scope.originalRequest);
                 } else {
                     return response;
                 }

Modified: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/protocol/RedirectStrategy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/protocol/RedirectStrategy.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/protocol/RedirectStrategy.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/protocol/RedirectStrategy.java Mon May  1 11:11:09 2017
@@ -27,8 +27,8 @@
 
 package org.apache.hc.client5.http.protocol;
 
-import org.apache.hc.client5.http.sync.methods.HttpUriRequest;
-import org.apache.hc.core5.http.ClassicHttpRequest;
+import java.net.URI;
+
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
@@ -51,10 +51,9 @@ public interface RedirectStrategy {
      * Determines if a request should be redirected to a new location
      * given the response from the target server.
      *
-     * @param request the executed request
+     * @param request  the executed request
      * @param response the response received from the target server
-     * @param context the context for the request execution
-     *
+     * @param context  the context for the request execution
      * @return {@code true} if the request should be redirected, {@code false}
      * otherwise
      */
@@ -63,20 +62,9 @@ public interface RedirectStrategy {
             HttpResponse response,
             HttpContext context) throws HttpException;
 
-    /**
-     * Determines the redirect location given the response from the target
-     * server and the current request execution context and generates a new
-     * request to be sent to the location.
-     *
-     * @param request the executed request
-     * @param response the response received from the target server
-     * @param context the context for the request execution
-     *
-     * @return redirected request
-     */
-    HttpUriRequest getRedirect(
-            ClassicHttpRequest request,
-            HttpResponse response,
-            HttpContext context) throws HttpException;
+    URI getLocationURI(
+            final HttpRequest request,
+            final HttpResponse response,
+            final HttpContext context) throws HttpException;
 
 }

Copied: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecChain.java (from r1793305, httpcomponents/httpclient/trunk/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/DummyBackend.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecChain.java?p2=httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecChain.java&p1=httpcomponents/httpclient/trunk/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/DummyBackend.java&r1=1793305&r2=1793308&rev=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/DummyBackend.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecChain.java Mon May  1 11:11:09 2017
@@ -24,46 +24,38 @@
  * <http://www.apache.org/>.
  *
  */
-package org.apache.hc.client5.http.impl.cache;
+
+package org.apache.hc.client5.http.sync;
 
 import java.io.IOException;
 
-import org.apache.hc.client5.http.impl.sync.ClientExecChain;
+import org.apache.hc.client5.http.HttpRoute;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
-import org.apache.hc.client5.http.sync.methods.HttpExecutionAware;
-import org.apache.hc.client5.http.impl.sync.RoutedHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.HttpException;
-import org.apache.hc.core5.http.HttpRequest;
-import org.apache.hc.core5.http.HttpStatus;
-import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
-
-public class DummyBackend implements ClientExecChain {
-
-    private ClassicHttpRequest request;
-    private ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
-    private int executions = 0;
+import org.apache.hc.core5.util.Args;
 
-    public void setResponse(final ClassicHttpResponse resp) {
-        response = resp;
-    }
+public interface ExecChain {
 
-    public HttpRequest getCapturedRequest() {
-        return request;
-    }
+    final class Scope {
 
-    @Override
-    public ClassicHttpResponse execute(
-            final RoutedHttpRequest request,
-            final HttpClientContext clientContext,
-            final HttpExecutionAware execAware) throws IOException, HttpException {
-        this.request = request;
-        executions++;
-        return response;
-    }
+        public final HttpRoute route;
+        public final ClassicHttpRequest originalRequest;
+        public final ExecRuntime execRuntime;
+        public final HttpClientContext clientContext;
+
+        public Scope(final HttpRoute route, final ClassicHttpRequest originalRequest, final ExecRuntime execRuntime, final HttpClientContext clientContext) {
+            this.route = Args.notNull(route, "Route");
+            this.originalRequest = Args.notNull(originalRequest, "Original request");
+            this.execRuntime = Args.notNull(execRuntime, "Exec runtime");
+            this.clientContext = clientContext != null ? clientContext : HttpClientContext.create();
+        }
 
-    public int getExecutions() {
-        return executions;
     }
+
+    ClassicHttpResponse proceed(
+            ClassicHttpRequest request,
+            Scope scope) throws IOException, HttpException;
+
 }

Copied: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecChainHandler.java (from r1793305, httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ClientExecChain.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecChainHandler.java?p2=httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecChainHandler.java&p1=httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ClientExecChain.java&r1=1793305&r2=1793308&rev=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/ClientExecChain.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecChainHandler.java Mon May  1 11:11:09 2017
@@ -25,12 +25,11 @@
  *
  */
 
-package org.apache.hc.client5.http.impl.sync;
+package org.apache.hc.client5.http.sync;
 
 import java.io.IOException;
 
-import org.apache.hc.client5.http.protocol.HttpClientContext;
-import org.apache.hc.client5.http.sync.methods.HttpExecutionAware;
+import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.HttpException;
 
@@ -47,25 +46,11 @@ import org.apache.hc.core5.http.HttpExce
  *
  * @since 4.3
  */
-public interface ClientExecChain {
+public interface ExecChainHandler {
 
-    /**
-     * Executes th request either by transmitting it to the target server or
-     * by passing it onto the next executor in the request execution chain.
-     *
-     * @param request current request.
-     * @param clientContext current HTTP context.
-     * @param execAware receiver of notifications of blocking I/O operations.
-     * @return HTTP response either received from the opposite endpoint
-     *   or generated locally.
-     * @throws IOException in case of a I/O error.
-     *   (this type of exceptions are potentially recoverable).
-     * @throws HttpException in case of an HTTP protocol error
-     *   (usually this type of exceptions are non-recoverable).
-     */
     ClassicHttpResponse execute(
-            RoutedHttpRequest request,
-            HttpClientContext clientContext,
-            HttpExecutionAware execAware) throws IOException, HttpException;
+            ClassicHttpRequest request,
+            ExecChain.Scope scope,
+            ExecChain chain) throws IOException, HttpException;
 
 }

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecChainHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecChainHandler.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecChainHandler.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Copied: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecRuntime.java (from r1793305, httpcomponents/httpclient/trunk/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/DummyBackend.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecRuntime.java?p2=httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecRuntime.java&p1=httpcomponents/httpclient/trunk/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/DummyBackend.java&r1=1793305&r2=1793308&rev=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/DummyBackend.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/ExecRuntime.java Mon May  1 11:11:09 2017
@@ -24,46 +24,64 @@
  * <http://www.apache.org/>.
  *
  */
-package org.apache.hc.client5.http.impl.cache;
+
+package org.apache.hc.client5.http.sync;
 
 import java.io.IOException;
 
-import org.apache.hc.client5.http.impl.sync.ClientExecChain;
+import org.apache.hc.client5.http.HttpRoute;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
-import org.apache.hc.client5.http.sync.methods.HttpExecutionAware;
-import org.apache.hc.client5.http.impl.sync.RoutedHttpRequest;
+import org.apache.hc.core5.annotation.Internal;
 import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.HttpException;
-import org.apache.hc.core5.http.HttpRequest;
-import org.apache.hc.core5.http.HttpStatus;
-import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
-
-public class DummyBackend implements ClientExecChain {
-
-    private ClassicHttpRequest request;
-    private ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
-    private int executions = 0;
-
-    public void setResponse(final ClassicHttpResponse resp) {
-        response = resp;
-    }
-
-    public HttpRequest getCapturedRequest() {
-        return request;
-    }
-
-    @Override
-    public ClassicHttpResponse execute(
-            final RoutedHttpRequest request,
-            final HttpClientContext clientContext,
-            final HttpExecutionAware execAware) throws IOException, HttpException {
-        this.request = request;
-        executions++;
-        return response;
-    }
-
-    public int getExecutions() {
-        return executions;
-    }
+import org.apache.hc.core5.util.TimeValue;
+
+/**
+ * Execution runtime that provides access to the underlying connection endpoint and helps
+ * manager its life cycle.
+ * <p>
+ * This interface is considered internal and generally ought not be used or accessed
+ * by custom request exec handlers.
+ *
+ * @since 5.0
+ */
+@Internal
+public interface ExecRuntime {
+
+    boolean isExecutionAborted();
+
+    boolean isConnectionAcquired();
+
+    void acquireConnection(
+            HttpRoute route,
+            Object state,
+            HttpClientContext context) throws IOException;
+
+    void releaseConnection();
+
+    void discardConnection();
+
+    boolean isConnected();
+
+    void disconnect() throws IOException;
+
+    void connect(HttpClientContext context) throws IOException;
+
+    void upgradeTls(HttpClientContext context) throws IOException;
+
+    ClassicHttpResponse execute(
+            ClassicHttpRequest request,
+            HttpClientContext context) throws IOException, HttpException;
+
+    boolean isConnectionReusable();
+
+    void markConnectionReusable();
+
+    void markConnectionNonReusable();
+
+    void setConnectionState(Object state);
+
+    void setConnectionValidFor(TimeValue duration);
+
 }

Modified: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/methods/HttpUriRequestBase.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/methods/HttpUriRequestBase.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/methods/HttpUriRequestBase.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/methods/HttpUriRequestBase.java Mon May  1 11:11:09 2017
@@ -30,13 +30,13 @@ import java.net.URI;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.apache.hc.client5.http.CancellableAware;
 import org.apache.hc.client5.http.config.Configurable;
 import org.apache.hc.client5.http.config.RequestConfig;
 import org.apache.hc.core5.concurrent.Cancellable;
 import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
 
-public class HttpUriRequestBase extends BasicClassicHttpRequest
-        implements HttpUriRequest, HttpExecutionAware, Configurable {
+public class HttpUriRequestBase extends BasicClassicHttpRequest implements CancellableAware, Configurable {
 
     private static final long serialVersionUID = 1L;
 
@@ -50,7 +50,6 @@ public class HttpUriRequestBase extends
         this.cancellableRef = new AtomicReference<>(null);
     }
 
-    @Override
     public void abort() {
         if (this.aborted.compareAndSet(false, true)) {
             final Cancellable cancellable = this.cancellableRef.getAndSet(null);
@@ -61,6 +60,10 @@ public class HttpUriRequestBase extends
     }
 
     @Override
+    public boolean isCancelled() {
+        return isAborted();
+    }
+
     public boolean isAborted() {
         return this.aborted.get();
     }

Modified: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/methods/RequestBuilder.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/methods/RequestBuilder.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/methods/RequestBuilder.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/sync/methods/RequestBuilder.java Mon May  1 11:11:09 2017
@@ -37,6 +37,7 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.apache.hc.client5.http.StandardMethods;
 import org.apache.hc.client5.http.config.Configurable;
 import org.apache.hc.client5.http.config.RequestConfig;
 import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
@@ -55,7 +56,7 @@ import org.apache.hc.core5.net.URIBuilde
 import org.apache.hc.core5.util.Args;
 
 /**
- * Builder for {@link HttpUriRequest} instances.
+ * Builder for {@link ClassicHttpRequest} instances.
  * <p>
  * Please note that this class treats parameters differently depending on composition
  * of the request: if the request has a content entity explicitly set with
@@ -83,20 +84,31 @@ public class RequestBuilder {
         this.method = method;
     }
 
+    RequestBuilder() {
+    }
+
+    RequestBuilder(final StandardMethods method) {
+        this(method.name());
+    }
+
     RequestBuilder(final String method, final URI uri) {
         super();
         this.method = method;
         this.uri = uri;
     }
 
+    RequestBuilder(final StandardMethods method, final URI uri) {
+        this(method.name(), uri);
+    }
+
     RequestBuilder(final String method, final String uri) {
         super();
         this.method = method;
         this.uri = uri != null ? URI.create(uri) : null;
     }
 
-    RequestBuilder() {
-        this(null);
+    RequestBuilder(final StandardMethods method, final String uri) {
+        this(method.name(), uri);
     }
 
     public static RequestBuilder create(final String method) {
@@ -105,150 +117,150 @@ public class RequestBuilder {
     }
 
     public static RequestBuilder get() {
-        return new RequestBuilder(HttpGet.METHOD_NAME);
+        return new RequestBuilder(StandardMethods.GET.name());
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder get(final URI uri) {
-        return new RequestBuilder(HttpGet.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.GET, uri);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder get(final String uri) {
-        return new RequestBuilder(HttpGet.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.GET, uri);
     }
 
     public static RequestBuilder head() {
-        return new RequestBuilder(HttpHead.METHOD_NAME);
+        return new RequestBuilder(StandardMethods.HEAD);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder head(final URI uri) {
-        return new RequestBuilder(HttpHead.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.HEAD, uri);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder head(final String uri) {
-        return new RequestBuilder(HttpHead.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.HEAD, uri);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder patch() {
-        return new RequestBuilder(HttpPatch.METHOD_NAME);
+        return new RequestBuilder(StandardMethods.PATCH.name());
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder patch(final URI uri) {
-        return new RequestBuilder(HttpPatch.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.PATCH, uri);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder patch(final String uri) {
-        return new RequestBuilder(HttpPatch.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.PATCH, uri);
     }
 
     public static RequestBuilder post() {
-        return new RequestBuilder(HttpPost.METHOD_NAME);
+        return new RequestBuilder(StandardMethods.POST);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder post(final URI uri) {
-        return new RequestBuilder(HttpPost.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.POST, uri);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder post(final String uri) {
-        return new RequestBuilder(HttpPost.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.POST, uri);
     }
 
     public static RequestBuilder put() {
-        return new RequestBuilder(HttpPut.METHOD_NAME);
+        return new RequestBuilder(StandardMethods.PUT);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder put(final URI uri) {
-        return new RequestBuilder(HttpPut.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.PUT, uri);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder put(final String uri) {
-        return new RequestBuilder(HttpPut.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.PUT, uri);
     }
 
     public static RequestBuilder delete() {
-        return new RequestBuilder(HttpDelete.METHOD_NAME);
+        return new RequestBuilder(StandardMethods.DELETE);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder delete(final URI uri) {
-        return new RequestBuilder(HttpDelete.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.DELETE, uri);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder delete(final String uri) {
-        return new RequestBuilder(HttpDelete.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.DELETE, uri);
     }
 
     public static RequestBuilder trace() {
-        return new RequestBuilder(HttpTrace.METHOD_NAME);
+        return new RequestBuilder(StandardMethods.TRACE);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder trace(final URI uri) {
-        return new RequestBuilder(HttpTrace.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.TRACE, uri);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder trace(final String uri) {
-        return new RequestBuilder(HttpTrace.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.TRACE, uri);
     }
 
     public static RequestBuilder options() {
-        return new RequestBuilder(HttpOptions.METHOD_NAME);
+        return new RequestBuilder(StandardMethods.OPTIONS);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder options(final URI uri) {
-        return new RequestBuilder(HttpOptions.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.OPTIONS, uri);
     }
 
     /**
      * @since 4.4
      */
     public static RequestBuilder options(final String uri) {
-        return new RequestBuilder(HttpOptions.METHOD_NAME, uri);
+        return new RequestBuilder(StandardMethods.OPTIONS, uri);
     }
 
     public static RequestBuilder copy(final ClassicHttpRequest request) {
@@ -449,12 +461,12 @@ public class RequestBuilder {
         return this;
     }
 
-    public HttpUriRequest build() {
+    public ClassicHttpRequest build() {
         URI uriNotNull = this.uri != null ? this.uri : URI.create("/");
         HttpEntity entityCopy = this.entity;
         if (parameters != null && !parameters.isEmpty()) {
-            if (entityCopy == null && (HttpPost.METHOD_NAME.equalsIgnoreCase(method)
-                    || HttpPut.METHOD_NAME.equalsIgnoreCase(method))) {
+            if (entityCopy == null && (StandardMethods.POST.name().equalsIgnoreCase(method)
+                    || StandardMethods.PUT.name().equalsIgnoreCase(method))) {
                 entityCopy = new UrlEncodedFormEntity(parameters, charset != null ? charset : StandardCharsets.ISO_8859_1);
             } else {
                 try {

Added: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestNamedElementChain.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestNamedElementChain.java?rev=1793308&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestNamedElementChain.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestNamedElementChain.java Mon May  1 11:11:09 2017
@@ -0,0 +1,97 @@
+/*
+ * ====================================================================
+ * 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.hc.client5.http.impl;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests for {@link NamedElementChain}.
+ */
+public class TestNamedElementChain {
+
+    @Test
+    public void testBasics() {
+        final NamedElementChain<Character> list = new NamedElementChain<>();
+        Assert.assertThat(list.getFirst(), CoreMatchers.nullValue());
+        Assert.assertThat(list.getLast(), CoreMatchers.nullValue());
+
+        final NamedElementChain<Character>.Node nodeA = list.addFirst('a', "a");
+
+        Assert.assertThat(list.getFirst(), CoreMatchers.sameInstance(nodeA));
+        Assert.assertThat(list.getLast(), CoreMatchers.sameInstance(nodeA));
+
+        final NamedElementChain<Character>.Node nodeB = list.addLast('b', "b");
+
+        Assert.assertThat(list.getFirst(), CoreMatchers.sameInstance(nodeA));
+        Assert.assertThat(list.getLast(), CoreMatchers.sameInstance(nodeB));
+
+        final NamedElementChain<Character>.Node nodeZ = list.addLast('z', "z");
+
+        Assert.assertThat(list.getFirst(), CoreMatchers.sameInstance(nodeA));
+        Assert.assertThat(list.getLast(), CoreMatchers.sameInstance(nodeZ));
+
+        Assert.assertThat(nodeA.getPrevious(), CoreMatchers.nullValue());
+        Assert.assertThat(nodeA.getNext(), CoreMatchers.sameInstance(nodeB));
+        Assert.assertThat(nodeB.getPrevious(), CoreMatchers.sameInstance(nodeA));
+        Assert.assertThat(nodeB.getNext(), CoreMatchers.sameInstance(nodeZ));
+        Assert.assertThat(nodeZ.getPrevious(), CoreMatchers.sameInstance(nodeB));
+        Assert.assertThat(nodeZ.getNext(), CoreMatchers.nullValue());
+
+        final NamedElementChain<Character>.Node nodeD = list.addAfter("b", 'd', "d");
+        Assert.assertThat(nodeD.getPrevious(), CoreMatchers.sameInstance(nodeB));
+        Assert.assertThat(nodeD.getNext(), CoreMatchers.sameInstance(nodeZ));
+        Assert.assertThat(nodeB.getNext(), CoreMatchers.sameInstance(nodeD));
+        Assert.assertThat(nodeZ.getPrevious(), CoreMatchers.sameInstance(nodeD));
+
+        final NamedElementChain<Character>.Node nodeC = list.addBefore("d", 'c', "c");
+        Assert.assertThat(nodeC.getPrevious(), CoreMatchers.sameInstance(nodeB));
+        Assert.assertThat(nodeC.getNext(), CoreMatchers.sameInstance(nodeD));
+        Assert.assertThat(nodeB.getNext(), CoreMatchers.sameInstance(nodeC));
+        Assert.assertThat(nodeD.getPrevious(), CoreMatchers.sameInstance(nodeC));
+        Assert.assertThat(list.getSize(), CoreMatchers.equalTo(5));
+
+        Assert.assertThat(list.remove("a"), CoreMatchers.is(true));
+        Assert.assertThat(list.remove("z"), CoreMatchers.is(true));
+        Assert.assertThat(list.remove("c"), CoreMatchers.is(true));
+        Assert.assertThat(list.remove("c"), CoreMatchers.is(false));
+        Assert.assertThat(list.remove("blah"), CoreMatchers.is(false));
+
+        Assert.assertThat(list.getFirst(), CoreMatchers.sameInstance(nodeB));
+        Assert.assertThat(list.getLast(), CoreMatchers.sameInstance(nodeD));
+
+        Assert.assertThat(list.getSize(), CoreMatchers.equalTo(2));
+        Assert.assertThat(list.addBefore("blah", 'e', "e"), CoreMatchers.nullValue());
+        Assert.assertThat(list.getSize(), CoreMatchers.equalTo(2));
+
+        Assert.assertThat(list.addAfter("yada", 'e', "e"), CoreMatchers.nullValue());
+        Assert.assertThat(list.getSize(), CoreMatchers.equalTo(2));
+    }
+
+}
\ No newline at end of file

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestNamedElementChain.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestNamedElementChain.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestNamedElementChain.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestClientRequestExecution.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestClientRequestExecution.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestClientRequestExecution.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestClientRequestExecution.java Mon May  1 11:11:09 2017
@@ -139,7 +139,7 @@ public class TestClientRequestExecution
         };
 
         this.httpclient = this.clientBuilder
-            .addInterceptorFirst(interceptor)
+            .addRequestInterceptorFirst(interceptor)
             .setRequestExecutor(new FaultyHttpRequestExecutor("Oppsie"))
             .setRetryHandler(requestRetryHandler)
             .build();

Modified: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestIdleConnectionEviction.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestIdleConnectionEviction.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestIdleConnectionEviction.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestIdleConnectionEviction.java Mon May  1 11:11:09 2017
@@ -32,7 +32,7 @@ import org.apache.hc.client5.http.impl.s
 import org.apache.hc.client5.http.localserver.LocalServerTestBase;
 import org.apache.hc.client5.http.protocol.ClientProtocolException;
 import org.apache.hc.client5.http.sync.methods.HttpGet;
-import org.apache.hc.client5.http.sync.methods.HttpUriRequest;
+import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.io.entity.EntityUtils;
@@ -73,7 +73,7 @@ public class TestIdleConnectionEviction
 
         private final CloseableHttpClient httpclient;
         private final HttpHost target;
-        private final HttpUriRequest request;
+        private final ClassicHttpRequest request;
         private final int count;
 
         private volatile Exception ex;
@@ -81,7 +81,7 @@ public class TestIdleConnectionEviction
         public WorkerThread(
                 final CloseableHttpClient httpclient,
                 final HttpHost target,
-                final HttpUriRequest request,
+                final ClassicHttpRequest request,
                 final int count) {
             super();
             this.httpclient = httpclient;
@@ -97,7 +97,6 @@ public class TestIdleConnectionEviction
                     final ClassicHttpResponse response = this.httpclient.execute(this.target, this.request);
                     final int status = response.getCode();
                     if (status != 200) {
-                        this.request.abort();
                         throw new ClientProtocolException("Unexpected status code: " + status);
                     }
                     EntityUtils.consume(response.getEntity());

Modified: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestStatefulConnManagement.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestStatefulConnManagement.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestStatefulConnManagement.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestStatefulConnManagement.java Mon May  1 11:11:09 2017
@@ -122,7 +122,7 @@ public class TestStatefulConnManagement
             final String state0 = (String) context.getAttribute("r0");
             Assert.assertNotNull(state0);
             for (int r = 1; r < requestCount; r++) {
-                Assert.assertEquals(state0, (String) context.getAttribute("r" + r));
+                Assert.assertEquals(state0, context.getAttribute("r" + r));
             }
         }
 

Modified: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/protocol/TestDefaultRedirectStrategy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/protocol/TestDefaultRedirectStrategy.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/protocol/TestDefaultRedirectStrategy.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/protocol/TestDefaultRedirectStrategy.java Mon May  1 11:11:09 2017
@@ -32,20 +32,13 @@ import java.util.List;
 import org.apache.hc.client5.http.config.RequestConfig;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
 import org.apache.hc.client5.http.sync.methods.HttpGet;
-import org.apache.hc.client5.http.sync.methods.HttpHead;
 import org.apache.hc.client5.http.sync.methods.HttpPost;
-import org.apache.hc.client5.http.sync.methods.HttpTrace;
-import org.apache.hc.client5.http.sync.methods.HttpUriRequest;
-import org.apache.hc.core5.http.HttpEntity;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpHeaders;
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.ProtocolException;
-import org.apache.hc.core5.http.io.entity.BasicHttpEntity;
 import org.apache.hc.core5.http.message.BasicHttpResponse;
-import org.apache.hc.core5.http.protocol.BasicHttpContext;
-import org.apache.hc.core5.http.protocol.HttpContext;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -279,44 +272,6 @@ public class TestDefaultRedirectStrategy
     }
 
     @Test
-    public void testGetRedirectRequest() throws Exception {
-        final DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
-        final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SEE_OTHER, "Redirect");
-        response.addHeader("Location", "http://localhost/stuff");
-        final HttpContext context1 = new BasicHttpContext();
-        final HttpUriRequest redirect1 = redirectStrategy.getRedirect(
-                new HttpGet("http://localhost/"), response, context1);
-        Assert.assertEquals("GET", redirect1.getMethod());
-        final HttpContext context2 = new BasicHttpContext();
-        final HttpUriRequest redirect2 = redirectStrategy.getRedirect(
-                new HttpPost("http://localhost/"), response, context2);
-        Assert.assertEquals("GET", redirect2.getMethod());
-        final HttpContext context3 = new BasicHttpContext();
-        final HttpUriRequest redirect3 = redirectStrategy.getRedirect(
-                new HttpHead("http://localhost/"), response, context3);
-        Assert.assertEquals("HEAD", redirect3.getMethod());
-    }
-
-    @Test
-    public void testGetRedirectRequestForTemporaryRedirect() throws Exception {
-        final DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
-        final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_TEMPORARY_REDIRECT, "Temporary Redirect");
-        response.addHeader("Location", "http://localhost/stuff");
-        final HttpContext context1 = new BasicHttpContext();
-        final HttpUriRequest redirect1 = redirectStrategy.getRedirect(
-                new HttpTrace("http://localhost/"), response, context1);
-        Assert.assertEquals("TRACE", redirect1.getMethod());
-        final HttpContext context2 = new BasicHttpContext();
-        final HttpPost httppost = new HttpPost("http://localhost/");
-        final HttpEntity entity = new BasicHttpEntity();
-        httppost.setEntity(entity);
-        final HttpUriRequest redirect2 = redirectStrategy.getRedirect(
-                httppost, response, context2);
-        Assert.assertEquals("POST", redirect2.getMethod());
-        Assert.assertSame(entity, redirect2.getEntity());
-    }
-
-    @Test
     public void testCreateLocationURI() throws Exception {
         final DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
         Assert.assertEquals("http://blahblah/",

Modified: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestDefaultHttpRequestRetryHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestDefaultHttpRequestRetryHandler.java?rev=1793308&r1=1793307&r2=1793308&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestDefaultHttpRequestRetryHandler.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestDefaultHttpRequestRetryHandler.java Mon May  1 11:11:09 2017
@@ -31,7 +31,6 @@ import java.net.UnknownHostException;
 
 import org.apache.hc.client5.http.ConnectTimeoutException;
 import org.apache.hc.client5.http.sync.methods.HttpGet;
-import org.apache.hc.client5.http.sync.methods.HttpUriRequest;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -41,7 +40,7 @@ public class TestDefaultHttpRequestRetry
 
     @Test
     public void noRetryOnConnectTimeout() throws Exception {
-        final HttpUriRequest request = new HttpGet("/");
+        final HttpGet request = new HttpGet("/");
 
         final DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
         Assert.assertEquals(3, retryHandler.getRetryCount());
@@ -51,7 +50,7 @@ public class TestDefaultHttpRequestRetry
 
     @Test
     public void noRetryOnUnknownHost() throws Exception {
-        final HttpUriRequest request = new HttpGet("/");
+        final HttpGet request = new HttpGet("/");
 
         final DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
 
@@ -60,7 +59,7 @@ public class TestDefaultHttpRequestRetry
 
     @Test
     public void noRetryOnAbortedRequests() throws Exception{
-        final HttpUriRequest request = new HttpGet("/");
+        final HttpGet request = new HttpGet("/");
         request.abort();
 
         final DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
@@ -70,7 +69,7 @@ public class TestDefaultHttpRequestRetry
 
     @Test
     public void retryOnNonAbortedRequests() throws Exception{
-        final HttpUriRequest request = new HttpGet("/");
+        final HttpGet request = new HttpGet("/");
 
         final DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
 
@@ -79,7 +78,7 @@ public class TestDefaultHttpRequestRetry
 
     @Test
     public void noRetryOnConnectionTimeout() throws Exception{
-        final HttpUriRequest request = new HttpGet("/");
+        final HttpGet request = new HttpGet("/");
 
         final DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
 

Added: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestExecRuntimeImpl.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestExecRuntimeImpl.java?rev=1793308&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestExecRuntimeImpl.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestExecRuntimeImpl.java Mon May  1 11:11:09 2017
@@ -0,0 +1,308 @@
+/*
+ * ====================================================================
+ * 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.hc.client5.http.impl.sync;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.hc.client5.http.CancellableAware;
+import org.apache.hc.client5.http.HttpRoute;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.io.ConnectionEndpoint;
+import org.apache.hc.client5.http.io.HttpClientConnectionManager;
+import org.apache.hc.client5.http.io.LeaseRequest;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.concurrent.Cancellable;
+import org.apache.hc.core5.http.ConnectionRequestTimeoutException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.impl.io.HttpRequestExecutor;
+import org.apache.hc.core5.io.ShutdownType;
+import org.apache.hc.core5.util.TimeValue;
+import org.apache.logging.log4j.Logger;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+@SuppressWarnings({"static-access"}) // test code
+public class TestExecRuntimeImpl {
+
+    @Mock
+    private Logger log;
+    @Mock
+    private HttpClientConnectionManager mgr;
+    @Mock
+    private LeaseRequest leaseRequest;
+    @Mock
+    private HttpRequestExecutor requestExecutor;
+    @Mock
+    private CancellableAware cancellableAware;
+    @Mock
+    private ConnectionEndpoint connectionEndpoint;
+
+    private HttpRoute route;
+    private ExecRuntimeImpl execRuntime;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        route = new HttpRoute(new HttpHost("host", 80));
+        execRuntime = new ExecRuntimeImpl(log, mgr, requestExecutor, cancellableAware);
+    }
+
+    @Test
+    public void testAcquireEndpoint() throws Exception {
+        final HttpClientContext context = HttpClientContext.create();
+        final RequestConfig config = RequestConfig.custom()
+                .setConnectTimeout(123, TimeUnit.MILLISECONDS)
+                .setSocketTimeout(234, TimeUnit.MILLISECONDS)
+                .setConnectionRequestTimeout(345, TimeUnit.MILLISECONDS)
+                .build();
+        context.setRequestConfig(config);
+        final HttpRoute route = new HttpRoute(new HttpHost("host", 80));
+
+        Mockito.when(mgr.lease(route, null)).thenReturn(leaseRequest);
+        Mockito.when(leaseRequest.get(
+                Mockito.anyLong(), Mockito.<TimeUnit>any())).thenReturn(connectionEndpoint);
+
+        execRuntime.acquireConnection(route, null, context);
+
+        Assert.assertTrue(execRuntime.isConnectionAcquired());
+        Assert.assertSame(connectionEndpoint, execRuntime.ensureValid());
+        Assert.assertFalse(execRuntime.isConnected());
+        Assert.assertFalse(execRuntime.isConnectionReusable());
+
+        Mockito.verify(leaseRequest).get(345, TimeUnit.MILLISECONDS);
+        Mockito.verify(cancellableAware, Mockito.times(1)).setCancellable(leaseRequest);
+        Mockito.verify(cancellableAware, Mockito.times(1)).setCancellable(execRuntime);
+        Mockito.verify(cancellableAware, Mockito.times(2)).setCancellable(Mockito.<Cancellable>any());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testAcquireEndpointAlreadyAcquired() throws Exception {
+        final HttpClientContext context = HttpClientContext.create();
+
+        Mockito.when(mgr.lease(route, null)).thenReturn(leaseRequest);
+        Mockito.when(leaseRequest.get(
+                Mockito.anyLong(), Mockito.<TimeUnit>any())).thenReturn(connectionEndpoint);
+
+        execRuntime.acquireConnection(route, null, context);
+
+        Assert.assertTrue(execRuntime.isConnectionAcquired());
+        Assert.assertSame(connectionEndpoint, execRuntime.ensureValid());
+
+        execRuntime.acquireConnection(route, null, context);
+    }
+
+    @Test(expected = ConnectionRequestTimeoutException.class)
+    public void testAcquireEndpointLeaseRequestTimeout() throws Exception {
+        final HttpClientContext context = HttpClientContext.create();
+
+        Mockito.when(mgr.lease(route, null)).thenReturn(leaseRequest);
+        Mockito.when(leaseRequest.get(
+                Mockito.anyLong(), Mockito.<TimeUnit>any())).thenThrow(new TimeoutException());
+
+        execRuntime.acquireConnection(route, null, context);
+    }
+
+    @Test(expected = RequestFailedException.class)
+    public void testAcquireEndpointLeaseRequestFailure() throws Exception {
+        final HttpClientContext context = HttpClientContext.create();
+
+        Mockito.when(mgr.lease(route, null)).thenReturn(leaseRequest);
+        Mockito.when(leaseRequest.get(
+                Mockito.anyLong(), Mockito.<TimeUnit>any())).thenThrow(new ExecutionException(new IllegalStateException()));
+
+        execRuntime.acquireConnection(route, null, context);
+    }
+
+    @Test
+    public void testAbortEndpoint() throws Exception {
+        final HttpClientContext context = HttpClientContext.create();
+        Mockito.when(mgr.lease(route, null)).thenReturn(leaseRequest);
+        Mockito.when(leaseRequest.get(
+                Mockito.anyLong(), Mockito.<TimeUnit>any())).thenReturn(connectionEndpoint);
+
+        execRuntime.acquireConnection(new HttpRoute(new HttpHost("host", 80)), null, context);
+        Assert.assertTrue(execRuntime.isConnectionAcquired());
+        execRuntime.discardConnection();
+
+        Assert.assertFalse(execRuntime.isConnectionAcquired());
+
+        Mockito.verify(connectionEndpoint).shutdown(ShutdownType.IMMEDIATE);
+        Mockito.verify(mgr).release(connectionEndpoint, null, TimeValue.ZERO_MILLISECONDS);
+
+        execRuntime.discardConnection();
+
+        Mockito.verify(connectionEndpoint, Mockito.times(1)).shutdown(ShutdownType.IMMEDIATE);
+        Mockito.verify(mgr, Mockito.times(1)).release(
+                Mockito.<ConnectionEndpoint>any(),
+                Mockito.anyObject(),
+                Mockito.<TimeValue>any());
+    }
+
+    @Test
+    public void testCancell() throws Exception {
+        final HttpClientContext context = HttpClientContext.create();
+
+        Mockito.when(mgr.lease(route, null)).thenReturn(leaseRequest);
+        Mockito.when(leaseRequest.get(
+                Mockito.anyLong(), Mockito.<TimeUnit>any())).thenReturn(connectionEndpoint);
+
+        execRuntime.acquireConnection(route, null, context);
+        Assert.assertTrue(execRuntime.isConnectionAcquired());
+
+        Assert.assertTrue(execRuntime.cancel());
+
+        Assert.assertFalse(execRuntime.isConnectionAcquired());
+
+        Mockito.verify(connectionEndpoint).shutdown(ShutdownType.IMMEDIATE);
+        Mockito.verify(mgr).release(connectionEndpoint, null, TimeValue.ZERO_MILLISECONDS);
+
+        Assert.assertFalse(execRuntime.cancel());
+
+        Mockito.verify(connectionEndpoint, Mockito.times(1)).shutdown(ShutdownType.IMMEDIATE);
+        Mockito.verify(mgr, Mockito.times(1)).release(
+                Mockito.<ConnectionEndpoint>any(),
+                Mockito.anyObject(),
+                Mockito.<TimeValue>any());
+    }
+
+    @Test
+    public void testReleaseEndpointReusable() throws Exception {
+        final HttpClientContext context = HttpClientContext.create();
+
+        Mockito.when(mgr.lease(route, null)).thenReturn(leaseRequest);
+        Mockito.when(leaseRequest.get(
+                Mockito.anyLong(), Mockito.<TimeUnit>any())).thenReturn(connectionEndpoint);
+
+        execRuntime.acquireConnection(route, null, context);
+        Assert.assertTrue(execRuntime.isConnectionAcquired());
+
+        execRuntime.setConnectionState("some state");
+        execRuntime.setConnectionValidFor(TimeValue.ofMillis(100000));
+        execRuntime.markConnectionReusable();
+
+        execRuntime.releaseConnection();
+
+        Assert.assertFalse(execRuntime.isConnectionAcquired());
+
+        Mockito.verify(connectionEndpoint, Mockito.never()).close();
+        Mockito.verify(mgr).release(connectionEndpoint, "some state", TimeValue.ofMillis(100000));
+
+        execRuntime.releaseConnection();
+
+        Mockito.verify(mgr, Mockito.times(1)).release(
+                Mockito.<ConnectionEndpoint>any(),
+                Mockito.anyObject(),
+                Mockito.<TimeValue>any());
+    }
+
+    @Test
+    public void testReleaseEndpointNonReusable() throws Exception {
+        final HttpClientContext context = HttpClientContext.create();
+
+        Mockito.when(mgr.lease(route, null)).thenReturn(leaseRequest);
+        Mockito.when(leaseRequest.get(
+                Mockito.anyLong(), Mockito.<TimeUnit>any())).thenReturn(connectionEndpoint);
+
+        execRuntime.acquireConnection(route, null, context);
+        Assert.assertTrue(execRuntime.isConnectionAcquired());
+
+        execRuntime.setConnectionState("some state");
+        execRuntime.setConnectionValidFor(TimeValue.ofMillis(100000));
+        execRuntime.markConnectionNonReusable();
+
+        execRuntime.releaseConnection();
+
+        Assert.assertFalse(execRuntime.isConnectionAcquired());
+
+        Mockito.verify(connectionEndpoint, Mockito.times(1)).close();
+        Mockito.verify(mgr).release(connectionEndpoint, null, TimeValue.ZERO_MILLISECONDS);
+
+        execRuntime.releaseConnection();
+
+        Mockito.verify(mgr, Mockito.times(1)).release(
+                Mockito.<ConnectionEndpoint>any(),
+                Mockito.anyObject(),
+                Mockito.<TimeValue>any());
+    }
+
+    @Test
+    public void testConnectEndpoint() throws Exception {
+        final HttpClientContext context = HttpClientContext.create();
+        final RequestConfig config = RequestConfig.custom()
+                .setConnectTimeout(123, TimeUnit.MILLISECONDS)
+                .setSocketTimeout(234, TimeUnit.MILLISECONDS)
+                .setConnectionRequestTimeout(345, TimeUnit.MILLISECONDS)
+                .build();
+        context.setRequestConfig(config);
+
+        Mockito.when(mgr.lease(route, null)).thenReturn(leaseRequest);
+        Mockito.when(leaseRequest.get(
+                Mockito.anyLong(), Mockito.<TimeUnit>any())).thenReturn(connectionEndpoint);
+
+        execRuntime.acquireConnection(route, null, context);
+        Assert.assertTrue(execRuntime.isConnectionAcquired());
+
+        Mockito.when(connectionEndpoint.isConnected()).thenReturn(false);
+        Assert.assertFalse(execRuntime.isConnected());
+
+        execRuntime.connect(context);
+
+        Mockito.verify(mgr).connect(connectionEndpoint, TimeValue.ofMillis(123), context);
+        Mockito.verify(connectionEndpoint).setSocketTimeout(234);
+    }
+
+    @Test
+    public void testDisonnectEndpoint() throws Exception {
+        final HttpClientContext context = HttpClientContext.create();
+
+        Mockito.when(mgr.lease(route, null)).thenReturn(leaseRequest);
+        Mockito.when(leaseRequest.get(
+                Mockito.anyLong(), Mockito.<TimeUnit>any())).thenReturn(connectionEndpoint);
+
+        execRuntime.acquireConnection(route, null, context);
+        Assert.assertTrue(execRuntime.isConnectionAcquired());
+
+        Mockito.when(connectionEndpoint.isConnected()).thenReturn(true);
+        Assert.assertTrue(execRuntime.isConnected());
+
+        execRuntime.connect(context);
+
+        Mockito.verify(mgr, Mockito.never()).connect(
+                Mockito.same(connectionEndpoint), Mockito.<TimeValue>any(), Mockito.<HttpClientContext>any());
+
+        execRuntime.disconnect();
+
+        Mockito.verify(connectionEndpoint).close();
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestExecRuntimeImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestExecRuntimeImpl.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestExecRuntimeImpl.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message