1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AbstractHttpClient.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,976 @@ 1.4 +/* 1.5 + * ==================================================================== 1.6 + * Licensed to the Apache Software Foundation (ASF) under one 1.7 + * or more contributor license agreements. See the NOTICE file 1.8 + * distributed with this work for additional information 1.9 + * regarding copyright ownership. The ASF licenses this file 1.10 + * to you under the Apache License, Version 2.0 (the 1.11 + * "License"); you may not use this file except in compliance 1.12 + * with the License. You may obtain a copy of the License at 1.13 + * 1.14 + * http://www.apache.org/licenses/LICENSE-2.0 1.15 + * 1.16 + * Unless required by applicable law or agreed to in writing, 1.17 + * software distributed under the License is distributed on an 1.18 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1.19 + * KIND, either express or implied. See the License for the 1.20 + * specific language governing permissions and limitations 1.21 + * under the License. 1.22 + * ==================================================================== 1.23 + * 1.24 + * This software consists of voluntary contributions made by many 1.25 + * individuals on behalf of the Apache Software Foundation. For more 1.26 + * information on the Apache Software Foundation, please see 1.27 + * <http://www.apache.org/>. 1.28 + * 1.29 + */ 1.30 + 1.31 +package ch.boye.httpclientandroidlib.impl.client; 1.32 + 1.33 +import java.io.IOException; 1.34 +import java.lang.reflect.UndeclaredThrowableException; 1.35 +import java.net.URI; 1.36 + 1.37 +import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog; 1.38 +/* LogFactory removed by HttpClient for Android script. */ 1.39 +import ch.boye.httpclientandroidlib.ConnectionReuseStrategy; 1.40 +import ch.boye.httpclientandroidlib.HttpEntity; 1.41 +import ch.boye.httpclientandroidlib.HttpException; 1.42 +import ch.boye.httpclientandroidlib.HttpHost; 1.43 +import ch.boye.httpclientandroidlib.HttpRequest; 1.44 +import ch.boye.httpclientandroidlib.HttpRequestInterceptor; 1.45 +import ch.boye.httpclientandroidlib.HttpResponse; 1.46 +import ch.boye.httpclientandroidlib.HttpResponseInterceptor; 1.47 +import ch.boye.httpclientandroidlib.annotation.GuardedBy; 1.48 +import ch.boye.httpclientandroidlib.annotation.ThreadSafe; 1.49 +import ch.boye.httpclientandroidlib.auth.AuthSchemeRegistry; 1.50 +import ch.boye.httpclientandroidlib.client.AuthenticationHandler; 1.51 +import ch.boye.httpclientandroidlib.client.ClientProtocolException; 1.52 +import ch.boye.httpclientandroidlib.client.CookieStore; 1.53 +import ch.boye.httpclientandroidlib.client.CredentialsProvider; 1.54 +import ch.boye.httpclientandroidlib.client.HttpClient; 1.55 +import ch.boye.httpclientandroidlib.client.HttpRequestRetryHandler; 1.56 +import ch.boye.httpclientandroidlib.client.RedirectHandler; 1.57 +import ch.boye.httpclientandroidlib.client.RedirectStrategy; 1.58 +import ch.boye.httpclientandroidlib.client.RequestDirector; 1.59 +import ch.boye.httpclientandroidlib.client.ResponseHandler; 1.60 +import ch.boye.httpclientandroidlib.client.UserTokenHandler; 1.61 +import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest; 1.62 +import ch.boye.httpclientandroidlib.client.params.AuthPolicy; 1.63 +import ch.boye.httpclientandroidlib.client.params.ClientPNames; 1.64 +import ch.boye.httpclientandroidlib.client.params.CookiePolicy; 1.65 +import ch.boye.httpclientandroidlib.client.protocol.ClientContext; 1.66 +import ch.boye.httpclientandroidlib.client.utils.URIUtils; 1.67 +import ch.boye.httpclientandroidlib.conn.ClientConnectionManager; 1.68 +import ch.boye.httpclientandroidlib.conn.ClientConnectionManagerFactory; 1.69 +import ch.boye.httpclientandroidlib.conn.ConnectionKeepAliveStrategy; 1.70 +import ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner; 1.71 +import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry; 1.72 +import ch.boye.httpclientandroidlib.cookie.CookieSpecRegistry; 1.73 +import ch.boye.httpclientandroidlib.impl.DefaultConnectionReuseStrategy; 1.74 +import ch.boye.httpclientandroidlib.impl.auth.BasicSchemeFactory; 1.75 +import ch.boye.httpclientandroidlib.impl.auth.DigestSchemeFactory; 1.76 +import ch.boye.httpclientandroidlib.impl.auth.NTLMSchemeFactory; 1.77 +/* NegotiateSchemeFactory removed by HttpClient for Android script. */ 1.78 +import ch.boye.httpclientandroidlib.impl.conn.DefaultHttpRoutePlanner; 1.79 +import ch.boye.httpclientandroidlib.impl.conn.SchemeRegistryFactory; 1.80 +import ch.boye.httpclientandroidlib.impl.conn.SingleClientConnManager; 1.81 +import ch.boye.httpclientandroidlib.impl.cookie.BestMatchSpecFactory; 1.82 +import ch.boye.httpclientandroidlib.impl.cookie.BrowserCompatSpecFactory; 1.83 +import ch.boye.httpclientandroidlib.impl.cookie.IgnoreSpecFactory; 1.84 +import ch.boye.httpclientandroidlib.impl.cookie.NetscapeDraftSpecFactory; 1.85 +import ch.boye.httpclientandroidlib.impl.cookie.RFC2109SpecFactory; 1.86 +import ch.boye.httpclientandroidlib.impl.cookie.RFC2965SpecFactory; 1.87 +import ch.boye.httpclientandroidlib.params.HttpParams; 1.88 +import ch.boye.httpclientandroidlib.protocol.BasicHttpContext; 1.89 +import ch.boye.httpclientandroidlib.protocol.BasicHttpProcessor; 1.90 +import ch.boye.httpclientandroidlib.protocol.DefaultedHttpContext; 1.91 +import ch.boye.httpclientandroidlib.protocol.HttpContext; 1.92 +import ch.boye.httpclientandroidlib.protocol.HttpProcessor; 1.93 +import ch.boye.httpclientandroidlib.protocol.HttpRequestExecutor; 1.94 +import ch.boye.httpclientandroidlib.protocol.ImmutableHttpProcessor; 1.95 +import ch.boye.httpclientandroidlib.util.EntityUtils; 1.96 + 1.97 +/** 1.98 + * Base class for {@link HttpClient} implementations. This class acts as 1.99 + * a facade to a number of special purpose handler or strategy 1.100 + * implementations responsible for handling of a particular aspect of 1.101 + * the HTTP protocol such as redirect or authentication handling or 1.102 + * making decision about connection persistence and keep alive duration. 1.103 + * This enables the users to selectively replace default implementation 1.104 + * of those aspects with custom, application specific ones. This class 1.105 + * also provides factory methods to instantiate those objects: 1.106 + * <ul> 1.107 + * <li>{@link HttpRequestExecutor}</li> object used to transmit messages 1.108 + * over HTTP connections. The {@link #createRequestExecutor()} must be 1.109 + * implemented by concrete super classes to instantiate this object. 1.110 + * <li>{@link BasicHttpProcessor}</li> object to manage a list of protocol 1.111 + * interceptors and apply cross-cutting protocol logic to all incoming 1.112 + * and outgoing HTTP messages. The {@link #createHttpProcessor()} must be 1.113 + * implemented by concrete super classes to instantiate this object. 1.114 + * <li>{@link HttpRequestRetryHandler}</li> object used to decide whether 1.115 + * or not a failed HTTP request is safe to retry automatically. 1.116 + * The {@link #createHttpRequestRetryHandler()} must be 1.117 + * implemented by concrete super classes to instantiate this object. 1.118 + * <li>{@link ClientConnectionManager}</li> object used to manage 1.119 + * persistent HTTP connections. 1.120 + * <li>{@link ConnectionReuseStrategy}</li> object used to decide whether 1.121 + * or not a HTTP connection can be kept alive and re-used for subsequent 1.122 + * HTTP requests. The {@link #createConnectionReuseStrategy()} must be 1.123 + * implemented by concrete super classes to instantiate this object. 1.124 + * <li>{@link ConnectionKeepAliveStrategy}</li> object used to decide how 1.125 + * long a persistent HTTP connection can be kept alive. 1.126 + * The {@link #createConnectionKeepAliveStrategy()} must be 1.127 + * implemented by concrete super classes to instantiate this object. 1.128 + * <li>{@link CookieSpecRegistry}</li> object used to maintain a list of 1.129 + * supported cookie specifications. 1.130 + * The {@link #createCookieSpecRegistry()} must be implemented by concrete 1.131 + * super classes to instantiate this object. 1.132 + * <li>{@link CookieStore}</li> object used to maintain a collection of 1.133 + * cookies. The {@link #createCookieStore()} must be implemented by 1.134 + * concrete super classes to instantiate this object. 1.135 + * <li>{@link AuthSchemeRegistry}</li> object used to maintain a list of 1.136 + * supported authentication schemes. 1.137 + * The {@link #createAuthSchemeRegistry()} must be implemented by concrete 1.138 + * super classes to instantiate this object. 1.139 + * <li>{@link CredentialsProvider}</li> object used to maintain 1.140 + * a collection user credentials. The {@link #createCredentialsProvider()} 1.141 + * must be implemented by concrete super classes to instantiate 1.142 + * this object. 1.143 + * <li>{@link AuthenticationHandler}</li> object used to authenticate 1.144 + * against the target host. 1.145 + * The {@link #createTargetAuthenticationHandler()} must be implemented 1.146 + * by concrete super classes to instantiate this object. 1.147 + * <li>{@link AuthenticationHandler}</li> object used to authenticate 1.148 + * against the proxy host. 1.149 + * The {@link #createProxyAuthenticationHandler()} must be implemented 1.150 + * by concrete super classes to instantiate this object. 1.151 + * <li>{@link HttpRoutePlanner}</li> object used to calculate a route 1.152 + * for establishing a connection to the target host. The route 1.153 + * may involve multiple intermediate hops. 1.154 + * The {@link #createHttpRoutePlanner()} must be implemented 1.155 + * by concrete super classes to instantiate this object. 1.156 + * <li>{@link RedirectStrategy}</li> object used to determine if an HTTP 1.157 + * request should be redirected to a new location in response to an HTTP 1.158 + * response received from the target server. 1.159 + * <li>{@link UserTokenHandler}</li> object used to determine if the 1.160 + * execution context is user identity specific. 1.161 + * The {@link #createUserTokenHandler()} must be implemented by 1.162 + * concrete super classes to instantiate this object. 1.163 + * </ul> 1.164 + * <p> 1.165 + * This class also maintains a list of protocol interceptors intended 1.166 + * for processing outgoing requests and incoming responses and provides 1.167 + * methods for managing those interceptors. New protocol interceptors can be 1.168 + * introduced to the protocol processor chain or removed from it if needed. 1.169 + * Internally protocol interceptors are stored in a simple 1.170 + * {@link java.util.ArrayList}. They are executed in the same natural order 1.171 + * as they are added to the list. 1.172 + * <p> 1.173 + * AbstractHttpClient is thread safe. It is recommended that the same 1.174 + * instance of this class is reused for multiple request executions. 1.175 + * When an instance of DefaultHttpClient is no longer needed and is about 1.176 + * to go out of scope the connection manager associated with it must be 1.177 + * shut down by calling {@link ClientConnectionManager#shutdown()}! 1.178 + * 1.179 + * @since 4.0 1.180 + */ 1.181 +@ThreadSafe 1.182 +@SuppressWarnings("deprecation") 1.183 +public abstract class AbstractHttpClient implements HttpClient { 1.184 + 1.185 + public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass()); 1.186 + 1.187 + /** The parameters. */ 1.188 + @GuardedBy("this") 1.189 + private HttpParams defaultParams; 1.190 + 1.191 + /** The request executor. */ 1.192 + @GuardedBy("this") 1.193 + private HttpRequestExecutor requestExec; 1.194 + 1.195 + /** The connection manager. */ 1.196 + @GuardedBy("this") 1.197 + private ClientConnectionManager connManager; 1.198 + 1.199 + /** The connection re-use strategy. */ 1.200 + @GuardedBy("this") 1.201 + private ConnectionReuseStrategy reuseStrategy; 1.202 + 1.203 + /** The connection keep-alive strategy. */ 1.204 + @GuardedBy("this") 1.205 + private ConnectionKeepAliveStrategy keepAliveStrategy; 1.206 + 1.207 + /** The cookie spec registry. */ 1.208 + @GuardedBy("this") 1.209 + private CookieSpecRegistry supportedCookieSpecs; 1.210 + 1.211 + /** The authentication scheme registry. */ 1.212 + @GuardedBy("this") 1.213 + private AuthSchemeRegistry supportedAuthSchemes; 1.214 + 1.215 + /** The HTTP protocol processor and its immutable copy. */ 1.216 + @GuardedBy("this") 1.217 + private BasicHttpProcessor mutableProcessor; 1.218 + 1.219 + @GuardedBy("this") 1.220 + private ImmutableHttpProcessor protocolProcessor; 1.221 + 1.222 + /** The request retry handler. */ 1.223 + @GuardedBy("this") 1.224 + private HttpRequestRetryHandler retryHandler; 1.225 + 1.226 + /** The redirect handler. */ 1.227 + @GuardedBy("this") 1.228 + private RedirectStrategy redirectStrategy; 1.229 + 1.230 + /** The target authentication handler. */ 1.231 + @GuardedBy("this") 1.232 + private AuthenticationHandler targetAuthHandler; 1.233 + 1.234 + /** The proxy authentication handler. */ 1.235 + @GuardedBy("this") 1.236 + private AuthenticationHandler proxyAuthHandler; 1.237 + 1.238 + /** The cookie store. */ 1.239 + @GuardedBy("this") 1.240 + private CookieStore cookieStore; 1.241 + 1.242 + /** The credentials provider. */ 1.243 + @GuardedBy("this") 1.244 + private CredentialsProvider credsProvider; 1.245 + 1.246 + /** The route planner. */ 1.247 + @GuardedBy("this") 1.248 + private HttpRoutePlanner routePlanner; 1.249 + 1.250 + /** The user token handler. */ 1.251 + @GuardedBy("this") 1.252 + private UserTokenHandler userTokenHandler; 1.253 + 1.254 + 1.255 + /** 1.256 + * Creates a new HTTP client. 1.257 + * 1.258 + * @param conman the connection manager 1.259 + * @param params the parameters 1.260 + */ 1.261 + protected AbstractHttpClient( 1.262 + final ClientConnectionManager conman, 1.263 + final HttpParams params) { 1.264 + defaultParams = params; 1.265 + connManager = conman; 1.266 + } // constructor 1.267 + 1.268 + 1.269 + protected abstract HttpParams createHttpParams(); 1.270 + 1.271 + 1.272 + protected abstract BasicHttpProcessor createHttpProcessor(); 1.273 + 1.274 + 1.275 + protected HttpContext createHttpContext() { 1.276 + HttpContext context = new BasicHttpContext(); 1.277 + context.setAttribute( 1.278 + ClientContext.SCHEME_REGISTRY, 1.279 + getConnectionManager().getSchemeRegistry()); 1.280 + context.setAttribute( 1.281 + ClientContext.AUTHSCHEME_REGISTRY, 1.282 + getAuthSchemes()); 1.283 + context.setAttribute( 1.284 + ClientContext.COOKIESPEC_REGISTRY, 1.285 + getCookieSpecs()); 1.286 + context.setAttribute( 1.287 + ClientContext.COOKIE_STORE, 1.288 + getCookieStore()); 1.289 + context.setAttribute( 1.290 + ClientContext.CREDS_PROVIDER, 1.291 + getCredentialsProvider()); 1.292 + return context; 1.293 + } 1.294 + 1.295 + 1.296 + protected ClientConnectionManager createClientConnectionManager() { 1.297 + SchemeRegistry registry = SchemeRegistryFactory.createDefault(); 1.298 + 1.299 + ClientConnectionManager connManager = null; 1.300 + HttpParams params = getParams(); 1.301 + 1.302 + ClientConnectionManagerFactory factory = null; 1.303 + 1.304 + String className = (String) params.getParameter( 1.305 + ClientPNames.CONNECTION_MANAGER_FACTORY_CLASS_NAME); 1.306 + if (className != null) { 1.307 + try { 1.308 + Class<?> clazz = Class.forName(className); 1.309 + factory = (ClientConnectionManagerFactory) clazz.newInstance(); 1.310 + } catch (ClassNotFoundException ex) { 1.311 + throw new IllegalStateException("Invalid class name: " + className); 1.312 + } catch (IllegalAccessException ex) { 1.313 + throw new IllegalAccessError(ex.getMessage()); 1.314 + } catch (InstantiationException ex) { 1.315 + throw new InstantiationError(ex.getMessage()); 1.316 + } 1.317 + } 1.318 + if (factory != null) { 1.319 + connManager = factory.newInstance(params, registry); 1.320 + } else { 1.321 + connManager = new SingleClientConnManager(registry); 1.322 + } 1.323 + 1.324 + return connManager; 1.325 + } 1.326 + 1.327 + 1.328 + protected AuthSchemeRegistry createAuthSchemeRegistry() { 1.329 + AuthSchemeRegistry registry = new AuthSchemeRegistry(); 1.330 + registry.register( 1.331 + AuthPolicy.BASIC, 1.332 + new BasicSchemeFactory()); 1.333 + registry.register( 1.334 + AuthPolicy.DIGEST, 1.335 + new DigestSchemeFactory()); 1.336 + registry.register( 1.337 + AuthPolicy.NTLM, 1.338 + new NTLMSchemeFactory()); 1.339 + /* NegotiateSchemeFactory removed by HttpClient for Android script. */ 1.340 + return registry; 1.341 + } 1.342 + 1.343 + 1.344 + protected CookieSpecRegistry createCookieSpecRegistry() { 1.345 + CookieSpecRegistry registry = new CookieSpecRegistry(); 1.346 + registry.register( 1.347 + CookiePolicy.BEST_MATCH, 1.348 + new BestMatchSpecFactory()); 1.349 + registry.register( 1.350 + CookiePolicy.BROWSER_COMPATIBILITY, 1.351 + new BrowserCompatSpecFactory()); 1.352 + registry.register( 1.353 + CookiePolicy.NETSCAPE, 1.354 + new NetscapeDraftSpecFactory()); 1.355 + registry.register( 1.356 + CookiePolicy.RFC_2109, 1.357 + new RFC2109SpecFactory()); 1.358 + registry.register( 1.359 + CookiePolicy.RFC_2965, 1.360 + new RFC2965SpecFactory()); 1.361 + registry.register( 1.362 + CookiePolicy.IGNORE_COOKIES, 1.363 + new IgnoreSpecFactory()); 1.364 + return registry; 1.365 + } 1.366 + 1.367 + 1.368 + protected HttpRequestExecutor createRequestExecutor() { 1.369 + return new HttpRequestExecutor(); 1.370 + } 1.371 + 1.372 + 1.373 + protected ConnectionReuseStrategy createConnectionReuseStrategy() { 1.374 + return new DefaultConnectionReuseStrategy(); 1.375 + } 1.376 + 1.377 + 1.378 + protected ConnectionKeepAliveStrategy createConnectionKeepAliveStrategy() { 1.379 + return new DefaultConnectionKeepAliveStrategy(); 1.380 + } 1.381 + 1.382 + 1.383 + protected HttpRequestRetryHandler createHttpRequestRetryHandler() { 1.384 + return new DefaultHttpRequestRetryHandler(); 1.385 + } 1.386 + 1.387 + 1.388 + @Deprecated 1.389 + protected RedirectHandler createRedirectHandler() { 1.390 + return new DefaultRedirectHandler(); 1.391 + } 1.392 + 1.393 + 1.394 + protected AuthenticationHandler createTargetAuthenticationHandler() { 1.395 + return new DefaultTargetAuthenticationHandler(); 1.396 + } 1.397 + 1.398 + 1.399 + protected AuthenticationHandler createProxyAuthenticationHandler() { 1.400 + return new DefaultProxyAuthenticationHandler(); 1.401 + } 1.402 + 1.403 + 1.404 + protected CookieStore createCookieStore() { 1.405 + return new BasicCookieStore(); 1.406 + } 1.407 + 1.408 + 1.409 + protected CredentialsProvider createCredentialsProvider() { 1.410 + return new BasicCredentialsProvider(); 1.411 + } 1.412 + 1.413 + 1.414 + protected HttpRoutePlanner createHttpRoutePlanner() { 1.415 + return new DefaultHttpRoutePlanner(getConnectionManager().getSchemeRegistry()); 1.416 + } 1.417 + 1.418 + 1.419 + protected UserTokenHandler createUserTokenHandler() { 1.420 + return new DefaultUserTokenHandler(); 1.421 + } 1.422 + 1.423 + 1.424 + // non-javadoc, see interface HttpClient 1.425 + public synchronized final HttpParams getParams() { 1.426 + if (defaultParams == null) { 1.427 + defaultParams = createHttpParams(); 1.428 + } 1.429 + return defaultParams; 1.430 + } 1.431 + 1.432 + 1.433 + /** 1.434 + * Replaces the parameters. 1.435 + * The implementation here does not update parameters of dependent objects. 1.436 + * 1.437 + * @param params the new default parameters 1.438 + */ 1.439 + public synchronized void setParams(HttpParams params) { 1.440 + defaultParams = params; 1.441 + } 1.442 + 1.443 + 1.444 + public synchronized final ClientConnectionManager getConnectionManager() { 1.445 + if (connManager == null) { 1.446 + connManager = createClientConnectionManager(); 1.447 + } 1.448 + return connManager; 1.449 + } 1.450 + 1.451 + 1.452 + public synchronized final HttpRequestExecutor getRequestExecutor() { 1.453 + if (requestExec == null) { 1.454 + requestExec = createRequestExecutor(); 1.455 + } 1.456 + return requestExec; 1.457 + } 1.458 + 1.459 + 1.460 + public synchronized final AuthSchemeRegistry getAuthSchemes() { 1.461 + if (supportedAuthSchemes == null) { 1.462 + supportedAuthSchemes = createAuthSchemeRegistry(); 1.463 + } 1.464 + return supportedAuthSchemes; 1.465 + } 1.466 + 1.467 + 1.468 + public synchronized void setAuthSchemes(final AuthSchemeRegistry authSchemeRegistry) { 1.469 + supportedAuthSchemes = authSchemeRegistry; 1.470 + } 1.471 + 1.472 + 1.473 + public synchronized final CookieSpecRegistry getCookieSpecs() { 1.474 + if (supportedCookieSpecs == null) { 1.475 + supportedCookieSpecs = createCookieSpecRegistry(); 1.476 + } 1.477 + return supportedCookieSpecs; 1.478 + } 1.479 + 1.480 + 1.481 + public synchronized void setCookieSpecs(final CookieSpecRegistry cookieSpecRegistry) { 1.482 + supportedCookieSpecs = cookieSpecRegistry; 1.483 + } 1.484 + 1.485 + 1.486 + public synchronized final ConnectionReuseStrategy getConnectionReuseStrategy() { 1.487 + if (reuseStrategy == null) { 1.488 + reuseStrategy = createConnectionReuseStrategy(); 1.489 + } 1.490 + return reuseStrategy; 1.491 + } 1.492 + 1.493 + 1.494 + public synchronized void setReuseStrategy(final ConnectionReuseStrategy reuseStrategy) { 1.495 + this.reuseStrategy = reuseStrategy; 1.496 + } 1.497 + 1.498 + 1.499 + public synchronized final ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy() { 1.500 + if (keepAliveStrategy == null) { 1.501 + keepAliveStrategy = createConnectionKeepAliveStrategy(); 1.502 + } 1.503 + return keepAliveStrategy; 1.504 + } 1.505 + 1.506 + 1.507 + public synchronized void setKeepAliveStrategy(final ConnectionKeepAliveStrategy keepAliveStrategy) { 1.508 + this.keepAliveStrategy = keepAliveStrategy; 1.509 + } 1.510 + 1.511 + 1.512 + public synchronized final HttpRequestRetryHandler getHttpRequestRetryHandler() { 1.513 + if (retryHandler == null) { 1.514 + retryHandler = createHttpRequestRetryHandler(); 1.515 + } 1.516 + return retryHandler; 1.517 + } 1.518 + 1.519 + 1.520 + public synchronized void setHttpRequestRetryHandler(final HttpRequestRetryHandler retryHandler) { 1.521 + this.retryHandler = retryHandler; 1.522 + } 1.523 + 1.524 + 1.525 + @Deprecated 1.526 + public synchronized final RedirectHandler getRedirectHandler() { 1.527 + return createRedirectHandler(); 1.528 + } 1.529 + 1.530 + 1.531 + @Deprecated 1.532 + public synchronized void setRedirectHandler(final RedirectHandler redirectHandler) { 1.533 + this.redirectStrategy = new DefaultRedirectStrategyAdaptor(redirectHandler); 1.534 + } 1.535 + 1.536 + /** 1.537 + * @since 4.1 1.538 + */ 1.539 + public synchronized final RedirectStrategy getRedirectStrategy() { 1.540 + if (redirectStrategy == null) { 1.541 + redirectStrategy = new DefaultRedirectStrategy(); 1.542 + } 1.543 + return redirectStrategy; 1.544 + } 1.545 + 1.546 + /** 1.547 + * @since 4.1 1.548 + */ 1.549 + public synchronized void setRedirectStrategy(final RedirectStrategy redirectStrategy) { 1.550 + this.redirectStrategy = redirectStrategy; 1.551 + } 1.552 + 1.553 + 1.554 + public synchronized final AuthenticationHandler getTargetAuthenticationHandler() { 1.555 + if (targetAuthHandler == null) { 1.556 + targetAuthHandler = createTargetAuthenticationHandler(); 1.557 + } 1.558 + return targetAuthHandler; 1.559 + } 1.560 + 1.561 + 1.562 + public synchronized void setTargetAuthenticationHandler( 1.563 + final AuthenticationHandler targetAuthHandler) { 1.564 + this.targetAuthHandler = targetAuthHandler; 1.565 + } 1.566 + 1.567 + 1.568 + public synchronized final AuthenticationHandler getProxyAuthenticationHandler() { 1.569 + if (proxyAuthHandler == null) { 1.570 + proxyAuthHandler = createProxyAuthenticationHandler(); 1.571 + } 1.572 + return proxyAuthHandler; 1.573 + } 1.574 + 1.575 + 1.576 + public synchronized void setProxyAuthenticationHandler( 1.577 + final AuthenticationHandler proxyAuthHandler) { 1.578 + this.proxyAuthHandler = proxyAuthHandler; 1.579 + } 1.580 + 1.581 + 1.582 + public synchronized final CookieStore getCookieStore() { 1.583 + if (cookieStore == null) { 1.584 + cookieStore = createCookieStore(); 1.585 + } 1.586 + return cookieStore; 1.587 + } 1.588 + 1.589 + 1.590 + public synchronized void setCookieStore(final CookieStore cookieStore) { 1.591 + this.cookieStore = cookieStore; 1.592 + } 1.593 + 1.594 + 1.595 + public synchronized final CredentialsProvider getCredentialsProvider() { 1.596 + if (credsProvider == null) { 1.597 + credsProvider = createCredentialsProvider(); 1.598 + } 1.599 + return credsProvider; 1.600 + } 1.601 + 1.602 + 1.603 + public synchronized void setCredentialsProvider(final CredentialsProvider credsProvider) { 1.604 + this.credsProvider = credsProvider; 1.605 + } 1.606 + 1.607 + 1.608 + public synchronized final HttpRoutePlanner getRoutePlanner() { 1.609 + if (this.routePlanner == null) { 1.610 + this.routePlanner = createHttpRoutePlanner(); 1.611 + } 1.612 + return this.routePlanner; 1.613 + } 1.614 + 1.615 + 1.616 + public synchronized void setRoutePlanner(final HttpRoutePlanner routePlanner) { 1.617 + this.routePlanner = routePlanner; 1.618 + } 1.619 + 1.620 + 1.621 + public synchronized final UserTokenHandler getUserTokenHandler() { 1.622 + if (this.userTokenHandler == null) { 1.623 + this.userTokenHandler = createUserTokenHandler(); 1.624 + } 1.625 + return this.userTokenHandler; 1.626 + } 1.627 + 1.628 + 1.629 + public synchronized void setUserTokenHandler(final UserTokenHandler userTokenHandler) { 1.630 + this.userTokenHandler = userTokenHandler; 1.631 + } 1.632 + 1.633 + 1.634 + protected synchronized final BasicHttpProcessor getHttpProcessor() { 1.635 + if (mutableProcessor == null) { 1.636 + mutableProcessor = createHttpProcessor(); 1.637 + } 1.638 + return mutableProcessor; 1.639 + } 1.640 + 1.641 + 1.642 + private synchronized final HttpProcessor getProtocolProcessor() { 1.643 + if (protocolProcessor == null) { 1.644 + // Get mutable HTTP processor 1.645 + BasicHttpProcessor proc = getHttpProcessor(); 1.646 + // and create an immutable copy of it 1.647 + int reqc = proc.getRequestInterceptorCount(); 1.648 + HttpRequestInterceptor[] reqinterceptors = new HttpRequestInterceptor[reqc]; 1.649 + for (int i = 0; i < reqc; i++) { 1.650 + reqinterceptors[i] = proc.getRequestInterceptor(i); 1.651 + } 1.652 + int resc = proc.getResponseInterceptorCount(); 1.653 + HttpResponseInterceptor[] resinterceptors = new HttpResponseInterceptor[resc]; 1.654 + for (int i = 0; i < resc; i++) { 1.655 + resinterceptors[i] = proc.getResponseInterceptor(i); 1.656 + } 1.657 + protocolProcessor = new ImmutableHttpProcessor(reqinterceptors, resinterceptors); 1.658 + } 1.659 + return protocolProcessor; 1.660 + } 1.661 + 1.662 + 1.663 + public synchronized int getResponseInterceptorCount() { 1.664 + return getHttpProcessor().getResponseInterceptorCount(); 1.665 + } 1.666 + 1.667 + 1.668 + public synchronized HttpResponseInterceptor getResponseInterceptor(int index) { 1.669 + return getHttpProcessor().getResponseInterceptor(index); 1.670 + } 1.671 + 1.672 + 1.673 + public synchronized HttpRequestInterceptor getRequestInterceptor(int index) { 1.674 + return getHttpProcessor().getRequestInterceptor(index); 1.675 + } 1.676 + 1.677 + 1.678 + public synchronized int getRequestInterceptorCount() { 1.679 + return getHttpProcessor().getRequestInterceptorCount(); 1.680 + } 1.681 + 1.682 + 1.683 + public synchronized void addResponseInterceptor(final HttpResponseInterceptor itcp) { 1.684 + getHttpProcessor().addInterceptor(itcp); 1.685 + protocolProcessor = null; 1.686 + } 1.687 + 1.688 + 1.689 + public synchronized void addResponseInterceptor(final HttpResponseInterceptor itcp, int index) { 1.690 + getHttpProcessor().addInterceptor(itcp, index); 1.691 + protocolProcessor = null; 1.692 + } 1.693 + 1.694 + 1.695 + public synchronized void clearResponseInterceptors() { 1.696 + getHttpProcessor().clearResponseInterceptors(); 1.697 + protocolProcessor = null; 1.698 + } 1.699 + 1.700 + 1.701 + public synchronized void removeResponseInterceptorByClass(Class<? extends HttpResponseInterceptor> clazz) { 1.702 + getHttpProcessor().removeResponseInterceptorByClass(clazz); 1.703 + protocolProcessor = null; 1.704 + } 1.705 + 1.706 + 1.707 + public synchronized void addRequestInterceptor(final HttpRequestInterceptor itcp) { 1.708 + getHttpProcessor().addInterceptor(itcp); 1.709 + protocolProcessor = null; 1.710 + } 1.711 + 1.712 + 1.713 + public synchronized void addRequestInterceptor(final HttpRequestInterceptor itcp, int index) { 1.714 + getHttpProcessor().addInterceptor(itcp, index); 1.715 + protocolProcessor = null; 1.716 + } 1.717 + 1.718 + 1.719 + public synchronized void clearRequestInterceptors() { 1.720 + getHttpProcessor().clearRequestInterceptors(); 1.721 + protocolProcessor = null; 1.722 + } 1.723 + 1.724 + 1.725 + public synchronized void removeRequestInterceptorByClass(Class<? extends HttpRequestInterceptor> clazz) { 1.726 + getHttpProcessor().removeRequestInterceptorByClass(clazz); 1.727 + protocolProcessor = null; 1.728 + } 1.729 + 1.730 + public final HttpResponse execute(HttpUriRequest request) 1.731 + throws IOException, ClientProtocolException { 1.732 + 1.733 + return execute(request, (HttpContext) null); 1.734 + } 1.735 + 1.736 + 1.737 + /** 1.738 + * Maps to {@link HttpClient#execute(HttpHost,HttpRequest,HttpContext) 1.739 + * execute(target, request, context)}. 1.740 + * The target is determined from the URI of the request. 1.741 + * 1.742 + * @param request the request to execute 1.743 + * @param context the request-specific execution context, 1.744 + * or <code>null</code> to use a default context 1.745 + */ 1.746 + public final HttpResponse execute(HttpUriRequest request, 1.747 + HttpContext context) 1.748 + throws IOException, ClientProtocolException { 1.749 + 1.750 + if (request == null) { 1.751 + throw new IllegalArgumentException 1.752 + ("Request must not be null."); 1.753 + } 1.754 + 1.755 + return execute(determineTarget(request), request, context); 1.756 + } 1.757 + 1.758 + private static HttpHost determineTarget(HttpUriRequest request) throws ClientProtocolException { 1.759 + // A null target may be acceptable if there is a default target. 1.760 + // Otherwise, the null target is detected in the director. 1.761 + HttpHost target = null; 1.762 + 1.763 + URI requestURI = request.getURI(); 1.764 + if (requestURI.isAbsolute()) { 1.765 + target = URIUtils.extractHost(requestURI); 1.766 + if (target == null) { 1.767 + throw new ClientProtocolException( 1.768 + "URI does not specify a valid host name: " + requestURI); 1.769 + } 1.770 + } 1.771 + return target; 1.772 + } 1.773 + 1.774 + public final HttpResponse execute(HttpHost target, HttpRequest request) 1.775 + throws IOException, ClientProtocolException { 1.776 + 1.777 + return execute(target, request, (HttpContext) null); 1.778 + } 1.779 + 1.780 + public final HttpResponse execute(HttpHost target, HttpRequest request, 1.781 + HttpContext context) 1.782 + throws IOException, ClientProtocolException { 1.783 + 1.784 + if (request == null) { 1.785 + throw new IllegalArgumentException 1.786 + ("Request must not be null."); 1.787 + } 1.788 + // a null target may be acceptable, this depends on the route planner 1.789 + // a null context is acceptable, default context created below 1.790 + 1.791 + HttpContext execContext = null; 1.792 + RequestDirector director = null; 1.793 + 1.794 + // Initialize the request execution context making copies of 1.795 + // all shared objects that are potentially threading unsafe. 1.796 + synchronized (this) { 1.797 + 1.798 + HttpContext defaultContext = createHttpContext(); 1.799 + if (context == null) { 1.800 + execContext = defaultContext; 1.801 + } else { 1.802 + execContext = new DefaultedHttpContext(context, defaultContext); 1.803 + } 1.804 + // Create a director for this request 1.805 + director = createClientRequestDirector( 1.806 + getRequestExecutor(), 1.807 + getConnectionManager(), 1.808 + getConnectionReuseStrategy(), 1.809 + getConnectionKeepAliveStrategy(), 1.810 + getRoutePlanner(), 1.811 + getProtocolProcessor(), 1.812 + getHttpRequestRetryHandler(), 1.813 + getRedirectStrategy(), 1.814 + getTargetAuthenticationHandler(), 1.815 + getProxyAuthenticationHandler(), 1.816 + getUserTokenHandler(), 1.817 + determineParams(request)); 1.818 + } 1.819 + 1.820 + try { 1.821 + return director.execute(target, request, execContext); 1.822 + } catch(HttpException httpException) { 1.823 + throw new ClientProtocolException(httpException); 1.824 + } 1.825 + } 1.826 + 1.827 + @Deprecated 1.828 + protected RequestDirector createClientRequestDirector( 1.829 + final HttpRequestExecutor requestExec, 1.830 + final ClientConnectionManager conman, 1.831 + final ConnectionReuseStrategy reustrat, 1.832 + final ConnectionKeepAliveStrategy kastrat, 1.833 + final HttpRoutePlanner rouplan, 1.834 + final HttpProcessor httpProcessor, 1.835 + final HttpRequestRetryHandler retryHandler, 1.836 + final ch.boye.httpclientandroidlib.client.RedirectHandler redirectHandler, 1.837 + final AuthenticationHandler targetAuthHandler, 1.838 + final AuthenticationHandler proxyAuthHandler, 1.839 + final UserTokenHandler stateHandler, 1.840 + final HttpParams params) { 1.841 + return new DefaultRequestDirector( 1.842 + requestExec, 1.843 + conman, 1.844 + reustrat, 1.845 + kastrat, 1.846 + rouplan, 1.847 + httpProcessor, 1.848 + retryHandler, 1.849 + redirectHandler, 1.850 + targetAuthHandler, 1.851 + proxyAuthHandler, 1.852 + stateHandler, 1.853 + params); 1.854 + } 1.855 + 1.856 + /** 1.857 + * @since 4.1 1.858 + */ 1.859 + protected RequestDirector createClientRequestDirector( 1.860 + final HttpRequestExecutor requestExec, 1.861 + final ClientConnectionManager conman, 1.862 + final ConnectionReuseStrategy reustrat, 1.863 + final ConnectionKeepAliveStrategy kastrat, 1.864 + final HttpRoutePlanner rouplan, 1.865 + final HttpProcessor httpProcessor, 1.866 + final HttpRequestRetryHandler retryHandler, 1.867 + final RedirectStrategy redirectStrategy, 1.868 + final AuthenticationHandler targetAuthHandler, 1.869 + final AuthenticationHandler proxyAuthHandler, 1.870 + final UserTokenHandler stateHandler, 1.871 + final HttpParams params) { 1.872 + return new DefaultRequestDirector( 1.873 + log, 1.874 + requestExec, 1.875 + conman, 1.876 + reustrat, 1.877 + kastrat, 1.878 + rouplan, 1.879 + httpProcessor, 1.880 + retryHandler, 1.881 + redirectStrategy, 1.882 + targetAuthHandler, 1.883 + proxyAuthHandler, 1.884 + stateHandler, 1.885 + params); 1.886 + } 1.887 + /** 1.888 + * Obtains parameters for executing a request. 1.889 + * The default implementation in this class creates a new 1.890 + * {@link ClientParamsStack} from the request parameters 1.891 + * and the client parameters. 1.892 + * <br/> 1.893 + * This method is called by the default implementation of 1.894 + * {@link #execute(HttpHost,HttpRequest,HttpContext)} 1.895 + * to obtain the parameters for the 1.896 + * {@link DefaultRequestDirector}. 1.897 + * 1.898 + * @param req the request that will be executed 1.899 + * 1.900 + * @return the parameters to use 1.901 + */ 1.902 + protected HttpParams determineParams(HttpRequest req) { 1.903 + return new ClientParamsStack 1.904 + (null, getParams(), req.getParams(), null); 1.905 + } 1.906 + 1.907 + public <T> T execute( 1.908 + final HttpUriRequest request, 1.909 + final ResponseHandler<? extends T> responseHandler) 1.910 + throws IOException, ClientProtocolException { 1.911 + return execute(request, responseHandler, null); 1.912 + } 1.913 + 1.914 + public <T> T execute( 1.915 + final HttpUriRequest request, 1.916 + final ResponseHandler<? extends T> responseHandler, 1.917 + final HttpContext context) 1.918 + throws IOException, ClientProtocolException { 1.919 + HttpHost target = determineTarget(request); 1.920 + return execute(target, request, responseHandler, context); 1.921 + } 1.922 + 1.923 + public <T> T execute( 1.924 + final HttpHost target, 1.925 + final HttpRequest request, 1.926 + final ResponseHandler<? extends T> responseHandler) 1.927 + throws IOException, ClientProtocolException { 1.928 + return execute(target, request, responseHandler, null); 1.929 + } 1.930 + 1.931 + public <T> T execute( 1.932 + final HttpHost target, 1.933 + final HttpRequest request, 1.934 + final ResponseHandler<? extends T> responseHandler, 1.935 + final HttpContext context) 1.936 + throws IOException, ClientProtocolException { 1.937 + if (responseHandler == null) { 1.938 + throw new IllegalArgumentException 1.939 + ("Response handler must not be null."); 1.940 + } 1.941 + 1.942 + HttpResponse response = execute(target, request, context); 1.943 + 1.944 + T result; 1.945 + try { 1.946 + result = responseHandler.handleResponse(response); 1.947 + } catch (Throwable t) { 1.948 + HttpEntity entity = response.getEntity(); 1.949 + try { 1.950 + EntityUtils.consume(entity); 1.951 + } catch (Exception t2) { 1.952 + // Log this exception. The original exception is more 1.953 + // important and will be thrown to the caller. 1.954 + this.log.warn("Error consuming content after an exception.", t2); 1.955 + } 1.956 + 1.957 + if (t instanceof Error) { 1.958 + throw (Error) t; 1.959 + } 1.960 + 1.961 + if (t instanceof RuntimeException) { 1.962 + throw (RuntimeException) t; 1.963 + } 1.964 + 1.965 + if (t instanceof IOException) { 1.966 + throw (IOException) t; 1.967 + } 1.968 + 1.969 + throw new UndeclaredThrowableException(t); 1.970 + } 1.971 + 1.972 + // Handling the response was successful. Ensure that the content has 1.973 + // been fully consumed. 1.974 + HttpEntity entity = response.getEntity(); 1.975 + EntityUtils.consume(entity); 1.976 + return result; 1.977 + } 1.978 + 1.979 +}