Wed, 31 Dec 2014 07:22:50 +0100
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 | } |