1 /* 2 * ==================================================================== 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * ==================================================================== 20 * 21 * This software consists of voluntary contributions made by many 22 * individuals on behalf of the Apache Software Foundation. For more 23 * information on the Apache Software Foundation, please see 24 * <http://www.apache.org/>. 25 * 26 */ 27 28 package ch.boye.httpclientandroidlib.impl.client; 29 30 import java.io.IOException; 31 import java.lang.reflect.UndeclaredThrowableException; 32 33 import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog; 34 /* LogFactory removed by HttpClient for Android script. */ 35 import ch.boye.httpclientandroidlib.ConnectionReuseStrategy; 36 import ch.boye.httpclientandroidlib.HttpException; 37 import ch.boye.httpclientandroidlib.HttpHost; 38 import ch.boye.httpclientandroidlib.HttpRequest; 39 import ch.boye.httpclientandroidlib.HttpRequestInterceptor; 40 import ch.boye.httpclientandroidlib.HttpResponseInterceptor; 41 import ch.boye.httpclientandroidlib.annotation.GuardedBy; 42 import ch.boye.httpclientandroidlib.annotation.ThreadSafe; 43 import ch.boye.httpclientandroidlib.auth.AuthSchemeRegistry; 44 import ch.boye.httpclientandroidlib.client.AuthenticationHandler; 45 import ch.boye.httpclientandroidlib.client.AuthenticationStrategy; 46 import ch.boye.httpclientandroidlib.client.BackoffManager; 47 import ch.boye.httpclientandroidlib.client.ClientProtocolException; 48 import ch.boye.httpclientandroidlib.client.ConnectionBackoffStrategy; 49 import ch.boye.httpclientandroidlib.client.CookieStore; 50 import ch.boye.httpclientandroidlib.client.CredentialsProvider; 51 import ch.boye.httpclientandroidlib.client.HttpRequestRetryHandler; 52 import ch.boye.httpclientandroidlib.client.RedirectHandler; 53 import ch.boye.httpclientandroidlib.client.RedirectStrategy; 54 import ch.boye.httpclientandroidlib.client.RequestDirector; 55 import ch.boye.httpclientandroidlib.client.UserTokenHandler; 56 import ch.boye.httpclientandroidlib.client.config.RequestConfig; 57 import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse; 58 import ch.boye.httpclientandroidlib.client.params.AuthPolicy; 59 import ch.boye.httpclientandroidlib.client.params.ClientPNames; 60 import ch.boye.httpclientandroidlib.client.params.CookiePolicy; 61 import ch.boye.httpclientandroidlib.client.params.HttpClientParamConfig; 62 import ch.boye.httpclientandroidlib.client.protocol.ClientContext; 63 import ch.boye.httpclientandroidlib.conn.ClientConnectionManager; 64 import ch.boye.httpclientandroidlib.conn.ClientConnectionManagerFactory; 65 import ch.boye.httpclientandroidlib.conn.ConnectionKeepAliveStrategy; 66 import ch.boye.httpclientandroidlib.conn.routing.HttpRoute; 67 import ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner; 68 import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry; 69 import ch.boye.httpclientandroidlib.cookie.CookieSpecRegistry; 70 import ch.boye.httpclientandroidlib.impl.DefaultConnectionReuseStrategy; 71 import ch.boye.httpclientandroidlib.impl.auth.BasicSchemeFactory; 72 import ch.boye.httpclientandroidlib.impl.auth.DigestSchemeFactory; 73 /* KerberosSchemeFactory removed by HttpClient for Android script. */ 74 import ch.boye.httpclientandroidlib.impl.auth.NTLMSchemeFactory; 75 /* SPNegoSchemeFactory removed by HttpClient for Android script. */ 76 import ch.boye.httpclientandroidlib.impl.conn.BasicClientConnectionManager; 77 import ch.boye.httpclientandroidlib.impl.conn.DefaultHttpRoutePlanner; 78 import ch.boye.httpclientandroidlib.impl.conn.SchemeRegistryFactory; 79 import ch.boye.httpclientandroidlib.impl.cookie.BestMatchSpecFactory; 80 import ch.boye.httpclientandroidlib.impl.cookie.BrowserCompatSpecFactory; 81 import ch.boye.httpclientandroidlib.impl.cookie.IgnoreSpecFactory; 82 import ch.boye.httpclientandroidlib.impl.cookie.NetscapeDraftSpecFactory; 83 import ch.boye.httpclientandroidlib.impl.cookie.RFC2109SpecFactory; 84 import ch.boye.httpclientandroidlib.impl.cookie.RFC2965SpecFactory; 85 import ch.boye.httpclientandroidlib.params.HttpParams; 86 import ch.boye.httpclientandroidlib.protocol.BasicHttpContext; 87 import ch.boye.httpclientandroidlib.protocol.BasicHttpProcessor; 88 import ch.boye.httpclientandroidlib.protocol.DefaultedHttpContext; 89 import ch.boye.httpclientandroidlib.protocol.HttpContext; 90 import ch.boye.httpclientandroidlib.protocol.HttpProcessor; 91 import ch.boye.httpclientandroidlib.protocol.HttpRequestExecutor; 92 import ch.boye.httpclientandroidlib.protocol.ImmutableHttpProcessor; 93 import ch.boye.httpclientandroidlib.util.Args; 94 95 /** 96 * Base class for {@link ch.boye.httpclientandroidlib.client.HttpClient} implementations. 97 * This class acts as a facade to a number of special purpose handler or 98 * strategy implementations responsible for handling of a particular aspect 99 * of the HTTP protocol such as redirect or authentication handling or 100 * making decision about connection persistence and keep alive duration. 101 * This enables the users to selectively replace default implementation 102 * of those aspects with custom, application specific ones. This class 103 * also provides factory methods to instantiate those objects: 104 * <ul> 105 * <li>{@link HttpRequestExecutor}</li> object used to transmit messages 106 * over HTTP connections. The {@link #createRequestExecutor()} must be 107 * implemented by concrete super classes to instantiate this object. 108 * <li>{@link BasicHttpProcessor}</li> object to manage a list of protocol 109 * interceptors and apply cross-cutting protocol logic to all incoming 110 * and outgoing HTTP messages. The {@link #createHttpProcessor()} must be 111 * implemented by concrete super classes to instantiate this object. 112 * <li>{@link HttpRequestRetryHandler}</li> object used to decide whether 113 * or not a failed HTTP request is safe to retry automatically. 114 * The {@link #createHttpRequestRetryHandler()} must be 115 * implemented by concrete super classes to instantiate this object. 116 * <li>{@link ClientConnectionManager}</li> object used to manage 117 * persistent HTTP connections. 118 * <li>{@link ConnectionReuseStrategy}</li> object used to decide whether 119 * or not a HTTP connection can be kept alive and re-used for subsequent 120 * HTTP requests. The {@link #createConnectionReuseStrategy()} must be 121 * implemented by concrete super classes to instantiate this object. 122 * <li>{@link ConnectionKeepAliveStrategy}</li> object used to decide how 123 * long a persistent HTTP connection can be kept alive. 124 * The {@link #createConnectionKeepAliveStrategy()} must be 125 * implemented by concrete super classes to instantiate this object. 126 * <li>{@link CookieSpecRegistry}</li> object used to maintain a list of 127 * supported cookie specifications. 128 * The {@link #createCookieSpecRegistry()} must be implemented by concrete 129 * super classes to instantiate this object. 130 * <li>{@link CookieStore}</li> object used to maintain a collection of 131 * cookies. The {@link #createCookieStore()} must be implemented by 132 * concrete super classes to instantiate this object. 133 * <li>{@link AuthSchemeRegistry}</li> object used to maintain a list of 134 * supported authentication schemes. 135 * The {@link #createAuthSchemeRegistry()} must be implemented by concrete 136 * super classes to instantiate this object. 137 * <li>{@link CredentialsProvider}</li> object used to maintain 138 * a collection user credentials. The {@link #createCredentialsProvider()} 139 * must be implemented by concrete super classes to instantiate 140 * this object. 141 * <li>{@link AuthenticationStrategy}</li> object used to authenticate 142 * against the target host. 143 * The {@link #createTargetAuthenticationStrategy()} must be implemented 144 * by concrete super classes to instantiate this object. 145 * <li>{@link AuthenticationStrategy}</li> object used to authenticate 146 * against the proxy host. 147 * The {@link #createProxyAuthenticationStrategy()} must be implemented 148 * by concrete super classes to instantiate this object. 149 * <li>{@link HttpRoutePlanner}</li> object used to calculate a route 150 * for establishing a connection to the target host. The route 151 * may involve multiple intermediate hops. 152 * The {@link #createHttpRoutePlanner()} must be implemented 153 * by concrete super classes to instantiate this object. 154 * <li>{@link RedirectStrategy}</li> object used to determine if an HTTP 155 * request should be redirected to a new location in response to an HTTP 156 * response received from the target server. 157 * <li>{@link UserTokenHandler}</li> object used to determine if the 158 * execution context is user identity specific. 159 * The {@link #createUserTokenHandler()} must be implemented by 160 * concrete super classes to instantiate this object. 161 * </ul> 162 * <p> 163 * This class also maintains a list of protocol interceptors intended 164 * for processing outgoing requests and incoming responses and provides 165 * methods for managing those interceptors. New protocol interceptors can be 166 * introduced to the protocol processor chain or removed from it if needed. 167 * Internally protocol interceptors are stored in a simple 168 * {@link java.util.ArrayList}. They are executed in the same natural order 169 * as they are added to the list. 170 * <p> 171 * AbstractHttpClient is thread safe. It is recommended that the same 172 * instance of this class is reused for multiple request executions. 173 * When an instance of DefaultHttpClient is no longer needed and is about 174 * to go out of scope the connection manager associated with it must be 175 * shut down by calling {@link ClientConnectionManager#shutdown()}! 176 * 177 * @since 4.0 178 * 179 * @deprecated (4.3) use {@link HttpClientBuilder}. 180 */ 181 @ThreadSafe 182 @Deprecated 183 public abstract class AbstractHttpClient extends CloseableHttpClient { 184 185 public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass()); 186 187 /** The parameters. */ 188 @GuardedBy("this") 189 private HttpParams defaultParams; 190 191 /** The request executor. */ 192 @GuardedBy("this") 193 private HttpRequestExecutor requestExec; 194 195 /** The connection manager. */ 196 @GuardedBy("this") 197 private ClientConnectionManager connManager; 198 199 /** The connection re-use strategy. */ 200 @GuardedBy("this") 201 private ConnectionReuseStrategy reuseStrategy; 202 203 /** The connection keep-alive strategy. */ 204 @GuardedBy("this") 205 private ConnectionKeepAliveStrategy keepAliveStrategy; 206 207 /** The cookie spec registry. */ 208 @GuardedBy("this") 209 private CookieSpecRegistry supportedCookieSpecs; 210 211 /** The authentication scheme registry. */ 212 @GuardedBy("this") 213 private AuthSchemeRegistry supportedAuthSchemes; 214 215 /** The HTTP protocol processor and its immutable copy. */ 216 @GuardedBy("this") 217 private BasicHttpProcessor mutableProcessor; 218 219 @GuardedBy("this") 220 private ImmutableHttpProcessor protocolProcessor; 221 222 /** The request retry handler. */ 223 @GuardedBy("this") 224 private HttpRequestRetryHandler retryHandler; 225 226 /** The redirect handler. */ 227 @GuardedBy("this") 228 private RedirectStrategy redirectStrategy; 229 230 /** The target authentication handler. */ 231 @GuardedBy("this") 232 private AuthenticationStrategy targetAuthStrategy; 233 234 /** The proxy authentication handler. */ 235 @GuardedBy("this") 236 private AuthenticationStrategy proxyAuthStrategy; 237 238 /** The cookie store. */ 239 @GuardedBy("this") 240 private CookieStore cookieStore; 241 242 /** The credentials provider. */ 243 @GuardedBy("this") 244 private CredentialsProvider credsProvider; 245 246 /** The route planner. */ 247 @GuardedBy("this") 248 private HttpRoutePlanner routePlanner; 249 250 /** The user token handler. */ 251 @GuardedBy("this") 252 private UserTokenHandler userTokenHandler; 253 254 /** The connection backoff strategy. */ 255 @GuardedBy("this") 256 private ConnectionBackoffStrategy connectionBackoffStrategy; 257 258 /** The backoff manager. */ 259 @GuardedBy("this") 260 private BackoffManager backoffManager; 261 262 /** 263 * Creates a new HTTP client. 264 * 265 * @param conman the connection manager 266 * @param params the parameters 267 */ AbstractHttpClient( final ClientConnectionManager conman, final HttpParams params)268 protected AbstractHttpClient( 269 final ClientConnectionManager conman, 270 final HttpParams params) { 271 super(); 272 defaultParams = params; 273 connManager = conman; 274 } // constructor 275 276 createHttpParams()277 protected abstract HttpParams createHttpParams(); 278 279 createHttpProcessor()280 protected abstract BasicHttpProcessor createHttpProcessor(); 281 282 createHttpContext()283 protected HttpContext createHttpContext() { 284 final HttpContext context = new BasicHttpContext(); 285 context.setAttribute( 286 ClientContext.SCHEME_REGISTRY, 287 getConnectionManager().getSchemeRegistry()); 288 context.setAttribute( 289 ClientContext.AUTHSCHEME_REGISTRY, 290 getAuthSchemes()); 291 context.setAttribute( 292 ClientContext.COOKIESPEC_REGISTRY, 293 getCookieSpecs()); 294 context.setAttribute( 295 ClientContext.COOKIE_STORE, 296 getCookieStore()); 297 context.setAttribute( 298 ClientContext.CREDS_PROVIDER, 299 getCredentialsProvider()); 300 return context; 301 } 302 303 createClientConnectionManager()304 protected ClientConnectionManager createClientConnectionManager() { 305 final SchemeRegistry registry = SchemeRegistryFactory.createDefault(); 306 307 ClientConnectionManager connManager = null; 308 final HttpParams params = getParams(); 309 310 ClientConnectionManagerFactory factory = null; 311 312 final String className = (String) params.getParameter( 313 ClientPNames.CONNECTION_MANAGER_FACTORY_CLASS_NAME); 314 if (className != null) { 315 try { 316 final Class<?> clazz = Class.forName(className); 317 factory = (ClientConnectionManagerFactory) clazz.newInstance(); 318 } catch (final ClassNotFoundException ex) { 319 throw new IllegalStateException("Invalid class name: " + className); 320 } catch (final IllegalAccessException ex) { 321 throw new IllegalAccessError(ex.getMessage()); 322 } catch (final InstantiationException ex) { 323 throw new InstantiationError(ex.getMessage()); 324 } 325 } 326 if (factory != null) { 327 connManager = factory.newInstance(params, registry); 328 } else { 329 connManager = new BasicClientConnectionManager(registry); 330 } 331 332 return connManager; 333 } 334 335 createAuthSchemeRegistry()336 protected AuthSchemeRegistry createAuthSchemeRegistry() { 337 final AuthSchemeRegistry registry = new AuthSchemeRegistry(); 338 registry.register( 339 AuthPolicy.BASIC, 340 new BasicSchemeFactory()); 341 registry.register( 342 AuthPolicy.DIGEST, 343 new DigestSchemeFactory()); 344 registry.register( 345 AuthPolicy.NTLM, 346 new NTLMSchemeFactory()); 347 /* SPNegoSchemeFactory removed by HttpClient for Android script. */ 348 /* KerberosSchemeFactory removed by HttpClient for Android script. */ 349 return registry; 350 } 351 352 createCookieSpecRegistry()353 protected CookieSpecRegistry createCookieSpecRegistry() { 354 final CookieSpecRegistry registry = new CookieSpecRegistry(); 355 registry.register( 356 CookiePolicy.BEST_MATCH, 357 new BestMatchSpecFactory()); 358 registry.register( 359 CookiePolicy.BROWSER_COMPATIBILITY, 360 new BrowserCompatSpecFactory()); 361 registry.register( 362 CookiePolicy.NETSCAPE, 363 new NetscapeDraftSpecFactory()); 364 registry.register( 365 CookiePolicy.RFC_2109, 366 new RFC2109SpecFactory()); 367 registry.register( 368 CookiePolicy.RFC_2965, 369 new RFC2965SpecFactory()); 370 registry.register( 371 CookiePolicy.IGNORE_COOKIES, 372 new IgnoreSpecFactory()); 373 return registry; 374 } 375 createRequestExecutor()376 protected HttpRequestExecutor createRequestExecutor() { 377 return new HttpRequestExecutor(); 378 } 379 createConnectionReuseStrategy()380 protected ConnectionReuseStrategy createConnectionReuseStrategy() { 381 return new DefaultConnectionReuseStrategy(); 382 } 383 createConnectionKeepAliveStrategy()384 protected ConnectionKeepAliveStrategy createConnectionKeepAliveStrategy() { 385 return new DefaultConnectionKeepAliveStrategy(); 386 } 387 createHttpRequestRetryHandler()388 protected HttpRequestRetryHandler createHttpRequestRetryHandler() { 389 return new DefaultHttpRequestRetryHandler(); 390 } 391 392 /** 393 * @deprecated (4.1) do not use 394 */ 395 @Deprecated createRedirectHandler()396 protected RedirectHandler createRedirectHandler() { 397 return new DefaultRedirectHandler(); 398 } 399 createTargetAuthenticationStrategy()400 protected AuthenticationStrategy createTargetAuthenticationStrategy() { 401 return new TargetAuthenticationStrategy(); 402 } 403 404 /** 405 * @deprecated (4.2) do not use 406 */ 407 @Deprecated createTargetAuthenticationHandler()408 protected AuthenticationHandler createTargetAuthenticationHandler() { 409 return new DefaultTargetAuthenticationHandler(); 410 } 411 createProxyAuthenticationStrategy()412 protected AuthenticationStrategy createProxyAuthenticationStrategy() { 413 return new ProxyAuthenticationStrategy(); 414 } 415 416 /** 417 * @deprecated (4.2) do not use 418 */ 419 @Deprecated createProxyAuthenticationHandler()420 protected AuthenticationHandler createProxyAuthenticationHandler() { 421 return new DefaultProxyAuthenticationHandler(); 422 } 423 createCookieStore()424 protected CookieStore createCookieStore() { 425 return new BasicCookieStore(); 426 } 427 createCredentialsProvider()428 protected CredentialsProvider createCredentialsProvider() { 429 return new BasicCredentialsProvider(); 430 } 431 createHttpRoutePlanner()432 protected HttpRoutePlanner createHttpRoutePlanner() { 433 return new DefaultHttpRoutePlanner(getConnectionManager().getSchemeRegistry()); 434 } 435 createUserTokenHandler()436 protected UserTokenHandler createUserTokenHandler() { 437 return new DefaultUserTokenHandler(); 438 } 439 440 // non-javadoc, see interface HttpClient getParams()441 public synchronized final HttpParams getParams() { 442 if (defaultParams == null) { 443 defaultParams = createHttpParams(); 444 } 445 return defaultParams; 446 } 447 448 /** 449 * Replaces the parameters. 450 * The implementation here does not update parameters of dependent objects. 451 * 452 * @param params the new default parameters 453 */ setParams(final HttpParams params)454 public synchronized void setParams(final HttpParams params) { 455 defaultParams = params; 456 } 457 458 getConnectionManager()459 public synchronized final ClientConnectionManager getConnectionManager() { 460 if (connManager == null) { 461 connManager = createClientConnectionManager(); 462 } 463 return connManager; 464 } 465 466 getRequestExecutor()467 public synchronized final HttpRequestExecutor getRequestExecutor() { 468 if (requestExec == null) { 469 requestExec = createRequestExecutor(); 470 } 471 return requestExec; 472 } 473 474 getAuthSchemes()475 public synchronized final AuthSchemeRegistry getAuthSchemes() { 476 if (supportedAuthSchemes == null) { 477 supportedAuthSchemes = createAuthSchemeRegistry(); 478 } 479 return supportedAuthSchemes; 480 } 481 setAuthSchemes(final AuthSchemeRegistry registry)482 public synchronized void setAuthSchemes(final AuthSchemeRegistry registry) { 483 supportedAuthSchemes = registry; 484 } 485 getConnectionBackoffStrategy()486 public synchronized final ConnectionBackoffStrategy getConnectionBackoffStrategy() { 487 return connectionBackoffStrategy; 488 } 489 setConnectionBackoffStrategy(final ConnectionBackoffStrategy strategy)490 public synchronized void setConnectionBackoffStrategy(final ConnectionBackoffStrategy strategy) { 491 connectionBackoffStrategy = strategy; 492 } 493 getCookieSpecs()494 public synchronized final CookieSpecRegistry getCookieSpecs() { 495 if (supportedCookieSpecs == null) { 496 supportedCookieSpecs = createCookieSpecRegistry(); 497 } 498 return supportedCookieSpecs; 499 } 500 getBackoffManager()501 public synchronized final BackoffManager getBackoffManager() { 502 return backoffManager; 503 } 504 setBackoffManager(final BackoffManager manager)505 public synchronized void setBackoffManager(final BackoffManager manager) { 506 backoffManager = manager; 507 } 508 setCookieSpecs(final CookieSpecRegistry registry)509 public synchronized void setCookieSpecs(final CookieSpecRegistry registry) { 510 supportedCookieSpecs = registry; 511 } 512 getConnectionReuseStrategy()513 public synchronized final ConnectionReuseStrategy getConnectionReuseStrategy() { 514 if (reuseStrategy == null) { 515 reuseStrategy = createConnectionReuseStrategy(); 516 } 517 return reuseStrategy; 518 } 519 520 setReuseStrategy(final ConnectionReuseStrategy strategy)521 public synchronized void setReuseStrategy(final ConnectionReuseStrategy strategy) { 522 this.reuseStrategy = strategy; 523 } 524 525 getConnectionKeepAliveStrategy()526 public synchronized final ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy() { 527 if (keepAliveStrategy == null) { 528 keepAliveStrategy = createConnectionKeepAliveStrategy(); 529 } 530 return keepAliveStrategy; 531 } 532 533 setKeepAliveStrategy(final ConnectionKeepAliveStrategy strategy)534 public synchronized void setKeepAliveStrategy(final ConnectionKeepAliveStrategy strategy) { 535 this.keepAliveStrategy = strategy; 536 } 537 538 getHttpRequestRetryHandler()539 public synchronized final HttpRequestRetryHandler getHttpRequestRetryHandler() { 540 if (retryHandler == null) { 541 retryHandler = createHttpRequestRetryHandler(); 542 } 543 return retryHandler; 544 } 545 setHttpRequestRetryHandler(final HttpRequestRetryHandler handler)546 public synchronized void setHttpRequestRetryHandler(final HttpRequestRetryHandler handler) { 547 this.retryHandler = handler; 548 } 549 550 /** 551 * @deprecated (4.1) do not use 552 */ 553 @Deprecated getRedirectHandler()554 public synchronized final RedirectHandler getRedirectHandler() { 555 return createRedirectHandler(); 556 } 557 558 /** 559 * @deprecated (4.1) do not use 560 */ 561 @Deprecated setRedirectHandler(final RedirectHandler handler)562 public synchronized void setRedirectHandler(final RedirectHandler handler) { 563 this.redirectStrategy = new DefaultRedirectStrategyAdaptor(handler); 564 } 565 566 /** 567 * @since 4.1 568 */ getRedirectStrategy()569 public synchronized final RedirectStrategy getRedirectStrategy() { 570 if (redirectStrategy == null) { 571 redirectStrategy = new DefaultRedirectStrategy(); 572 } 573 return redirectStrategy; 574 } 575 576 /** 577 * @since 4.1 578 */ setRedirectStrategy(final RedirectStrategy strategy)579 public synchronized void setRedirectStrategy(final RedirectStrategy strategy) { 580 this.redirectStrategy = strategy; 581 } 582 583 /** 584 * @deprecated (4.2) do not use 585 */ 586 @Deprecated getTargetAuthenticationHandler()587 public synchronized final AuthenticationHandler getTargetAuthenticationHandler() { 588 return createTargetAuthenticationHandler(); 589 } 590 591 /** 592 * @deprecated (4.2) do not use 593 */ 594 @Deprecated setTargetAuthenticationHandler(final AuthenticationHandler handler)595 public synchronized void setTargetAuthenticationHandler(final AuthenticationHandler handler) { 596 this.targetAuthStrategy = new AuthenticationStrategyAdaptor(handler); 597 } 598 599 /** 600 * @since 4.2 601 */ getTargetAuthenticationStrategy()602 public synchronized final AuthenticationStrategy getTargetAuthenticationStrategy() { 603 if (targetAuthStrategy == null) { 604 targetAuthStrategy = createTargetAuthenticationStrategy(); 605 } 606 return targetAuthStrategy; 607 } 608 609 /** 610 * @since 4.2 611 */ setTargetAuthenticationStrategy(final AuthenticationStrategy strategy)612 public synchronized void setTargetAuthenticationStrategy(final AuthenticationStrategy strategy) { 613 this.targetAuthStrategy = strategy; 614 } 615 616 /** 617 * @deprecated (4.2) do not use 618 */ 619 @Deprecated getProxyAuthenticationHandler()620 public synchronized final AuthenticationHandler getProxyAuthenticationHandler() { 621 return createProxyAuthenticationHandler(); 622 } 623 624 /** 625 * @deprecated (4.2) do not use 626 */ 627 @Deprecated setProxyAuthenticationHandler(final AuthenticationHandler handler)628 public synchronized void setProxyAuthenticationHandler(final AuthenticationHandler handler) { 629 this.proxyAuthStrategy = new AuthenticationStrategyAdaptor(handler); 630 } 631 632 /** 633 * @since 4.2 634 */ getProxyAuthenticationStrategy()635 public synchronized final AuthenticationStrategy getProxyAuthenticationStrategy() { 636 if (proxyAuthStrategy == null) { 637 proxyAuthStrategy = createProxyAuthenticationStrategy(); 638 } 639 return proxyAuthStrategy; 640 } 641 642 /** 643 * @since 4.2 644 */ setProxyAuthenticationStrategy(final AuthenticationStrategy strategy)645 public synchronized void setProxyAuthenticationStrategy(final AuthenticationStrategy strategy) { 646 this.proxyAuthStrategy = strategy; 647 } 648 getCookieStore()649 public synchronized final CookieStore getCookieStore() { 650 if (cookieStore == null) { 651 cookieStore = createCookieStore(); 652 } 653 return cookieStore; 654 } 655 setCookieStore(final CookieStore cookieStore)656 public synchronized void setCookieStore(final CookieStore cookieStore) { 657 this.cookieStore = cookieStore; 658 } 659 getCredentialsProvider()660 public synchronized final CredentialsProvider getCredentialsProvider() { 661 if (credsProvider == null) { 662 credsProvider = createCredentialsProvider(); 663 } 664 return credsProvider; 665 } 666 setCredentialsProvider(final CredentialsProvider credsProvider)667 public synchronized void setCredentialsProvider(final CredentialsProvider credsProvider) { 668 this.credsProvider = credsProvider; 669 } 670 getRoutePlanner()671 public synchronized final HttpRoutePlanner getRoutePlanner() { 672 if (this.routePlanner == null) { 673 this.routePlanner = createHttpRoutePlanner(); 674 } 675 return this.routePlanner; 676 } 677 setRoutePlanner(final HttpRoutePlanner routePlanner)678 public synchronized void setRoutePlanner(final HttpRoutePlanner routePlanner) { 679 this.routePlanner = routePlanner; 680 } 681 getUserTokenHandler()682 public synchronized final UserTokenHandler getUserTokenHandler() { 683 if (this.userTokenHandler == null) { 684 this.userTokenHandler = createUserTokenHandler(); 685 } 686 return this.userTokenHandler; 687 } 688 setUserTokenHandler(final UserTokenHandler handler)689 public synchronized void setUserTokenHandler(final UserTokenHandler handler) { 690 this.userTokenHandler = handler; 691 } 692 getHttpProcessor()693 protected synchronized final BasicHttpProcessor getHttpProcessor() { 694 if (mutableProcessor == null) { 695 mutableProcessor = createHttpProcessor(); 696 } 697 return mutableProcessor; 698 } 699 getProtocolProcessor()700 private synchronized HttpProcessor getProtocolProcessor() { 701 if (protocolProcessor == null) { 702 // Get mutable HTTP processor 703 final BasicHttpProcessor proc = getHttpProcessor(); 704 // and create an immutable copy of it 705 final int reqc = proc.getRequestInterceptorCount(); 706 final HttpRequestInterceptor[] reqinterceptors = new HttpRequestInterceptor[reqc]; 707 for (int i = 0; i < reqc; i++) { 708 reqinterceptors[i] = proc.getRequestInterceptor(i); 709 } 710 final int resc = proc.getResponseInterceptorCount(); 711 final HttpResponseInterceptor[] resinterceptors = new HttpResponseInterceptor[resc]; 712 for (int i = 0; i < resc; i++) { 713 resinterceptors[i] = proc.getResponseInterceptor(i); 714 } 715 protocolProcessor = new ImmutableHttpProcessor(reqinterceptors, resinterceptors); 716 } 717 return protocolProcessor; 718 } 719 getResponseInterceptorCount()720 public synchronized int getResponseInterceptorCount() { 721 return getHttpProcessor().getResponseInterceptorCount(); 722 } 723 getResponseInterceptor(final int index)724 public synchronized HttpResponseInterceptor getResponseInterceptor(final int index) { 725 return getHttpProcessor().getResponseInterceptor(index); 726 } 727 getRequestInterceptor(final int index)728 public synchronized HttpRequestInterceptor getRequestInterceptor(final int index) { 729 return getHttpProcessor().getRequestInterceptor(index); 730 } 731 getRequestInterceptorCount()732 public synchronized int getRequestInterceptorCount() { 733 return getHttpProcessor().getRequestInterceptorCount(); 734 } 735 addResponseInterceptor(final HttpResponseInterceptor itcp)736 public synchronized void addResponseInterceptor(final HttpResponseInterceptor itcp) { 737 getHttpProcessor().addInterceptor(itcp); 738 protocolProcessor = null; 739 } 740 addResponseInterceptor(final HttpResponseInterceptor itcp, final int index)741 public synchronized void addResponseInterceptor(final HttpResponseInterceptor itcp, final int index) { 742 getHttpProcessor().addInterceptor(itcp, index); 743 protocolProcessor = null; 744 } 745 clearResponseInterceptors()746 public synchronized void clearResponseInterceptors() { 747 getHttpProcessor().clearResponseInterceptors(); 748 protocolProcessor = null; 749 } 750 removeResponseInterceptorByClass(final Class<? extends HttpResponseInterceptor> clazz)751 public synchronized void removeResponseInterceptorByClass(final Class<? extends HttpResponseInterceptor> clazz) { 752 getHttpProcessor().removeResponseInterceptorByClass(clazz); 753 protocolProcessor = null; 754 } 755 addRequestInterceptor(final HttpRequestInterceptor itcp)756 public synchronized void addRequestInterceptor(final HttpRequestInterceptor itcp) { 757 getHttpProcessor().addInterceptor(itcp); 758 protocolProcessor = null; 759 } 760 addRequestInterceptor(final HttpRequestInterceptor itcp, final int index)761 public synchronized void addRequestInterceptor(final HttpRequestInterceptor itcp, final int index) { 762 getHttpProcessor().addInterceptor(itcp, index); 763 protocolProcessor = null; 764 } 765 clearRequestInterceptors()766 public synchronized void clearRequestInterceptors() { 767 getHttpProcessor().clearRequestInterceptors(); 768 protocolProcessor = null; 769 } 770 removeRequestInterceptorByClass(final Class<? extends HttpRequestInterceptor> clazz)771 public synchronized void removeRequestInterceptorByClass(final Class<? extends HttpRequestInterceptor> clazz) { 772 getHttpProcessor().removeRequestInterceptorByClass(clazz); 773 protocolProcessor = null; 774 } 775 776 @Override doExecute(final HttpHost target, final HttpRequest request, final HttpContext context)777 protected final CloseableHttpResponse doExecute(final HttpHost target, final HttpRequest request, 778 final HttpContext context) 779 throws IOException, ClientProtocolException { 780 781 Args.notNull(request, "HTTP request"); 782 // a null target may be acceptable, this depends on the route planner 783 // a null context is acceptable, default context created below 784 785 HttpContext execContext = null; 786 RequestDirector director = null; 787 HttpRoutePlanner routePlanner = null; 788 ConnectionBackoffStrategy connectionBackoffStrategy = null; 789 BackoffManager backoffManager = null; 790 791 // Initialize the request execution context making copies of 792 // all shared objects that are potentially threading unsafe. 793 synchronized (this) { 794 795 final HttpContext defaultContext = createHttpContext(); 796 if (context == null) { 797 execContext = defaultContext; 798 } else { 799 execContext = new DefaultedHttpContext(context, defaultContext); 800 } 801 final HttpParams params = determineParams(request); 802 final RequestConfig config = HttpClientParamConfig.getRequestConfig(params); 803 execContext.setAttribute(ClientContext.REQUEST_CONFIG, config); 804 805 // Create a director for this request 806 director = createClientRequestDirector( 807 getRequestExecutor(), 808 getConnectionManager(), 809 getConnectionReuseStrategy(), 810 getConnectionKeepAliveStrategy(), 811 getRoutePlanner(), 812 getProtocolProcessor(), 813 getHttpRequestRetryHandler(), 814 getRedirectStrategy(), 815 getTargetAuthenticationStrategy(), 816 getProxyAuthenticationStrategy(), 817 getUserTokenHandler(), 818 params); 819 routePlanner = getRoutePlanner(); 820 connectionBackoffStrategy = getConnectionBackoffStrategy(); 821 backoffManager = getBackoffManager(); 822 } 823 824 try { 825 if (connectionBackoffStrategy != null && backoffManager != null) { 826 final HttpHost targetForRoute = (target != null) ? target 827 : (HttpHost) determineParams(request).getParameter( 828 ClientPNames.DEFAULT_HOST); 829 final HttpRoute route = routePlanner.determineRoute(targetForRoute, request, execContext); 830 831 final CloseableHttpResponse out; 832 try { 833 out = CloseableHttpResponseProxy.newProxy( 834 director.execute(target, request, execContext)); 835 } catch (final RuntimeException re) { 836 if (connectionBackoffStrategy.shouldBackoff(re)) { 837 backoffManager.backOff(route); 838 } 839 throw re; 840 } catch (final Exception e) { 841 if (connectionBackoffStrategy.shouldBackoff(e)) { 842 backoffManager.backOff(route); 843 } 844 if (e instanceof HttpException) { 845 throw (HttpException)e; 846 } 847 if (e instanceof IOException) { 848 throw (IOException)e; 849 } 850 throw new UndeclaredThrowableException(e); 851 } 852 if (connectionBackoffStrategy.shouldBackoff(out)) { 853 backoffManager.backOff(route); 854 } else { 855 backoffManager.probe(route); 856 } 857 return out; 858 } else { 859 return CloseableHttpResponseProxy.newProxy( 860 director.execute(target, request, execContext)); 861 } 862 } catch(final HttpException httpException) { 863 throw new ClientProtocolException(httpException); 864 } 865 } 866 867 /** 868 * @deprecated (4.1) do not use 869 */ 870 @Deprecated createClientRequestDirector( final HttpRequestExecutor requestExec, final ClientConnectionManager conman, final ConnectionReuseStrategy reustrat, final ConnectionKeepAliveStrategy kastrat, final HttpRoutePlanner rouplan, final HttpProcessor httpProcessor, final HttpRequestRetryHandler retryHandler, final RedirectHandler redirectHandler, final AuthenticationHandler targetAuthHandler, final AuthenticationHandler proxyAuthHandler, final UserTokenHandler userTokenHandler, final HttpParams params)871 protected RequestDirector createClientRequestDirector( 872 final HttpRequestExecutor requestExec, 873 final ClientConnectionManager conman, 874 final ConnectionReuseStrategy reustrat, 875 final ConnectionKeepAliveStrategy kastrat, 876 final HttpRoutePlanner rouplan, 877 final HttpProcessor httpProcessor, 878 final HttpRequestRetryHandler retryHandler, 879 final RedirectHandler redirectHandler, 880 final AuthenticationHandler targetAuthHandler, 881 final AuthenticationHandler proxyAuthHandler, 882 final UserTokenHandler userTokenHandler, 883 final HttpParams params) { 884 return new DefaultRequestDirector( 885 requestExec, 886 conman, 887 reustrat, 888 kastrat, 889 rouplan, 890 httpProcessor, 891 retryHandler, 892 redirectHandler, 893 targetAuthHandler, 894 proxyAuthHandler, 895 userTokenHandler, 896 params); 897 } 898 899 /** 900 * @deprecated (4.2) do not use 901 */ 902 @Deprecated createClientRequestDirector( final HttpRequestExecutor requestExec, final ClientConnectionManager conman, final ConnectionReuseStrategy reustrat, final ConnectionKeepAliveStrategy kastrat, final HttpRoutePlanner rouplan, final HttpProcessor httpProcessor, final HttpRequestRetryHandler retryHandler, final RedirectStrategy redirectStrategy, final AuthenticationHandler targetAuthHandler, final AuthenticationHandler proxyAuthHandler, final UserTokenHandler userTokenHandler, final HttpParams params)903 protected RequestDirector createClientRequestDirector( 904 final HttpRequestExecutor requestExec, 905 final ClientConnectionManager conman, 906 final ConnectionReuseStrategy reustrat, 907 final ConnectionKeepAliveStrategy kastrat, 908 final HttpRoutePlanner rouplan, 909 final HttpProcessor httpProcessor, 910 final HttpRequestRetryHandler retryHandler, 911 final RedirectStrategy redirectStrategy, 912 final AuthenticationHandler targetAuthHandler, 913 final AuthenticationHandler proxyAuthHandler, 914 final UserTokenHandler userTokenHandler, 915 final HttpParams params) { 916 return new DefaultRequestDirector( 917 log, 918 requestExec, 919 conman, 920 reustrat, 921 kastrat, 922 rouplan, 923 httpProcessor, 924 retryHandler, 925 redirectStrategy, 926 targetAuthHandler, 927 proxyAuthHandler, 928 userTokenHandler, 929 params); 930 } 931 932 933 /** 934 * @since 4.2 935 */ createClientRequestDirector( final HttpRequestExecutor requestExec, final ClientConnectionManager conman, final ConnectionReuseStrategy reustrat, final ConnectionKeepAliveStrategy kastrat, final HttpRoutePlanner rouplan, final HttpProcessor httpProcessor, final HttpRequestRetryHandler retryHandler, final RedirectStrategy redirectStrategy, final AuthenticationStrategy targetAuthStrategy, final AuthenticationStrategy proxyAuthStrategy, final UserTokenHandler userTokenHandler, final HttpParams params)936 protected RequestDirector createClientRequestDirector( 937 final HttpRequestExecutor requestExec, 938 final ClientConnectionManager conman, 939 final ConnectionReuseStrategy reustrat, 940 final ConnectionKeepAliveStrategy kastrat, 941 final HttpRoutePlanner rouplan, 942 final HttpProcessor httpProcessor, 943 final HttpRequestRetryHandler retryHandler, 944 final RedirectStrategy redirectStrategy, 945 final AuthenticationStrategy targetAuthStrategy, 946 final AuthenticationStrategy proxyAuthStrategy, 947 final UserTokenHandler userTokenHandler, 948 final HttpParams params) { 949 return new DefaultRequestDirector( 950 log, 951 requestExec, 952 conman, 953 reustrat, 954 kastrat, 955 rouplan, 956 httpProcessor, 957 retryHandler, 958 redirectStrategy, 959 targetAuthStrategy, 960 proxyAuthStrategy, 961 userTokenHandler, 962 params); 963 } 964 965 /** 966 * Obtains parameters for executing a request. 967 * The default implementation in this class creates a new 968 * {@link ClientParamsStack} from the request parameters 969 * and the client parameters. 970 * <br/> 971 * This method is called by the default implementation of 972 * {@link #execute(HttpHost,HttpRequest,HttpContext)} 973 * to obtain the parameters for the 974 * {@link DefaultRequestDirector}. 975 * 976 * @param req the request that will be executed 977 * 978 * @return the parameters to use 979 */ determineParams(final HttpRequest req)980 protected HttpParams determineParams(final HttpRequest req) { 981 return new ClientParamsStack 982 (null, getParams(), req.getParams(), null); 983 } 984 985 close()986 public void close() { 987 getConnectionManager().shutdown(); 988 } 989 990 } 991