Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 32D38200C77 for ; Mon, 1 May 2017 13:11:17 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 316DB160BBD; Mon, 1 May 2017 11:11:17 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id A892D160BAB for ; Mon, 1 May 2017 13:11:14 +0200 (CEST) Received: (qmail 29871 invoked by uid 500); 1 May 2017 11:11:13 -0000 Mailing-List: contact commits-help@hc.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "HttpComponents Project" Delivered-To: mailing list commits@hc.apache.org Received: (qmail 29797 invoked by uid 99); 1 May 2017 11:11:13 -0000 Received: from Unknown (HELO svn01-us-west.apache.org) (209.188.14.144) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 01 May 2017 11:11:13 +0000 Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id 367363A47ED for ; Mon, 1 May 2017 11:11:12 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit 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 -0000 To: commits@hc.apache.org From: olegk@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20170501111112.367363A47ED@svn01-us-west.apache.org> archived-at: Mon, 01 May 2017 11:11:17 -0000 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 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 @@ * . * */ -package org.apache.hc.client5.http.auth; + +package org.apache.hc.client5.http.impl.sync; + +import java.io.InterruptedIOException; /** - * Abstract store of authentication credentials. - *

- * 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 @@ * . * */ -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 @@ * . * */ -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. + *

+ * 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. *

* 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 + * . + * + */ + +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 list = new NamedElementChain<>(); + Assert.assertThat(list.getFirst(), CoreMatchers.nullValue()); + Assert.assertThat(list.getLast(), CoreMatchers.nullValue()); + + final NamedElementChain.Node nodeA = list.addFirst('a', "a"); + + Assert.assertThat(list.getFirst(), CoreMatchers.sameInstance(nodeA)); + Assert.assertThat(list.getLast(), CoreMatchers.sameInstance(nodeA)); + + final NamedElementChain.Node nodeB = list.addLast('b', "b"); + + Assert.assertThat(list.getFirst(), CoreMatchers.sameInstance(nodeA)); + Assert.assertThat(list.getLast(), CoreMatchers.sameInstance(nodeB)); + + final NamedElementChain.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.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.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 + * . + * + */ +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.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.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.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.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.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.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.any(), + Mockito.anyObject(), + Mockito.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.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.any(), + Mockito.anyObject(), + Mockito.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.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.any(), + Mockito.anyObject(), + Mockito.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.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.any(), + Mockito.anyObject(), + Mockito.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.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.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.any(), Mockito.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