michael@0: /* michael@0: * ==================================================================== michael@0: * Licensed to the Apache Software Foundation (ASF) under one michael@0: * or more contributor license agreements. See the NOTICE file michael@0: * distributed with this work for additional information michael@0: * regarding copyright ownership. The ASF licenses this file michael@0: * to you under the Apache License, Version 2.0 (the michael@0: * "License"); you may not use this file except in compliance michael@0: * with the License. You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, michael@0: * software distributed under the License is distributed on an michael@0: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY michael@0: * KIND, either express or implied. See the License for the michael@0: * specific language governing permissions and limitations michael@0: * under the License. michael@0: * ==================================================================== michael@0: * michael@0: * This software consists of voluntary contributions made by many michael@0: * individuals on behalf of the Apache Software Foundation. For more michael@0: * information on the Apache Software Foundation, please see michael@0: * . michael@0: * michael@0: */ michael@0: michael@0: package ch.boye.httpclientandroidlib.impl.client; michael@0: michael@0: import java.io.IOException; michael@0: import java.lang.reflect.UndeclaredThrowableException; michael@0: import java.net.URI; michael@0: michael@0: import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog; michael@0: /* LogFactory removed by HttpClient for Android script. */ michael@0: import ch.boye.httpclientandroidlib.ConnectionReuseStrategy; michael@0: import ch.boye.httpclientandroidlib.HttpEntity; michael@0: import ch.boye.httpclientandroidlib.HttpException; michael@0: import ch.boye.httpclientandroidlib.HttpHost; michael@0: import ch.boye.httpclientandroidlib.HttpRequest; michael@0: import ch.boye.httpclientandroidlib.HttpRequestInterceptor; michael@0: import ch.boye.httpclientandroidlib.HttpResponse; michael@0: import ch.boye.httpclientandroidlib.HttpResponseInterceptor; michael@0: import ch.boye.httpclientandroidlib.annotation.GuardedBy; michael@0: import ch.boye.httpclientandroidlib.annotation.ThreadSafe; michael@0: import ch.boye.httpclientandroidlib.auth.AuthSchemeRegistry; michael@0: import ch.boye.httpclientandroidlib.client.AuthenticationHandler; michael@0: import ch.boye.httpclientandroidlib.client.ClientProtocolException; michael@0: import ch.boye.httpclientandroidlib.client.CookieStore; michael@0: import ch.boye.httpclientandroidlib.client.CredentialsProvider; michael@0: import ch.boye.httpclientandroidlib.client.HttpClient; michael@0: import ch.boye.httpclientandroidlib.client.HttpRequestRetryHandler; michael@0: import ch.boye.httpclientandroidlib.client.RedirectHandler; michael@0: import ch.boye.httpclientandroidlib.client.RedirectStrategy; michael@0: import ch.boye.httpclientandroidlib.client.RequestDirector; michael@0: import ch.boye.httpclientandroidlib.client.ResponseHandler; michael@0: import ch.boye.httpclientandroidlib.client.UserTokenHandler; michael@0: import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest; michael@0: import ch.boye.httpclientandroidlib.client.params.AuthPolicy; michael@0: import ch.boye.httpclientandroidlib.client.params.ClientPNames; michael@0: import ch.boye.httpclientandroidlib.client.params.CookiePolicy; michael@0: import ch.boye.httpclientandroidlib.client.protocol.ClientContext; michael@0: import ch.boye.httpclientandroidlib.client.utils.URIUtils; michael@0: import ch.boye.httpclientandroidlib.conn.ClientConnectionManager; michael@0: import ch.boye.httpclientandroidlib.conn.ClientConnectionManagerFactory; michael@0: import ch.boye.httpclientandroidlib.conn.ConnectionKeepAliveStrategy; michael@0: import ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner; michael@0: import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry; michael@0: import ch.boye.httpclientandroidlib.cookie.CookieSpecRegistry; michael@0: import ch.boye.httpclientandroidlib.impl.DefaultConnectionReuseStrategy; michael@0: import ch.boye.httpclientandroidlib.impl.auth.BasicSchemeFactory; michael@0: import ch.boye.httpclientandroidlib.impl.auth.DigestSchemeFactory; michael@0: import ch.boye.httpclientandroidlib.impl.auth.NTLMSchemeFactory; michael@0: /* NegotiateSchemeFactory removed by HttpClient for Android script. */ michael@0: import ch.boye.httpclientandroidlib.impl.conn.DefaultHttpRoutePlanner; michael@0: import ch.boye.httpclientandroidlib.impl.conn.SchemeRegistryFactory; michael@0: import ch.boye.httpclientandroidlib.impl.conn.SingleClientConnManager; michael@0: import ch.boye.httpclientandroidlib.impl.cookie.BestMatchSpecFactory; michael@0: import ch.boye.httpclientandroidlib.impl.cookie.BrowserCompatSpecFactory; michael@0: import ch.boye.httpclientandroidlib.impl.cookie.IgnoreSpecFactory; michael@0: import ch.boye.httpclientandroidlib.impl.cookie.NetscapeDraftSpecFactory; michael@0: import ch.boye.httpclientandroidlib.impl.cookie.RFC2109SpecFactory; michael@0: import ch.boye.httpclientandroidlib.impl.cookie.RFC2965SpecFactory; michael@0: import ch.boye.httpclientandroidlib.params.HttpParams; michael@0: import ch.boye.httpclientandroidlib.protocol.BasicHttpContext; michael@0: import ch.boye.httpclientandroidlib.protocol.BasicHttpProcessor; michael@0: import ch.boye.httpclientandroidlib.protocol.DefaultedHttpContext; michael@0: import ch.boye.httpclientandroidlib.protocol.HttpContext; michael@0: import ch.boye.httpclientandroidlib.protocol.HttpProcessor; michael@0: import ch.boye.httpclientandroidlib.protocol.HttpRequestExecutor; michael@0: import ch.boye.httpclientandroidlib.protocol.ImmutableHttpProcessor; michael@0: import ch.boye.httpclientandroidlib.util.EntityUtils; michael@0: michael@0: /** michael@0: * Base class for {@link HttpClient} implementations. This class acts as michael@0: * a facade to a number of special purpose handler or strategy michael@0: * implementations responsible for handling of a particular aspect of michael@0: * the HTTP protocol such as redirect or authentication handling or michael@0: * making decision about connection persistence and keep alive duration. michael@0: * This enables the users to selectively replace default implementation michael@0: * of those aspects with custom, application specific ones. This class michael@0: * also provides factory methods to instantiate those objects: michael@0: * michael@0: *

michael@0: * This class also maintains a list of protocol interceptors intended michael@0: * for processing outgoing requests and incoming responses and provides michael@0: * methods for managing those interceptors. New protocol interceptors can be michael@0: * introduced to the protocol processor chain or removed from it if needed. michael@0: * Internally protocol interceptors are stored in a simple michael@0: * {@link java.util.ArrayList}. They are executed in the same natural order michael@0: * as they are added to the list. michael@0: *

michael@0: * AbstractHttpClient is thread safe. It is recommended that the same michael@0: * instance of this class is reused for multiple request executions. michael@0: * When an instance of DefaultHttpClient is no longer needed and is about michael@0: * to go out of scope the connection manager associated with it must be michael@0: * shut down by calling {@link ClientConnectionManager#shutdown()}! michael@0: * michael@0: * @since 4.0 michael@0: */ michael@0: @ThreadSafe michael@0: @SuppressWarnings("deprecation") michael@0: public abstract class AbstractHttpClient implements HttpClient { michael@0: michael@0: public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass()); michael@0: michael@0: /** The parameters. */ michael@0: @GuardedBy("this") michael@0: private HttpParams defaultParams; michael@0: michael@0: /** The request executor. */ michael@0: @GuardedBy("this") michael@0: private HttpRequestExecutor requestExec; michael@0: michael@0: /** The connection manager. */ michael@0: @GuardedBy("this") michael@0: private ClientConnectionManager connManager; michael@0: michael@0: /** The connection re-use strategy. */ michael@0: @GuardedBy("this") michael@0: private ConnectionReuseStrategy reuseStrategy; michael@0: michael@0: /** The connection keep-alive strategy. */ michael@0: @GuardedBy("this") michael@0: private ConnectionKeepAliveStrategy keepAliveStrategy; michael@0: michael@0: /** The cookie spec registry. */ michael@0: @GuardedBy("this") michael@0: private CookieSpecRegistry supportedCookieSpecs; michael@0: michael@0: /** The authentication scheme registry. */ michael@0: @GuardedBy("this") michael@0: private AuthSchemeRegistry supportedAuthSchemes; michael@0: michael@0: /** The HTTP protocol processor and its immutable copy. */ michael@0: @GuardedBy("this") michael@0: private BasicHttpProcessor mutableProcessor; michael@0: michael@0: @GuardedBy("this") michael@0: private ImmutableHttpProcessor protocolProcessor; michael@0: michael@0: /** The request retry handler. */ michael@0: @GuardedBy("this") michael@0: private HttpRequestRetryHandler retryHandler; michael@0: michael@0: /** The redirect handler. */ michael@0: @GuardedBy("this") michael@0: private RedirectStrategy redirectStrategy; michael@0: michael@0: /** The target authentication handler. */ michael@0: @GuardedBy("this") michael@0: private AuthenticationHandler targetAuthHandler; michael@0: michael@0: /** The proxy authentication handler. */ michael@0: @GuardedBy("this") michael@0: private AuthenticationHandler proxyAuthHandler; michael@0: michael@0: /** The cookie store. */ michael@0: @GuardedBy("this") michael@0: private CookieStore cookieStore; michael@0: michael@0: /** The credentials provider. */ michael@0: @GuardedBy("this") michael@0: private CredentialsProvider credsProvider; michael@0: michael@0: /** The route planner. */ michael@0: @GuardedBy("this") michael@0: private HttpRoutePlanner routePlanner; michael@0: michael@0: /** The user token handler. */ michael@0: @GuardedBy("this") michael@0: private UserTokenHandler userTokenHandler; michael@0: michael@0: michael@0: /** michael@0: * Creates a new HTTP client. michael@0: * michael@0: * @param conman the connection manager michael@0: * @param params the parameters michael@0: */ michael@0: protected AbstractHttpClient( michael@0: final ClientConnectionManager conman, michael@0: final HttpParams params) { michael@0: defaultParams = params; michael@0: connManager = conman; michael@0: } // constructor michael@0: michael@0: michael@0: protected abstract HttpParams createHttpParams(); michael@0: michael@0: michael@0: protected abstract BasicHttpProcessor createHttpProcessor(); michael@0: michael@0: michael@0: protected HttpContext createHttpContext() { michael@0: HttpContext context = new BasicHttpContext(); michael@0: context.setAttribute( michael@0: ClientContext.SCHEME_REGISTRY, michael@0: getConnectionManager().getSchemeRegistry()); michael@0: context.setAttribute( michael@0: ClientContext.AUTHSCHEME_REGISTRY, michael@0: getAuthSchemes()); michael@0: context.setAttribute( michael@0: ClientContext.COOKIESPEC_REGISTRY, michael@0: getCookieSpecs()); michael@0: context.setAttribute( michael@0: ClientContext.COOKIE_STORE, michael@0: getCookieStore()); michael@0: context.setAttribute( michael@0: ClientContext.CREDS_PROVIDER, michael@0: getCredentialsProvider()); michael@0: return context; michael@0: } michael@0: michael@0: michael@0: protected ClientConnectionManager createClientConnectionManager() { michael@0: SchemeRegistry registry = SchemeRegistryFactory.createDefault(); michael@0: michael@0: ClientConnectionManager connManager = null; michael@0: HttpParams params = getParams(); michael@0: michael@0: ClientConnectionManagerFactory factory = null; michael@0: michael@0: String className = (String) params.getParameter( michael@0: ClientPNames.CONNECTION_MANAGER_FACTORY_CLASS_NAME); michael@0: if (className != null) { michael@0: try { michael@0: Class clazz = Class.forName(className); michael@0: factory = (ClientConnectionManagerFactory) clazz.newInstance(); michael@0: } catch (ClassNotFoundException ex) { michael@0: throw new IllegalStateException("Invalid class name: " + className); michael@0: } catch (IllegalAccessException ex) { michael@0: throw new IllegalAccessError(ex.getMessage()); michael@0: } catch (InstantiationException ex) { michael@0: throw new InstantiationError(ex.getMessage()); michael@0: } michael@0: } michael@0: if (factory != null) { michael@0: connManager = factory.newInstance(params, registry); michael@0: } else { michael@0: connManager = new SingleClientConnManager(registry); michael@0: } michael@0: michael@0: return connManager; michael@0: } michael@0: michael@0: michael@0: protected AuthSchemeRegistry createAuthSchemeRegistry() { michael@0: AuthSchemeRegistry registry = new AuthSchemeRegistry(); michael@0: registry.register( michael@0: AuthPolicy.BASIC, michael@0: new BasicSchemeFactory()); michael@0: registry.register( michael@0: AuthPolicy.DIGEST, michael@0: new DigestSchemeFactory()); michael@0: registry.register( michael@0: AuthPolicy.NTLM, michael@0: new NTLMSchemeFactory()); michael@0: /* NegotiateSchemeFactory removed by HttpClient for Android script. */ michael@0: return registry; michael@0: } michael@0: michael@0: michael@0: protected CookieSpecRegistry createCookieSpecRegistry() { michael@0: CookieSpecRegistry registry = new CookieSpecRegistry(); michael@0: registry.register( michael@0: CookiePolicy.BEST_MATCH, michael@0: new BestMatchSpecFactory()); michael@0: registry.register( michael@0: CookiePolicy.BROWSER_COMPATIBILITY, michael@0: new BrowserCompatSpecFactory()); michael@0: registry.register( michael@0: CookiePolicy.NETSCAPE, michael@0: new NetscapeDraftSpecFactory()); michael@0: registry.register( michael@0: CookiePolicy.RFC_2109, michael@0: new RFC2109SpecFactory()); michael@0: registry.register( michael@0: CookiePolicy.RFC_2965, michael@0: new RFC2965SpecFactory()); michael@0: registry.register( michael@0: CookiePolicy.IGNORE_COOKIES, michael@0: new IgnoreSpecFactory()); michael@0: return registry; michael@0: } michael@0: michael@0: michael@0: protected HttpRequestExecutor createRequestExecutor() { michael@0: return new HttpRequestExecutor(); michael@0: } michael@0: michael@0: michael@0: protected ConnectionReuseStrategy createConnectionReuseStrategy() { michael@0: return new DefaultConnectionReuseStrategy(); michael@0: } michael@0: michael@0: michael@0: protected ConnectionKeepAliveStrategy createConnectionKeepAliveStrategy() { michael@0: return new DefaultConnectionKeepAliveStrategy(); michael@0: } michael@0: michael@0: michael@0: protected HttpRequestRetryHandler createHttpRequestRetryHandler() { michael@0: return new DefaultHttpRequestRetryHandler(); michael@0: } michael@0: michael@0: michael@0: @Deprecated michael@0: protected RedirectHandler createRedirectHandler() { michael@0: return new DefaultRedirectHandler(); michael@0: } michael@0: michael@0: michael@0: protected AuthenticationHandler createTargetAuthenticationHandler() { michael@0: return new DefaultTargetAuthenticationHandler(); michael@0: } michael@0: michael@0: michael@0: protected AuthenticationHandler createProxyAuthenticationHandler() { michael@0: return new DefaultProxyAuthenticationHandler(); michael@0: } michael@0: michael@0: michael@0: protected CookieStore createCookieStore() { michael@0: return new BasicCookieStore(); michael@0: } michael@0: michael@0: michael@0: protected CredentialsProvider createCredentialsProvider() { michael@0: return new BasicCredentialsProvider(); michael@0: } michael@0: michael@0: michael@0: protected HttpRoutePlanner createHttpRoutePlanner() { michael@0: return new DefaultHttpRoutePlanner(getConnectionManager().getSchemeRegistry()); michael@0: } michael@0: michael@0: michael@0: protected UserTokenHandler createUserTokenHandler() { michael@0: return new DefaultUserTokenHandler(); michael@0: } michael@0: michael@0: michael@0: // non-javadoc, see interface HttpClient michael@0: public synchronized final HttpParams getParams() { michael@0: if (defaultParams == null) { michael@0: defaultParams = createHttpParams(); michael@0: } michael@0: return defaultParams; michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Replaces the parameters. michael@0: * The implementation here does not update parameters of dependent objects. michael@0: * michael@0: * @param params the new default parameters michael@0: */ michael@0: public synchronized void setParams(HttpParams params) { michael@0: defaultParams = params; michael@0: } michael@0: michael@0: michael@0: public synchronized final ClientConnectionManager getConnectionManager() { michael@0: if (connManager == null) { michael@0: connManager = createClientConnectionManager(); michael@0: } michael@0: return connManager; michael@0: } michael@0: michael@0: michael@0: public synchronized final HttpRequestExecutor getRequestExecutor() { michael@0: if (requestExec == null) { michael@0: requestExec = createRequestExecutor(); michael@0: } michael@0: return requestExec; michael@0: } michael@0: michael@0: michael@0: public synchronized final AuthSchemeRegistry getAuthSchemes() { michael@0: if (supportedAuthSchemes == null) { michael@0: supportedAuthSchemes = createAuthSchemeRegistry(); michael@0: } michael@0: return supportedAuthSchemes; michael@0: } michael@0: michael@0: michael@0: public synchronized void setAuthSchemes(final AuthSchemeRegistry authSchemeRegistry) { michael@0: supportedAuthSchemes = authSchemeRegistry; michael@0: } michael@0: michael@0: michael@0: public synchronized final CookieSpecRegistry getCookieSpecs() { michael@0: if (supportedCookieSpecs == null) { michael@0: supportedCookieSpecs = createCookieSpecRegistry(); michael@0: } michael@0: return supportedCookieSpecs; michael@0: } michael@0: michael@0: michael@0: public synchronized void setCookieSpecs(final CookieSpecRegistry cookieSpecRegistry) { michael@0: supportedCookieSpecs = cookieSpecRegistry; michael@0: } michael@0: michael@0: michael@0: public synchronized final ConnectionReuseStrategy getConnectionReuseStrategy() { michael@0: if (reuseStrategy == null) { michael@0: reuseStrategy = createConnectionReuseStrategy(); michael@0: } michael@0: return reuseStrategy; michael@0: } michael@0: michael@0: michael@0: public synchronized void setReuseStrategy(final ConnectionReuseStrategy reuseStrategy) { michael@0: this.reuseStrategy = reuseStrategy; michael@0: } michael@0: michael@0: michael@0: public synchronized final ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy() { michael@0: if (keepAliveStrategy == null) { michael@0: keepAliveStrategy = createConnectionKeepAliveStrategy(); michael@0: } michael@0: return keepAliveStrategy; michael@0: } michael@0: michael@0: michael@0: public synchronized void setKeepAliveStrategy(final ConnectionKeepAliveStrategy keepAliveStrategy) { michael@0: this.keepAliveStrategy = keepAliveStrategy; michael@0: } michael@0: michael@0: michael@0: public synchronized final HttpRequestRetryHandler getHttpRequestRetryHandler() { michael@0: if (retryHandler == null) { michael@0: retryHandler = createHttpRequestRetryHandler(); michael@0: } michael@0: return retryHandler; michael@0: } michael@0: michael@0: michael@0: public synchronized void setHttpRequestRetryHandler(final HttpRequestRetryHandler retryHandler) { michael@0: this.retryHandler = retryHandler; michael@0: } michael@0: michael@0: michael@0: @Deprecated michael@0: public synchronized final RedirectHandler getRedirectHandler() { michael@0: return createRedirectHandler(); michael@0: } michael@0: michael@0: michael@0: @Deprecated michael@0: public synchronized void setRedirectHandler(final RedirectHandler redirectHandler) { michael@0: this.redirectStrategy = new DefaultRedirectStrategyAdaptor(redirectHandler); michael@0: } michael@0: michael@0: /** michael@0: * @since 4.1 michael@0: */ michael@0: public synchronized final RedirectStrategy getRedirectStrategy() { michael@0: if (redirectStrategy == null) { michael@0: redirectStrategy = new DefaultRedirectStrategy(); michael@0: } michael@0: return redirectStrategy; michael@0: } michael@0: michael@0: /** michael@0: * @since 4.1 michael@0: */ michael@0: public synchronized void setRedirectStrategy(final RedirectStrategy redirectStrategy) { michael@0: this.redirectStrategy = redirectStrategy; michael@0: } michael@0: michael@0: michael@0: public synchronized final AuthenticationHandler getTargetAuthenticationHandler() { michael@0: if (targetAuthHandler == null) { michael@0: targetAuthHandler = createTargetAuthenticationHandler(); michael@0: } michael@0: return targetAuthHandler; michael@0: } michael@0: michael@0: michael@0: public synchronized void setTargetAuthenticationHandler( michael@0: final AuthenticationHandler targetAuthHandler) { michael@0: this.targetAuthHandler = targetAuthHandler; michael@0: } michael@0: michael@0: michael@0: public synchronized final AuthenticationHandler getProxyAuthenticationHandler() { michael@0: if (proxyAuthHandler == null) { michael@0: proxyAuthHandler = createProxyAuthenticationHandler(); michael@0: } michael@0: return proxyAuthHandler; michael@0: } michael@0: michael@0: michael@0: public synchronized void setProxyAuthenticationHandler( michael@0: final AuthenticationHandler proxyAuthHandler) { michael@0: this.proxyAuthHandler = proxyAuthHandler; michael@0: } michael@0: michael@0: michael@0: public synchronized final CookieStore getCookieStore() { michael@0: if (cookieStore == null) { michael@0: cookieStore = createCookieStore(); michael@0: } michael@0: return cookieStore; michael@0: } michael@0: michael@0: michael@0: public synchronized void setCookieStore(final CookieStore cookieStore) { michael@0: this.cookieStore = cookieStore; michael@0: } michael@0: michael@0: michael@0: public synchronized final CredentialsProvider getCredentialsProvider() { michael@0: if (credsProvider == null) { michael@0: credsProvider = createCredentialsProvider(); michael@0: } michael@0: return credsProvider; michael@0: } michael@0: michael@0: michael@0: public synchronized void setCredentialsProvider(final CredentialsProvider credsProvider) { michael@0: this.credsProvider = credsProvider; michael@0: } michael@0: michael@0: michael@0: public synchronized final HttpRoutePlanner getRoutePlanner() { michael@0: if (this.routePlanner == null) { michael@0: this.routePlanner = createHttpRoutePlanner(); michael@0: } michael@0: return this.routePlanner; michael@0: } michael@0: michael@0: michael@0: public synchronized void setRoutePlanner(final HttpRoutePlanner routePlanner) { michael@0: this.routePlanner = routePlanner; michael@0: } michael@0: michael@0: michael@0: public synchronized final UserTokenHandler getUserTokenHandler() { michael@0: if (this.userTokenHandler == null) { michael@0: this.userTokenHandler = createUserTokenHandler(); michael@0: } michael@0: return this.userTokenHandler; michael@0: } michael@0: michael@0: michael@0: public synchronized void setUserTokenHandler(final UserTokenHandler userTokenHandler) { michael@0: this.userTokenHandler = userTokenHandler; michael@0: } michael@0: michael@0: michael@0: protected synchronized final BasicHttpProcessor getHttpProcessor() { michael@0: if (mutableProcessor == null) { michael@0: mutableProcessor = createHttpProcessor(); michael@0: } michael@0: return mutableProcessor; michael@0: } michael@0: michael@0: michael@0: private synchronized final HttpProcessor getProtocolProcessor() { michael@0: if (protocolProcessor == null) { michael@0: // Get mutable HTTP processor michael@0: BasicHttpProcessor proc = getHttpProcessor(); michael@0: // and create an immutable copy of it michael@0: int reqc = proc.getRequestInterceptorCount(); michael@0: HttpRequestInterceptor[] reqinterceptors = new HttpRequestInterceptor[reqc]; michael@0: for (int i = 0; i < reqc; i++) { michael@0: reqinterceptors[i] = proc.getRequestInterceptor(i); michael@0: } michael@0: int resc = proc.getResponseInterceptorCount(); michael@0: HttpResponseInterceptor[] resinterceptors = new HttpResponseInterceptor[resc]; michael@0: for (int i = 0; i < resc; i++) { michael@0: resinterceptors[i] = proc.getResponseInterceptor(i); michael@0: } michael@0: protocolProcessor = new ImmutableHttpProcessor(reqinterceptors, resinterceptors); michael@0: } michael@0: return protocolProcessor; michael@0: } michael@0: michael@0: michael@0: public synchronized int getResponseInterceptorCount() { michael@0: return getHttpProcessor().getResponseInterceptorCount(); michael@0: } michael@0: michael@0: michael@0: public synchronized HttpResponseInterceptor getResponseInterceptor(int index) { michael@0: return getHttpProcessor().getResponseInterceptor(index); michael@0: } michael@0: michael@0: michael@0: public synchronized HttpRequestInterceptor getRequestInterceptor(int index) { michael@0: return getHttpProcessor().getRequestInterceptor(index); michael@0: } michael@0: michael@0: michael@0: public synchronized int getRequestInterceptorCount() { michael@0: return getHttpProcessor().getRequestInterceptorCount(); michael@0: } michael@0: michael@0: michael@0: public synchronized void addResponseInterceptor(final HttpResponseInterceptor itcp) { michael@0: getHttpProcessor().addInterceptor(itcp); michael@0: protocolProcessor = null; michael@0: } michael@0: michael@0: michael@0: public synchronized void addResponseInterceptor(final HttpResponseInterceptor itcp, int index) { michael@0: getHttpProcessor().addInterceptor(itcp, index); michael@0: protocolProcessor = null; michael@0: } michael@0: michael@0: michael@0: public synchronized void clearResponseInterceptors() { michael@0: getHttpProcessor().clearResponseInterceptors(); michael@0: protocolProcessor = null; michael@0: } michael@0: michael@0: michael@0: public synchronized void removeResponseInterceptorByClass(Class clazz) { michael@0: getHttpProcessor().removeResponseInterceptorByClass(clazz); michael@0: protocolProcessor = null; michael@0: } michael@0: michael@0: michael@0: public synchronized void addRequestInterceptor(final HttpRequestInterceptor itcp) { michael@0: getHttpProcessor().addInterceptor(itcp); michael@0: protocolProcessor = null; michael@0: } michael@0: michael@0: michael@0: public synchronized void addRequestInterceptor(final HttpRequestInterceptor itcp, int index) { michael@0: getHttpProcessor().addInterceptor(itcp, index); michael@0: protocolProcessor = null; michael@0: } michael@0: michael@0: michael@0: public synchronized void clearRequestInterceptors() { michael@0: getHttpProcessor().clearRequestInterceptors(); michael@0: protocolProcessor = null; michael@0: } michael@0: michael@0: michael@0: public synchronized void removeRequestInterceptorByClass(Class clazz) { michael@0: getHttpProcessor().removeRequestInterceptorByClass(clazz); michael@0: protocolProcessor = null; michael@0: } michael@0: michael@0: public final HttpResponse execute(HttpUriRequest request) michael@0: throws IOException, ClientProtocolException { michael@0: michael@0: return execute(request, (HttpContext) null); michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Maps to {@link HttpClient#execute(HttpHost,HttpRequest,HttpContext) michael@0: * execute(target, request, context)}. michael@0: * The target is determined from the URI of the request. michael@0: * michael@0: * @param request the request to execute michael@0: * @param context the request-specific execution context, michael@0: * or null to use a default context michael@0: */ michael@0: public final HttpResponse execute(HttpUriRequest request, michael@0: HttpContext context) michael@0: throws IOException, ClientProtocolException { michael@0: michael@0: if (request == null) { michael@0: throw new IllegalArgumentException michael@0: ("Request must not be null."); michael@0: } michael@0: michael@0: return execute(determineTarget(request), request, context); michael@0: } michael@0: michael@0: private static HttpHost determineTarget(HttpUriRequest request) throws ClientProtocolException { michael@0: // A null target may be acceptable if there is a default target. michael@0: // Otherwise, the null target is detected in the director. michael@0: HttpHost target = null; michael@0: michael@0: URI requestURI = request.getURI(); michael@0: if (requestURI.isAbsolute()) { michael@0: target = URIUtils.extractHost(requestURI); michael@0: if (target == null) { michael@0: throw new ClientProtocolException( michael@0: "URI does not specify a valid host name: " + requestURI); michael@0: } michael@0: } michael@0: return target; michael@0: } michael@0: michael@0: public final HttpResponse execute(HttpHost target, HttpRequest request) michael@0: throws IOException, ClientProtocolException { michael@0: michael@0: return execute(target, request, (HttpContext) null); michael@0: } michael@0: michael@0: public final HttpResponse execute(HttpHost target, HttpRequest request, michael@0: HttpContext context) michael@0: throws IOException, ClientProtocolException { michael@0: michael@0: if (request == null) { michael@0: throw new IllegalArgumentException michael@0: ("Request must not be null."); michael@0: } michael@0: // a null target may be acceptable, this depends on the route planner michael@0: // a null context is acceptable, default context created below michael@0: michael@0: HttpContext execContext = null; michael@0: RequestDirector director = null; michael@0: michael@0: // Initialize the request execution context making copies of michael@0: // all shared objects that are potentially threading unsafe. michael@0: synchronized (this) { michael@0: michael@0: HttpContext defaultContext = createHttpContext(); michael@0: if (context == null) { michael@0: execContext = defaultContext; michael@0: } else { michael@0: execContext = new DefaultedHttpContext(context, defaultContext); michael@0: } michael@0: // Create a director for this request michael@0: director = createClientRequestDirector( michael@0: getRequestExecutor(), michael@0: getConnectionManager(), michael@0: getConnectionReuseStrategy(), michael@0: getConnectionKeepAliveStrategy(), michael@0: getRoutePlanner(), michael@0: getProtocolProcessor(), michael@0: getHttpRequestRetryHandler(), michael@0: getRedirectStrategy(), michael@0: getTargetAuthenticationHandler(), michael@0: getProxyAuthenticationHandler(), michael@0: getUserTokenHandler(), michael@0: determineParams(request)); michael@0: } michael@0: michael@0: try { michael@0: return director.execute(target, request, execContext); michael@0: } catch(HttpException httpException) { michael@0: throw new ClientProtocolException(httpException); michael@0: } michael@0: } michael@0: michael@0: @Deprecated michael@0: protected RequestDirector createClientRequestDirector( michael@0: final HttpRequestExecutor requestExec, michael@0: final ClientConnectionManager conman, michael@0: final ConnectionReuseStrategy reustrat, michael@0: final ConnectionKeepAliveStrategy kastrat, michael@0: final HttpRoutePlanner rouplan, michael@0: final HttpProcessor httpProcessor, michael@0: final HttpRequestRetryHandler retryHandler, michael@0: final ch.boye.httpclientandroidlib.client.RedirectHandler redirectHandler, michael@0: final AuthenticationHandler targetAuthHandler, michael@0: final AuthenticationHandler proxyAuthHandler, michael@0: final UserTokenHandler stateHandler, michael@0: final HttpParams params) { michael@0: return new DefaultRequestDirector( michael@0: requestExec, michael@0: conman, michael@0: reustrat, michael@0: kastrat, michael@0: rouplan, michael@0: httpProcessor, michael@0: retryHandler, michael@0: redirectHandler, michael@0: targetAuthHandler, michael@0: proxyAuthHandler, michael@0: stateHandler, michael@0: params); michael@0: } michael@0: michael@0: /** michael@0: * @since 4.1 michael@0: */ michael@0: protected RequestDirector createClientRequestDirector( michael@0: final HttpRequestExecutor requestExec, michael@0: final ClientConnectionManager conman, michael@0: final ConnectionReuseStrategy reustrat, michael@0: final ConnectionKeepAliveStrategy kastrat, michael@0: final HttpRoutePlanner rouplan, michael@0: final HttpProcessor httpProcessor, michael@0: final HttpRequestRetryHandler retryHandler, michael@0: final RedirectStrategy redirectStrategy, michael@0: final AuthenticationHandler targetAuthHandler, michael@0: final AuthenticationHandler proxyAuthHandler, michael@0: final UserTokenHandler stateHandler, michael@0: final HttpParams params) { michael@0: return new DefaultRequestDirector( michael@0: log, michael@0: requestExec, michael@0: conman, michael@0: reustrat, michael@0: kastrat, michael@0: rouplan, michael@0: httpProcessor, michael@0: retryHandler, michael@0: redirectStrategy, michael@0: targetAuthHandler, michael@0: proxyAuthHandler, michael@0: stateHandler, michael@0: params); michael@0: } michael@0: /** michael@0: * Obtains parameters for executing a request. michael@0: * The default implementation in this class creates a new michael@0: * {@link ClientParamsStack} from the request parameters michael@0: * and the client parameters. michael@0: *
michael@0: * This method is called by the default implementation of michael@0: * {@link #execute(HttpHost,HttpRequest,HttpContext)} michael@0: * to obtain the parameters for the michael@0: * {@link DefaultRequestDirector}. michael@0: * michael@0: * @param req the request that will be executed michael@0: * michael@0: * @return the parameters to use michael@0: */ michael@0: protected HttpParams determineParams(HttpRequest req) { michael@0: return new ClientParamsStack michael@0: (null, getParams(), req.getParams(), null); michael@0: } michael@0: michael@0: public T execute( michael@0: final HttpUriRequest request, michael@0: final ResponseHandler responseHandler) michael@0: throws IOException, ClientProtocolException { michael@0: return execute(request, responseHandler, null); michael@0: } michael@0: michael@0: public T execute( michael@0: final HttpUriRequest request, michael@0: final ResponseHandler responseHandler, michael@0: final HttpContext context) michael@0: throws IOException, ClientProtocolException { michael@0: HttpHost target = determineTarget(request); michael@0: return execute(target, request, responseHandler, context); michael@0: } michael@0: michael@0: public T execute( michael@0: final HttpHost target, michael@0: final HttpRequest request, michael@0: final ResponseHandler responseHandler) michael@0: throws IOException, ClientProtocolException { michael@0: return execute(target, request, responseHandler, null); michael@0: } michael@0: michael@0: public T execute( michael@0: final HttpHost target, michael@0: final HttpRequest request, michael@0: final ResponseHandler responseHandler, michael@0: final HttpContext context) michael@0: throws IOException, ClientProtocolException { michael@0: if (responseHandler == null) { michael@0: throw new IllegalArgumentException michael@0: ("Response handler must not be null."); michael@0: } michael@0: michael@0: HttpResponse response = execute(target, request, context); michael@0: michael@0: T result; michael@0: try { michael@0: result = responseHandler.handleResponse(response); michael@0: } catch (Throwable t) { michael@0: HttpEntity entity = response.getEntity(); michael@0: try { michael@0: EntityUtils.consume(entity); michael@0: } catch (Exception t2) { michael@0: // Log this exception. The original exception is more michael@0: // important and will be thrown to the caller. michael@0: this.log.warn("Error consuming content after an exception.", t2); michael@0: } michael@0: michael@0: if (t instanceof Error) { michael@0: throw (Error) t; michael@0: } michael@0: michael@0: if (t instanceof RuntimeException) { michael@0: throw (RuntimeException) t; michael@0: } michael@0: michael@0: if (t instanceof IOException) { michael@0: throw (IOException) t; michael@0: } michael@0: michael@0: throw new UndeclaredThrowableException(t); michael@0: } michael@0: michael@0: // Handling the response was successful. Ensure that the content has michael@0: // been fully consumed. michael@0: HttpEntity entity = response.getEntity(); michael@0: EntityUtils.consume(entity); michael@0: return result; michael@0: } michael@0: michael@0: }