Changelog:

* Removed static instances from SchemeRegistry, CookieSpecRegistry and AuthSchemeRegistry
* Made sure there is only one instance of SchemeRegistry per HttpClient / ClientConnectionManager
* HostConfiguration, HttpRoute and RouteTracker no longer implement Cloneable as they do not override #clone() method
* AbstractHttpClient should now be threading safe
* DefaultHttpClient populates HTTP execution context with data required for request execution

git-svn-id: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpclient/trunk@534769 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2007-05-03 09:51:22 +00:00
parent 9fb978483a
commit 7cda278cd5
19 changed files with 404 additions and 251 deletions

View File

@ -50,12 +50,6 @@ import org.apache.http.message.BasicHttpRequest;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
import org.apache.http.protocol.RequestTargetHost;
import org.apache.http.protocol.RequestUserAgent;
import org.apache.http.util.EntityUtils;
@ -139,16 +133,7 @@ public class ClientExecuteDirect {
// new SingleClientConnManager(getParams(), supportedSchemes);
DefaultHttpClient dhc =
new DefaultHttpClient(getParams(), ccm, supportedSchemes);
BasicHttpProcessor bhp = dhc.getProcessor();
// Required protocol interceptors
bhp.addInterceptor(new RequestContent());
bhp.addInterceptor(new RequestTargetHost());
// Recommended protocol interceptors
bhp.addInterceptor(new RequestConnControl());
bhp.addInterceptor(new RequestUserAgent());
bhp.addInterceptor(new RequestExpectContinue());
new DefaultHttpClient(ccm, getParams());
return dhc;
}

View File

@ -53,12 +53,6 @@ import org.apache.http.message.BasicHttpRequest;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
import org.apache.http.protocol.RequestTargetHost;
import org.apache.http.protocol.RequestUserAgent;
import org.apache.http.util.EntityUtils;
@ -151,16 +145,7 @@ public class ClientExecuteProxy {
// new SingleClientConnManager(getParams(), supportedSchemes);
DefaultHttpClient dhc =
new DefaultHttpClient(getParams(), ccm, supportedSchemes);
BasicHttpProcessor bhp = dhc.getProcessor();
// Required protocol interceptors
bhp.addInterceptor(new RequestContent());
bhp.addInterceptor(new RequestTargetHost());
// Recommended protocol interceptors
bhp.addInterceptor(new RequestConnControl());
bhp.addInterceptor(new RequestUserAgent());
bhp.addInterceptor(new RequestExpectContinue());
new DefaultHttpClient(ccm, getParams());
return dhc;
}

View File

@ -35,20 +35,15 @@ import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.PlainSocketFactory;
import org.apache.http.conn.Scheme;
import org.apache.http.conn.SchemeRegistry;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.SingleClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
import org.apache.http.protocol.RequestTargetHost;
import org.apache.http.protocol.RequestUserAgent;
/**
* How to abort an HTTP method before its normal completion.
@ -74,19 +69,7 @@ public class MethodAbort {
HttpProtocolParams.setContentCharset(params, "UTF-8");
HttpProtocolParams.setUserAgent(params, "Jakarta-HttpClient/4.0");
DefaultHttpClient httpclient = new DefaultHttpClient(
params,
new SingleClientConnManager(params, supportedSchemes),
supportedSchemes);
// Required protocol interceptors
httpclient.getProcessor().addInterceptor(new RequestContent());
httpclient.getProcessor().addInterceptor(new RequestTargetHost());
// Recommended protocol interceptors
httpclient.getProcessor().addInterceptor(new RequestConnControl());
httpclient.getProcessor().addInterceptor(new RequestUserAgent());
httpclient.getProcessor().addInterceptor(new RequestExpectContinue());
HttpClient httpclient = new DefaultHttpClient(params);
HttpHost target = new HttpHost("www.apache.org", 80, "http");

View File

@ -48,8 +48,6 @@ import org.apache.http.params.HttpParams;
*/
public final class AuthSchemeRegistry {
public final static AuthSchemeRegistry DEFAULT = new AuthSchemeRegistry();
private final Map registeredSchemes = new LinkedHashMap();
/**

View File

@ -0,0 +1,48 @@
/*
* $HeadURL$
* $Revision$
* $Date$
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.client.protocol;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpExecutionContext;
public class HttpClientContext extends HttpExecutionContext {
public static final String SCHEME_REGISTRY = "http.scheme-registry";
public static final String COOKIESPEC_REGISTRY = "http.cookiespec-registry";
public static final String AUTHSCHEME_REGISTRY = "http.authscheme-registry";
public static final String HTTP_STATE = "http.state";
public HttpClientContext(final HttpContext parentContext) {
super(parentContext);
}
}

View File

@ -49,6 +49,8 @@ package org.apache.http.conn;
*/
public interface ClientConnectionManager {
SchemeRegistry getSchemeRegistry();
/**
* Obtains a connection.
* This method will block until a connection becomes available

View File

@ -54,7 +54,7 @@ import org.apache.http.util.LangUtils;
*
* @since 4.0
*/
public class HostConfiguration implements Cloneable {
public class HostConfiguration {
/**
* Constant representing a configuration for <i>any</i> host.

View File

@ -50,7 +50,7 @@ import org.apache.http.util.CharArrayBuffer;
*
* @since 4.0
*/
public final class HttpRoute implements Cloneable {
public final class HttpRoute {
/** The target host to connect to. */
private final HttpHost targetHost;

View File

@ -48,7 +48,7 @@ import org.apache.http.util.CharArrayBuffer;
*
* @since 4.0
*/
public final class RouteTracker implements Cloneable {
public final class RouteTracker {
/** The target host to connect to. */
private final HttpHost targetHost;

View File

@ -52,17 +52,6 @@ import org.apache.http.HttpHost;
*/
public final class SchemeRegistry {
/**
* A default scheme registry.
* It is empty by default, but can be initialized by any application.
* The default scheme registry should only be used by applications that
* know for sure that this class is NOT shared with any other application.
* For example a Servlet, Portlet or EJB should not rely on being the
* only user of this class.
*/
public final static SchemeRegistry DEFAULT = new SchemeRegistry();
/** The available schemes in this registry. */
private final Map registeredSchemes;

View File

@ -51,8 +51,6 @@ import org.apache.http.params.HttpParams;
*/
public final class CookieSpecRegistry {
public final static CookieSpecRegistry DEFAULT = new CookieSpecRegistry();
private final Map registeredSpecs;
public CookieSpecRegistry() {

View File

@ -32,21 +32,29 @@
package org.apache.http.impl.client;
import java.io.IOException;
import java.util.List;
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpException;
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.SyncHttpExecutionContext;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.conn.SchemeRegistry;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.auth.AuthSchemeRegistry;
import org.apache.http.client.ClientRequestDirector;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpState;
import org.apache.http.client.RoutedRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.cookie.CookieSpecRegistry;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpExecutionContext;
import org.apache.http.protocol.HttpRequestExecutor;
import org.apache.http.protocol.HttpRequestInterceptorList;
import org.apache.http.protocol.HttpResponseInterceptorList;
@ -62,84 +70,79 @@ import org.apache.http.client.RoutedRequest;
* @since 4.0
*/
public abstract class AbstractHttpClient
implements HttpClient {
implements HttpClient, HttpRequestInterceptorList, HttpResponseInterceptorList {
/** The default context. */
protected HttpContext defaultContext;
private HttpContext defaultContext;
/** The parameters. */
protected HttpParams defaultParams;
private HttpParams defaultParams;
/** The connection manager. */
protected ClientConnectionManager connManager;
private ClientConnectionManager connManager;
/** The connection re-use strategy. */
protected ConnectionReuseStrategy reuseStrategy;
private ConnectionReuseStrategy reuseStrategy;
/** The HTTP processor, if defined. */
protected BasicHttpProcessor httpProcessor;
/** The cookie spec registry. */
private CookieSpecRegistry supportedCookieSpecs;
/** The scheme registry. */
protected SchemeRegistry supportedSchemes;
/** The authentication scheme registry. */
private AuthSchemeRegistry supportedAuthSchemes;
/** The HTTP processor. */
private BasicHttpProcessor httpProcessor;
/** The default HTTP state. */
private HttpState defaultState;
/**
* Creates a new HTTP client.
*
* @param context the context, or <code>null</code> to use an instance of
* {@link SyncHttpExecutionContext SyncHttpExecutionContext}
* @param params the parameters
* @param conman the connection manager
* @param schemes the scheme registry, or
* <code>null</code> to use the
* {@link SchemeRegistry#DEFAULT default}
* @param params the parameters
*/
protected AbstractHttpClient(HttpContext context, HttpParams params,
ClientConnectionManager conman,
SchemeRegistry schemes) {
if (params == null)
throw new IllegalArgumentException
("Parameters must not be null.");
if (conman == null)
throw new IllegalArgumentException
("Connection manager must not be null.");
defaultContext = (context != null) ?
context : new SyncHttpExecutionContext(null);
defaultParams = params;
connManager = conman;
supportedSchemes = (schemes != null) ?
schemes : SchemeRegistry.DEFAULT;
// to be initialized by derived class constructors, if needed:
reuseStrategy = null;
httpProcessor = null;
protected AbstractHttpClient(
final ClientConnectionManager conman,
final HttpParams params) {
defaultParams = params;
connManager = conman;
} // constructor
// non-javadoc, see interface HttpClient
public final HttpContext getContext() {
return defaultContext;
}
protected abstract HttpParams createHttpParams();
/**
* Replaces the default context.
*
* @param context the new default context
*/
public void setContext(HttpContext context) {
if (context == null)
throw new IllegalArgumentException
("Context must not be null.");
defaultContext = context;
}
protected abstract HttpContext createHttpContext();
protected abstract ClientConnectionManager createClientConnectionManager();
protected abstract AuthSchemeRegistry createAuthSchemeRegistry();
protected abstract CookieSpecRegistry createCookieSpecRegistry();
protected abstract ConnectionReuseStrategy createConnectionReuseStrategy();
protected abstract BasicHttpProcessor createHttpProcessor();
protected abstract HttpState createHttpState();
protected abstract void populateContext(HttpContext context);
// non-javadoc, see interface HttpClient
public final HttpParams getParams() {
public synchronized final HttpParams getParams() {
if (defaultParams == null) {
defaultParams = createHttpParams();
}
return defaultParams;
}
@ -150,16 +153,16 @@ public abstract class AbstractHttpClient
*
* @param params the new default parameters
*/
public void setParams(HttpParams params) {
if (params == null)
throw new IllegalArgumentException
("Parameters must not be null.");
public synchronized void setParams(HttpParams params) {
defaultParams = params;
}
// non-javadoc, see interface HttpClient
public final ClientConnectionManager getConnectionManager() {
public synchronized final ClientConnectionManager getConnectionManager() {
if (connManager == null) {
connManager = createClientConnectionManager();
}
return connManager;
}
@ -168,23 +171,116 @@ public abstract class AbstractHttpClient
// derived classes may offer that method at their own risk
/**
* Obtains the HTTP processor.
*
* @return the HTTP processor, or <code>null</code> if not set
*/
public BasicHttpProcessor getProcessor() {
public synchronized final AuthSchemeRegistry getAuthSchemes() {
if (supportedAuthSchemes == null) {
supportedAuthSchemes = createAuthSchemeRegistry();
}
return supportedAuthSchemes;
}
public synchronized void setAuthSchemes(final AuthSchemeRegistry authSchemeRegistry) {
supportedAuthSchemes = authSchemeRegistry;
}
public synchronized final CookieSpecRegistry getCookieSpecs() {
if (supportedCookieSpecs == null) {
supportedCookieSpecs = createCookieSpecRegistry();
}
return supportedCookieSpecs;
}
public synchronized void setCookieSpecs(final CookieSpecRegistry cookieSpecRegistry) {
supportedCookieSpecs = cookieSpecRegistry;
}
public synchronized final ConnectionReuseStrategy getConnectionReuseStrategy() {
if (reuseStrategy == null) {
reuseStrategy = createConnectionReuseStrategy();
}
return reuseStrategy;
}
public synchronized void setReuseStrategy(final ConnectionReuseStrategy reuseStrategy) {
this.reuseStrategy = reuseStrategy;
}
public synchronized final HttpState getState() {
if (defaultState == null) {
defaultState = createHttpState();
}
return defaultState;
}
public synchronized void setState(final HttpState state) {
defaultState = state;
}
protected synchronized final BasicHttpProcessor getHttpProcessor() {
if (httpProcessor == null) {
httpProcessor = createHttpProcessor();
}
return httpProcessor;
}
/**
* Specifies the HTTP processor.
*
* @param hproc the HTTP processor, or <code>null</code> to unset
*/
public void setProcessor(BasicHttpProcessor hproc) {
httpProcessor = hproc;
public synchronized final HttpContext getContext() {
if (defaultContext == null) {
defaultContext = createHttpContext();
}
return defaultContext;
}
public synchronized void addResponseInterceptor(final HttpResponseInterceptor itcp) {
getHttpProcessor().addInterceptor(itcp);
}
public synchronized void clearResponseInterceptors() {
getHttpProcessor().clearResponseInterceptors();
}
public synchronized HttpResponseInterceptor getResponseInterceptor(int index) {
return getHttpProcessor().getResponseInterceptor(index);
}
public synchronized int getResponseInterceptorCount() {
return getHttpProcessor().getResponseInterceptorCount();
}
public synchronized void addRequestInterceptor(final HttpRequestInterceptor itcp) {
getHttpProcessor().addInterceptor(itcp);
}
public synchronized void clearRequestInterceptors() {
getHttpProcessor().clearRequestInterceptors();
}
public synchronized HttpRequestInterceptor getRequestInterceptor(int index) {
return getHttpProcessor().getRequestInterceptor(index);
}
public synchronized int getRequestInterceptorCount() {
return getHttpProcessor().getRequestInterceptorCount();
}
public synchronized void setInterceptors(final List itcps) {
getHttpProcessor().setInterceptors(itcps);
}
@ -204,7 +300,7 @@ public abstract class AbstractHttpClient
public final HttpResponse execute(HttpHost target, HttpRequest request)
throws HttpException, IOException {
return execute(target, request, defaultContext);
return execute(target, request, null);
}
@ -229,12 +325,63 @@ public abstract class AbstractHttpClient
// Otherwise, the null target is detected in determineRoute().
if (context == null)
context = defaultContext;
context = new HttpExecutionContext(getContext());
RoutedRequest roureq = determineRoute(target, request, context);
return execute(roureq, context);
}
// non-javadoc, see interface HttpClient
public final HttpResponse execute(RoutedRequest roureq, HttpContext context)
throws HttpException, IOException {
if (roureq == null) {
throw new IllegalArgumentException
("Routed request must not be null.");
}
if (roureq.getRequest() == null) {
throw new IllegalArgumentException
("Request must not be null.");
}
if (roureq.getRoute() == null) {
throw new IllegalArgumentException
("Route must not be null.");
}
if (context == null)
context = new HttpExecutionContext(getContext());
ClientRequestDirector director = null;
// Initialize the request execution context making copies of
// all shared objects that are potentially threading unsafe.
synchronized (this) {
// Populate the context for this request
populateContext(context);
// Create a copy of the HTTP processor
BasicHttpProcessor httpproc = getHttpProcessor().copy();
// Create an HTTP request executor for this request
HttpRequestExecutor reqexec = new HttpRequestExecutor(httpproc);
reqexec.setParams(getParams());
// Create a director for this request
director = new DefaultClientRequestDirector(
getConnectionManager(),
getConnectionReuseStrategy(),
reqexec);
}
HttpResponse response = director.execute(roureq, context);
// If the response depends on the connection, the director
// will have set up an auto-release input stream.
//@@@ or move that logic here into the client?
//@@@ "finalize" response, to allow for buffering of entities?
//@@@ here or in director?
return response;
} // execute
/**
* Determines the route for a request.

View File

@ -48,7 +48,6 @@ import org.apache.http.conn.HttpRoute;
import org.apache.http.conn.ManagedClientConnection;
import org.apache.http.conn.RouteDirector;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpExecutionContext;
import org.apache.http.protocol.HttpRequestExecutor;
@ -80,22 +79,17 @@ public class DefaultClientRequestDirector
/** The request executor. */
protected final HttpRequestExecutor requestExec;
/** The parameters. */
protected final HttpParams defaultParams;
/** The currently allocated connection. */
protected ManagedClientConnection managedConn;
public DefaultClientRequestDirector(ClientConnectionManager conman,
ConnectionReuseStrategy reustrat,
HttpRequestExecutor reqexec,
HttpParams params) {
HttpRequestExecutor reqexec) {
this.connManager = conman;
this.reuseStrategy = reustrat;
this.requestExec = reqexec;
this.defaultParams = params;
this.managedConn = null;
@ -224,16 +218,16 @@ public class DefaultClientRequestDirector
case RouteDirector.CONNECT_TARGET:
case RouteDirector.CONNECT_PROXY:
managedConn.open(route, context, defaultParams);
managedConn.open(route, context, requestExec.getParams());
break;
case RouteDirector.CREATE_TUNNEL:
boolean secure = createTunnel(route, context);
managedConn.tunnelCreated(secure, defaultParams);
managedConn.tunnelCreated(secure, requestExec.getParams());
break;
case RouteDirector.LAYER_PROTOCOL:
managedConn.layerProtocol(context, defaultParams);
managedConn.layerProtocol(context, requestExec.getParams());
break;
case RouteDirector.UNREACHABLE:

View File

@ -31,24 +31,33 @@
package org.apache.http.impl.client;
import java.io.IOException;
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientRequestDirector;
import org.apache.http.auth.AuthSchemeRegistry;
import org.apache.http.client.HttpState;
import org.apache.http.client.RoutedRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.HttpRoute;
import org.apache.http.conn.PlainSocketFactory;
import org.apache.http.conn.Scheme;
import org.apache.http.conn.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.cookie.CookieSpecRegistry;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.conn.SingleClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestExecutor;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
import org.apache.http.protocol.RequestTargetHost;
import org.apache.http.protocol.RequestUserAgent;
import org.apache.http.protocol.SyncHttpExecutionContext;
@ -77,79 +86,88 @@ public class DefaultHttpClient extends AbstractHttpClient {
* <code>null</code> to use the
* {@link SchemeRegistry#DEFAULT default}
*/
public DefaultHttpClient(HttpParams params,
ClientConnectionManager conman,
SchemeRegistry schemes) {
super(null, params, conman, schemes);
httpProcessor = createProcessor();
reuseStrategy = createReuseStrategy();
public DefaultHttpClient(
final ClientConnectionManager conman,
final HttpParams params) {
super(conman, params);
}
/**
* Creates and initializes an HTTP processor.
* This method is typically called by the constructor,
* after the base class has been initialized.
*
* @return a new, initialized HTTP processor
*/
protected BasicHttpProcessor createProcessor() {
BasicHttpProcessor bhp = new BasicHttpProcessor();
//@@@ evaluate defaultParams to initialize interceptors
return bhp;
public DefaultHttpClient(final HttpParams params) {
super(null, params);
}
/**
* Creates a connection reuse strategy.
* This method is typically called by the constructor,
* after the base class has been initialized.
*/
protected ConnectionReuseStrategy createReuseStrategy() {
//@@@ evaluate defaultParams to determine implementation
ConnectionReuseStrategy rus = new DefaultConnectionReuseStrategy();
return rus;
protected HttpParams createHttpParams() {
return new BasicHttpParams();
}
// non-javadoc, see interface HttpClient
public HttpResponse execute(RoutedRequest roureq, HttpContext context)
throws HttpException, IOException {
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(
new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(
new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
if (roureq == null) {
throw new IllegalArgumentException
("Routed request must not be null.");
}
if (roureq.getRequest() == null) {
throw new IllegalArgumentException
("Request must not be null.");
}
if (roureq.getRoute() == null) {
throw new IllegalArgumentException
("Route must not be null.");
}
return new SingleClientConnManager(getParams(), registry);
}
if (context == null)
context = defaultContext;
ClientRequestDirector director = createDirector(context);
HttpResponse response = director.execute(roureq, context);
// If the response depends on the connection, the director
// will have set up an auto-release input stream.
//@@@ or move that logic here into the client?
protected HttpContext createHttpContext() {
return new SyncHttpExecutionContext(null);
}
//@@@ "finalize" response, to allow for buffering of entities?
//@@@ here or in director?
return response;
protected ConnectionReuseStrategy createConnectionReuseStrategy() {
return new DefaultConnectionReuseStrategy();
}
} // execute
protected AuthSchemeRegistry createAuthSchemeRegistry() {
AuthSchemeRegistry registry = new AuthSchemeRegistry();
return registry;
}
protected CookieSpecRegistry createCookieSpecRegistry() {
CookieSpecRegistry registry = new CookieSpecRegistry();
return registry;
}
protected BasicHttpProcessor createHttpProcessor() {
BasicHttpProcessor httpproc = new BasicHttpProcessor();
// Required protocol interceptors
httpproc.addInterceptor(new RequestContent());
httpproc.addInterceptor(new RequestTargetHost());
// Recommended protocol interceptors
httpproc.addInterceptor(new RequestConnControl());
httpproc.addInterceptor(new RequestUserAgent());
httpproc.addInterceptor(new RequestExpectContinue());
return httpproc;
}
protected HttpState createHttpState() {
return new HttpState();
}
protected void populateContext(final HttpContext context) {
context.setAttribute(
HttpClientContext.SCHEME_REGISTRY,
getConnectionManager().getSchemeRegistry());
context.setAttribute(
HttpClientContext.AUTHSCHEME_REGISTRY,
getAuthSchemes());
context.setAttribute(
HttpClientContext.COOKIESPEC_REGISTRY,
getCookieSpecs());
context.setAttribute(
HttpClientContext.HTTP_STATE,
getState());
}
// non-javadoc, see base class AbstractHttpClient
@ -165,7 +183,8 @@ public class DefaultHttpClient extends AbstractHttpClient {
("Target host must not be null.");
}
Scheme schm = supportedSchemes.getScheme(target.getSchemeName());
SchemeRegistry schemeRegistry = getConnectionManager().getSchemeRegistry();
Scheme schm = schemeRegistry.getScheme(target.getSchemeName());
// as it is typically used for TLS/SSL, we assume that
// a layered scheme implies a secure connection
HttpRoute route = new HttpRoute(target, null, schm.isLayered());
@ -174,23 +193,4 @@ public class DefaultHttpClient extends AbstractHttpClient {
}
/**
* Creates a new director for a request execution.
*
* @param context the context to use for the execution,
* never <code>null</code>
*
* @return the new director for executing a method in the given context
*/
protected ClientRequestDirector createDirector(HttpContext context) {
//@@@ can we use a single reqexec without sacrificing thread safety?
//@@@ it seems wasteful to throw away both director and reqexec
HttpRequestExecutor reqexec = new HttpRequestExecutor(httpProcessor);
reqexec.setParams(defaultParams);
return new DefaultClientRequestDirector
(connManager, reuseStrategy, reqexec, defaultParams);
}
} // class DefaultHttpClient

View File

@ -86,7 +86,11 @@ public class DefaultClientConnectionOperator
* {@link SchemeRegistry#DEFAULT SchemeRegistry.DEFAULT}
*/
public DefaultClientConnectionOperator(SchemeRegistry schemes) {
schemeRegistry = (schemes != null) ? schemes : SchemeRegistry.DEFAULT;
if (schemes == null) {
throw new IllegalArgumentException
("Scheme registry must not be null.");
}
schemeRegistry = schemes;
}

View File

@ -78,6 +78,9 @@ public class SingleClientConnManager implements ClientConnectionManager {
"Make sure to release the connection before allocating another one.";
/** The schemes supported by this connection manager. */
protected SchemeRegistry schemeRegistry;
/** The parameters of this connection manager. */
protected HttpParams params = new BasicHttpParams();
@ -115,7 +118,11 @@ public class SingleClientConnManager implements ClientConnectionManager {
if (params == null) {
throw new IllegalArgumentException("Parameters must not be null.");
}
if (schreg == null) {
throw new IllegalArgumentException("Scheme registry must not be null.");
}
this.params = params;
this.schemeRegistry = schreg;
this.connOperator = createConnectionOperator(schreg);
this.uniquePoolEntry = new PoolEntry(connOperator.createConnection());
this.managedConn = null;
@ -126,6 +133,11 @@ public class SingleClientConnManager implements ClientConnectionManager {
} // <constructor>
public SchemeRegistry getSchemeRegistry() {
return this.schemeRegistry;
}
/**
* Hook for creating the connection operator.
* It is called by the constructor.

View File

@ -104,6 +104,9 @@ public class ThreadSafeClientConnManager
private static WeakHashMap ALL_CONNECTION_MANAGERS = new WeakHashMap();
/** The schemes supported by this connection manager. */
protected SchemeRegistry schemeRegistry;
/** The parameters of this connection manager. */
private HttpParams params = new BasicHttpParams();
@ -133,6 +136,7 @@ public class ThreadSafeClientConnManager
throw new IllegalArgumentException("Parameters must not be null.");
}
this.params = params;
this.schemeRegistry = schreg;
this.connectionPool = new ConnectionPool();
this.connOperator = createConnectionOperator(schreg);
this.isShutDown = false;
@ -143,6 +147,10 @@ public class ThreadSafeClientConnManager
} // <constructor>
public SchemeRegistry getSchemeRegistry() {
return this.schemeRegistry;
}
// non-javadoc, see interface ClientConnectionManager
public ManagedClientConnection getConnection(HttpRoute route) {

View File

@ -63,7 +63,7 @@ public class TestCookiePolicy extends TestCase {
}
public void testRegisterUnregisterCookieSpecFactory() {
CookieSpecRegistry registry = CookieSpecRegistry.DEFAULT;
CookieSpecRegistry registry = new CookieSpecRegistry();
List names = registry.getSpecNames();
assertNotNull(names);
assertEquals(0, names.size());
@ -98,7 +98,7 @@ public class TestCookiePolicy extends TestCase {
}
public void testGetNewCookieSpec() {
CookieSpecRegistry registry = CookieSpecRegistry.DEFAULT;
CookieSpecRegistry registry = new CookieSpecRegistry();
registry.register(CookieSpecParams.BROWSER_COMPATIBILITY,
new BrowserCompatSpecFactory());
registry.register(CookieSpecParams.NETSCAPE,
@ -131,7 +131,7 @@ public class TestCookiePolicy extends TestCase {
}
public void testInvalidInput() {
CookieSpecRegistry registry = CookieSpecRegistry.DEFAULT;
CookieSpecRegistry registry = new CookieSpecRegistry();
try {
registry.register(null, null);
fail("IllegalArgumentException should have been thrown");

View File

@ -147,7 +147,7 @@ public class TestTSCCMNoServer extends TestCase {
}
mgr = null;
mgr = new ThreadSafeClientConnManager(params, null);
mgr = new ThreadSafeClientConnManager(params, schreg);
assertNotNull(mgr);
assertNotNull(mgr.getParams());
assertEquals(paramval, mgr.getParams().getParameter(paramkey));