mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AbstractHttpClient.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

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

mercurial