Index: src/java/org/apache/http/conn/impl/MultiThreadedHttpConnectionManager.java =================================================================== --- src/java/org/apache/http/conn/impl/MultiThreadedHttpConnectionManager.java (revision 489341) +++ src/java/org/apache/http/conn/impl/MultiThreadedHttpConnectionManager.java (working copy) @@ -340,9 +340,8 @@ synchronized (connectionPool) { - // we clone the hostConfiguration - // so that it cannot be changed once the connection has been retrieved - hostConfiguration = new HostConfiguration(hostConfiguration); + // we used to clone the hostconfig here, but it is now immutable: + //hostConfiguration = new HostConfiguration(hostConfiguration); HostConnectionPool hostPool = connectionPool.getHostPool(hostConfiguration); WaitingThread waitingThread = null; Index: src/java/org/apache/http/conn/HostConfiguration.java =================================================================== --- src/java/org/apache/http/conn/HostConfiguration.java (revision 489337) +++ src/java/org/apache/http/conn/HostConfiguration.java (working copy) @@ -34,10 +34,17 @@ import org.apache.http.HttpHost; import org.apache.http.util.LangUtils; + + /** - * Holds all of the variables needed to describe an HTTP connection to a host. This includes - * remote host, port and protocol, proxy host and port, local address, and virtual host. + * Provides configuration data for connecting to a host. + * That is the host to connect to plus + * a proxy to use or a local IP address to select + * one of several network interfaces. + * Instances of this class are immutable. + * Instances of derived classes should be immutable, too. * + * @author Roland Weber * @author Michael Becke * @author Mike Bowler * @author Oleg Kalnichevski @@ -48,294 +55,124 @@ public class HostConfiguration implements Cloneable { /** - * A value to represent any host configuration, instead of using something like - * null. This value should be treated as immutable and only used in - * lookups and other such places to represent "any" host config. + * Constant representing a configuration for any host. + * That means to no host in particular. Use this constant in + * cases where you'd otherwise pass null to + * refer to a default value that applies to "any" host. */ - public static final HostConfiguration ANY_HOST_CONFIGURATION = new HostConfiguration(); + public static final + HostConfiguration ANY_HOST_CONFIGURATION = new HostConfiguration(); - /** The host to use. */ - private HttpHost host = null; + /** The host to connect to. */ + private final HttpHost targetHost; /** The host name of the proxy server */ - private HttpHost proxyHost = null; + private final HttpHost proxyHost; - /** The local address to use when creating the socket, or null to use the default */ - private InetAddress localAddress = null; - /** - * Constructor for HostConfiguration. + * The local address to use when creating the socket. + * null indicates that the default should be used. */ - public HostConfiguration() { - super(); - } - + private final InetAddress localAddress; + + /** - * Copy constructor for HostConfiguration - * - * @param hostConfiguration the hostConfiguration to copy + * Creates a new host configuration. + * + * @param host the target host to connect to + * @param proxy the proxy host to use, or + * null for a direct connection + * @param laddr the local IP address to use, or + * null for any */ - public HostConfiguration (final HostConfiguration hostConfiguration) { - // wrap all of the assignments in a synchronized block to avoid - // having to negotiate the monitor for each method call - synchronized (hostConfiguration) { - if (hostConfiguration.host != null) { - this.host = new HttpHost(hostConfiguration.host); - } else { - this.host = null; - } - if (hostConfiguration.proxyHost != null) { - this.proxyHost = new HttpHost(hostConfiguration.proxyHost); - } else { - this.proxyHost = null; - } - this.localAddress = hostConfiguration.getLocalAddress(); - } + public HostConfiguration(HttpHost host, HttpHost proxy, + InetAddress laddr) { + if (host == null) { + throw new IllegalArgumentException("Target host may not be null."); + } + this.targetHost = host; + this.proxyHost = proxy; + this.localAddress = laddr; } + /** - * @see java.lang.Object#clone() + * Creates a new "any" host configuration. + * This is the only way to create a host configuration + * without a target host. It is used exclusively to initialize + * {@link #ANY_HOST_CONFIGURATION ANY_HOST_CONFIGURATION}. */ - public Object clone() { - return new HostConfiguration(this); - } - - /** - * @see java.lang.Object#toString() - */ - public synchronized String toString() { + private HostConfiguration() { + this.targetHost = null; + this.proxyHost = null; + this.localAddress = null; + } + + + // non-javadoc, see java.lang.Object#toString() + public String toString() { - boolean appendComma = false; StringBuffer b = new StringBuffer(50); b.append("HostConfiguration["); - if (this.host != null) { - appendComma = true; - b.append("host=").append(this.host); + if (this.targetHost != null) { + b.append("host=").append(this.targetHost); + } else { + b.append("host=*any*"); } if (this.proxyHost != null) { - if (appendComma) { - b.append(", "); - } else { - appendComma = true; - } - b.append("proxyHost=").append(this.proxyHost); + b.append(", ").append("proxyHost=").append(this.proxyHost); } if (this.localAddress != null) { - if (appendComma) { - b.append(", "); - } else { - appendComma = true; - } - b.append("localAddress=").append(this.localAddress); - if (appendComma) { - b.append(", "); - } else { - appendComma = true; - } + b.append(", ").append("localAddress=").append(this.localAddress); } b.append("]"); return b.toString(); - } - - /** - * Sets the given host - * - * @param host the host - */ - public synchronized void setHost(final HttpHost host) { - this.host = host; } - - /** - * Sets the given host, port and protocol - * - * @param host the host(IP or DNS name) - * @param port The port - * @param protocol The protocol. - */ - public synchronized void setHost(final String host, int port, final String protocol) { - this.host = new HttpHost(host, port, protocol); - } - - /** - * Sets the given host and port. Uses the default protocol "http". - * - * @param host the host(IP or DNS name) - * @param port The port - */ - public synchronized void setHost(final String host, int port) { - setHost(host, port, "http"); - } - - /** - * Set the given host. Uses the default protocol("http") and its port. - * - * @param host The host(IP or DNS name). - */ - public synchronized void setHost(final String host) { - setHost(host, -1, "http"); - } - - /** - * Return the host url. - * - * @return The host url. - */ - public synchronized String getHostURL() { - if (this.host == null) { - throw new IllegalStateException("Host must be set to create a host URL"); - } else { - return this.host.toURI(); - } - } + /** * Returns the target host. * - * @return the target host, or null if not set - * - * @see #isHostSet() + * @return the target host, or null if this is + * {@link #ANY_HOST_CONFIGURATION ANY_HOST_CONFIGURATION} */ - public synchronized HttpHost getHost() { - return this.host; + public HttpHost getHost() { + return this.targetHost; } - /** - * Returns the host name. - * - * @return the host(IP or DNS name), or null if not set - * - * @see #isHostSet() - */ - public synchronized String getHostName() { - if (this.host != null) { - return this.host.getHostName(); - } else { - return null; - } - } /** - * Returns the port. + * Returns the proxy to use. * - * @return the host port, or -1 if not set - * - * @see #isHostSet() - */ - public synchronized int getPort() { - if (this.host != null) { - return this.host.getPort(); - } else { - return -1; - } - } - - /** - * Returns the protocol. - * @return The protocol. - */ - public synchronized Scheme getScheme() { - if (this.host != null) { - return Scheme.getScheme(this.host.getSchemeName()); - } else { - return null; - } - } - - /** - * Sets the given proxy host - * - * @param proxyHost the proxy host - */ - public synchronized void setProxyHost(final HttpHost proxyHost) { - this.proxyHost = proxyHost; - } - - /** - * Set the proxy settings. - * @param proxyHost The proxy host - * @param proxyPort The proxy port - */ - public synchronized void setProxy(final String proxyHost, int proxyPort) { - this.proxyHost = new HttpHost(proxyHost, proxyPort); - } - - /** - * Returns the proxyHost. - * * @return the proxy host, or null if not set - * - * @see #isProxySet() */ - public synchronized HttpHost getProxyHost() { + public HttpHost getProxyHost() { return this.proxyHost; } - /** - * Returns the proxyHost. - * - * @return the proxy host, or null if not set - * - * @see #isProxySet() - */ - public synchronized String getProxyHostName() { - if (this.proxyHost != null) { - return this.proxyHost.getHostName(); - } else { - return null; - } - } /** - * Returns the proxyPort. - * - * @return the proxy port, or -1 if not set - * - * @see #isProxySet() - */ - public synchronized int getProxyPort() { - if (this.proxyHost != null) { - return this.proxyHost.getPort(); - } else { - return -1; - } - } - - /** - * Set the local address to be used when creating connections. - * If this is unset, the default address will be used. - * This is useful for specifying the interface to use on multi-homed or clustered systems. - * - * @param localAddress the local address to use - */ - - public synchronized void setLocalAddress(InetAddress localAddress) { - this.localAddress = localAddress; - } - - /** * Return the local address to be used when creating connections. * If this is unset, the default address should be used. * - * @return the local address to be used when creating Sockets, or null + * @return the local address to be used when creating Sockets, + * or null */ - - public synchronized InetAddress getLocalAddress() { + public InetAddress getLocalAddress() { return this.localAddress; } - - /** - * @see java.lang.Object#equals(java.lang.Object) - */ - public synchronized boolean equals(final Object o) { + + + // non-javadoc, see java.lang.Object#equals(java.lang.Object) + public boolean equals(final Object o) { if (o instanceof HostConfiguration) { // shortcut if we're comparing with ourselves if (o == this) { return true; } HostConfiguration that = (HostConfiguration) o; - return LangUtils.equals(this.host, that.host) + return LangUtils.equals(this.targetHost, that.targetHost) && LangUtils.equals(this.proxyHost, that.proxyHost) && LangUtils.equals(this.localAddress, that.localAddress); } else { @@ -344,12 +181,10 @@ } - /** - * @see java.lang.Object#hashCode() - */ - public synchronized int hashCode() { + // non-javadoc, see java.lang.Object#hashCode() + public int hashCode() { int hash = LangUtils.HASH_SEED; - hash = LangUtils.hashCode(hash, this.host); + hash = LangUtils.hashCode(hash, this.targetHost); hash = LangUtils.hashCode(hash, this.proxyHost); hash = LangUtils.hashCode(hash, this.localAddress); return hash;