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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial