Index: src/java/org/apache/http/conn/SocketFactory.java
===================================================================
--- src/java/org/apache/http/conn/SocketFactory.java (revision 490517)
+++ src/java/org/apache/http/conn/SocketFactory.java (working copy)
@@ -39,43 +39,61 @@
import org.apache.http.params.HttpParams;
/**
- * A factory for creating Sockets.
+ * A factory for creating and connecting sockets.
+ * The factory encapsulates the logic for establishing a socket connection.
+ *
+ * Both {@link java.lang.Object#equals(java.lang.Object) Object.equals()}
+ * and {@link java.lang.Object#hashCode() Object.hashCode()}
+ * must be overridden for the correct operation of some connection managers.
*
- *
Both {@link java.lang.Object#equals(java.lang.Object) Object.equals()} and
- * {@link java.lang.Object#hashCode() Object.hashCode()} should be overridden appropriately.
- * Protocol socket factories are used to uniquely identify Protocols and
- * HostConfigurations, and equals() and hashCode() are
- * required for the correct operation of some connection managers.
null indicates that a new socket
+ * should be created and connected.
+ * @param host the host to connect to
+ * @param port the port to connect to on the host
+ * @param localAddress the local address to bind the socket to, or
+ * null for any
+ * @param localPort the port on the local machine,
+ * 0 or a negative number for any
+ * @param params additional {@link HttpParams parameters} for connecting
*
- * @throws IOException if an I/O error occurs while creating the socket
- * @throws UnknownHostException if the IP address of the host cannot be
- * determined
- * @throws ConnectTimeoutException if socket cannot be connected within the
- * given time limit
+ * @return the connected socket. The returned object may be different
+ * from the sock argument if this factory supports
+ * a layered protocol.
*
- * @since 3.0
+ * @throws IOException if an I/O error occurs
+ * @throws UnknownHostException if the IP address of the target host
+ * can not be determined
+ * @throws ConnectTimeoutException if the socket cannot be connected
+ * within the time limit defined in the params
*/
Socket createSocket(
+ Socket sock,
String host,
int port,
InetAddress localAddress,
Index: src/java/org/apache/http/conn/ssl/SSLSocketFactory.java
===================================================================
--- src/java/org/apache/http/conn/ssl/SSLSocketFactory.java (revision 490517)
+++ src/java/org/apache/http/conn/ssl/SSLSocketFactory.java (working copy)
@@ -56,6 +56,8 @@
import java.security.UnrecoverableKeyException;
/**
+ * Secure socket factory based on {@link javax.net.ssl JSSE}
+ *.
* * SSLProtocolSocketFactory can be used to validate the identity of the HTTPS * server against a list of trusted certificates and to authenticate to the HTTPS @@ -230,44 +232,63 @@ return tmfactory.getTrustManagers(); } - /** - * Attempts to get a new socket connection to the given host within the given time limit. - * - * @param host the host name/IP - * @param port the port on the host - * @param localAddress the local host name/IP to bind the socket to - * @param localPort the port on the local machine - * @param params {@link HttpConnectionParams Http connection parameters} - * - * @return Socket a new socket - * - * @throws IOException if an I/O error occurs while creating the socket - * @throws UnknownHostException if the IP address of the host cannot be - * determined - * @throws ConnectTimeoutException if socket cannot be connected within the - * given time limit - * - * @since 3.0 - */ + + // non-javadoc, see interface org.apache.http.conn.SocketFactory + public Socket createSocket() + throws IOException { + + // the cast makes sure that the factory is working as expected + return (SSLSocket) this.socketfactory.createSocket(); + } + + + // non-javadoc, see interface org.apache.http.conn.SocketFactory public Socket createSocket( + final Socket sock, final String host, final int port, final InetAddress localAddress, - final int localPort, + int localPort, final HttpParams params - ) throws IOException, UnknownHostException, ConnectTimeoutException { + ) throws IOException { + + if (host == null) { + throw new IllegalArgumentException("Target host may not be null."); + } if (params == null) { - throw new IllegalArgumentException("Parameters may not be null"); + throw new IllegalArgumentException("Parameters may not be null."); } - SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(); - if (localAddress != null) { - sslSocket.bind(new InetSocketAddress(localAddress, localPort)); + + // resolve the target hostname first + final InetSocketAddress target = new InetSocketAddress(host, port); + + SSLSocket sslock = (SSLSocket) + ((sock != null) ? sock : createSocket()); + + if ((localAddress != null) || (localPort > 0)) { + + // we need to bind explicitly + if (localPort < 0) + localPort = 0; // indicates "any" + + InetSocketAddress isa = + new InetSocketAddress(localAddress, localPort); + sslock.bind(isa); } + int timeout = HttpConnectionParams.getConnectionTimeout(params); - sslSocket.connect(new InetSocketAddress(host, port), timeout); - hostnameVerifier.verify(host, sslSocket); - // verifyHostName() didn't blowup - good! - return sslSocket; + sslock.connect(target, timeout); + + try { + hostnameVerifier.verify(host, sslock); + // verifyHostName() didn't blowup - good! + } catch (IOException iox) { + // close the socket before re-throwing the exception + try { sslock.close(); } catch (Exception x) { /*ignore*/ } + throw iox; + } + + return sslock; } /** Index: src/java/org/apache/http/conn/impl/DefaultHttpHostConnection.java =================================================================== --- src/java/org/apache/http/conn/impl/DefaultHttpHostConnection.java (revision 490517) +++ src/java/org/apache/http/conn/impl/DefaultHttpHostConnection.java (working copy) @@ -157,7 +157,7 @@ } socketFactory = scheme.getSocketFactory(); Socket socket = socketFactory.createSocket( - hostname, port, + null, hostname, port, this.hostconf.getLocalAddress(), 0, params); // Bind connection to the socket Index: src/java/org/apache/http/conn/PlainSocketFactory.java =================================================================== --- src/java/org/apache/http/conn/PlainSocketFactory.java (revision 490517) +++ src/java/org/apache/http/conn/PlainSocketFactory.java (working copy) @@ -33,6 +33,7 @@ import java.io.IOException; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; @@ -40,85 +41,96 @@ import org.apache.http.params.HttpParams; /** - * The default class for creating protocol sockets. This class just uses the - * {@link java.net.Socket socket} constructors. + * The default class for creating sockets. + * This class just uses the {@link java.net.Socket socket} API + * in Java 1.4 or greater. * + * @author Roland Weber * @author Michael Becke - * - * @since 2.0 */ -public class PlainSocketFactory implements SocketFactory { +public final class PlainSocketFactory implements SocketFactory { /** * The factory singleton. */ - private static final PlainSocketFactory DEFAULT_FACTORY = new PlainSocketFactory(); - + private static final + PlainSocketFactory DEFAULT_FACTORY = new PlainSocketFactory(); + /** - * Gets an singleton instance of the DefaultProtocolSocketFactory. - * @return a DefaultProtocolSocketFactory + * Gets the singleton instance of this class. + * @return the one and only plain socket factory */ - public static PlainSocketFactory getSocketFactory() { + public static final PlainSocketFactory getSocketFactory() { return DEFAULT_FACTORY; } - + /** - * Constructor for DefaultProtocolSocketFactory. + * Restricted default constructor. */ private PlainSocketFactory() { super(); } - /** - * Attempts to get a new socket connection to using old (pre Java 1.4) IO mode. - * This socket factory does not support connect timeout as it requires Java 1.4 - * functionality. - * - * @param host the host name/IP - * @param port the port on the host - * @param localAddress the local host name/IP to bind the socket to - * @param localPort the port on the local machine - * @param params {@link HttpConnectionParams Http connection parameters} - * - * @return Socket a new socket - * - * @throws IOException if an I/O error occurs while creating the socket - * @throws UnknownHostException if the IP address of the host cannot be - * @throws IllegalStateException if connection timeout is set - * determined - * - * @since 3.0 - */ - public Socket createSocket( - final String host, - final int port, - final InetAddress localAddress, - final int localPort, - final HttpParams params - ) throws IOException, UnknownHostException { + + // non-javadoc, see interface org.apache.http.conn.SocketFactory + public Socket createSocket() { + return new Socket(); + } + + // non-javadoc, see interface org.apache.http.conn.SocketFactory + public Socket createSocket(Socket sock, String host, int port, + InetAddress localAddress, int localPort, + HttpParams params) + throws IOException { + + if (host == null) { + throw new IllegalArgumentException("Target host may not be null."); + } if (params == null) { - throw new IllegalArgumentException("Parameters may not be null"); + throw new IllegalArgumentException("Parameters may not be null."); } - int timeout = HttpConnectionParams.getConnectionTimeout(params); - if (timeout != 0) { - throw new IllegalStateException("Connection timeout is not supported in old IO mode"); + + // resolve the target hostname first + final InetSocketAddress target = new InetSocketAddress(host, port); + + if (sock == null) + sock = createSocket(); + + if ((localAddress != null) || (localPort > 0)) { + + // we need to bind explicitly + if (localPort < 0) + localPort = 0; // indicates "any" + + InetSocketAddress isa = + new InetSocketAddress(localAddress, localPort); + sock.bind(isa); } - if (localAddress != null) { - return new Socket(host, port, localAddress, localPort); - } else { - return new Socket(host, port); - } - } + int timeout = HttpConnectionParams.getConnectionTimeout(params); + sock.connect(target, timeout); + + return sock; + + } // createSocket(sock,host,...) + + /** - * All instances of DefaultProtocolSocketFactory are the same. + * Compares this factory with an object. + * There is only one instance of this class. + * + * @param obj the object to compare with + * + * @return iff the argument is this object */ public boolean equals(Object obj) { - return ((obj != null) && obj.getClass().equals(PlainSocketFactory.class)); + return (obj == this); } /** - * All instances of DefaultProtocolSocketFactory have the same hash code. + * Obtains a hash code for this object. + * All instances of this class have the same hash code. + * There is only one instance of this class. */ public int hashCode() { return PlainSocketFactory.class.hashCode();