1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.apache.commons.httpclient.protocol;
31
32 import java.io.IOException;
33 import java.net.InetAddress;
34 import java.net.Socket;
35 import java.net.UnknownHostException;
36
37 import javax.net.ssl.SSLSocketFactory;
38
39 import org.apache.commons.httpclient.ConnectTimeoutException;
40 import org.apache.commons.httpclient.params.HttpConnectionParams;
41
42 /***
43 * A SecureProtocolSocketFactory that uses JSSE to create sockets.
44 *
45 * @author Michael Becke
46 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
47 *
48 * @since 2.0
49 */
50 public class SSLProtocolSocketFactory implements SecureProtocolSocketFactory {
51
52 /***
53 * The factory singleton.
54 */
55 private static final SSLProtocolSocketFactory factory = new SSLProtocolSocketFactory();
56
57 /***
58 * Gets an singleton instance of the SSLProtocolSocketFactory.
59 * @return a SSLProtocolSocketFactory
60 */
61 static SSLProtocolSocketFactory getSocketFactory() {
62 return factory;
63 }
64
65 /***
66 * Constructor for SSLProtocolSocketFactory.
67 */
68 public SSLProtocolSocketFactory() {
69 super();
70 }
71
72 /***
73 * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
74 */
75 public Socket createSocket(
76 String host,
77 int port,
78 InetAddress clientHost,
79 int clientPort)
80 throws IOException, UnknownHostException {
81 return SSLSocketFactory.getDefault().createSocket(
82 host,
83 port,
84 clientHost,
85 clientPort
86 );
87 }
88
89 /***
90 * Attempts to get a new socket connection to the given host within the given time limit.
91 * <p>
92 * This method employs several techniques to circumvent the limitations of older JREs that
93 * do not support connect timeout. When running in JRE 1.4 or above reflection is used to
94 * call Socket#connect(SocketAddress endpoint, int timeout) method. When executing in older
95 * JREs a controller thread is executed. The controller thread attempts to create a new socket
96 * within the given limit of time. If socket constructor does not return until the timeout
97 * expires, the controller terminates and throws an {@link ConnectTimeoutException}
98 * </p>
99 *
100 * @param host the host name/IP
101 * @param port the port on the host
102 * @param localAddress the local host name/IP to bind the socket to
103 * @param localPort the port on the local machine
104 * @param params {@link HttpConnectionParams Http connection parameters}
105 *
106 * @return Socket a new socket
107 *
108 * @throws IOException if an I/O error occurs while creating the socket
109 * @throws UnknownHostException if the IP address of the host cannot be
110 * determined
111 *
112 * @since 3.0
113 */
114 public Socket createSocket(
115 final String host,
116 final int port,
117 final InetAddress localAddress,
118 final int localPort,
119 final HttpConnectionParams params
120 ) throws IOException, UnknownHostException, ConnectTimeoutException {
121 if (params == null) {
122 throw new IllegalArgumentException("Parameters may not be null");
123 }
124 int timeout = params.getConnectionTimeout();
125 if (timeout == 0) {
126 return createSocket(host, port, localAddress, localPort);
127 } else {
128
129 Socket socket = ReflectionSocketFactory.createSocket(
130 "javax.net.ssl.SSLSocketFactory", host, port, localAddress, localPort, timeout);
131 if (socket == null) {
132 socket = ControllerThreadSocketFactory.createSocket(
133 this, host, port, localAddress, localPort, timeout);
134 }
135 return socket;
136 }
137 }
138
139 /***
140 * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
141 */
142 public Socket createSocket(String host, int port)
143 throws IOException, UnknownHostException {
144 return SSLSocketFactory.getDefault().createSocket(
145 host,
146 port
147 );
148 }
149
150 /***
151 * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
152 */
153 public Socket createSocket(
154 Socket socket,
155 String host,
156 int port,
157 boolean autoClose)
158 throws IOException, UnknownHostException {
159 return ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(
160 socket,
161 host,
162 port,
163 autoClose
164 );
165 }
166
167 /***
168 * All instances of SSLProtocolSocketFactory are the same.
169 */
170 public boolean equals(Object obj) {
171 return ((obj != null) && obj.getClass().equals(SSLProtocolSocketFactory.class));
172 }
173
174 /***
175 * All instances of SSLProtocolSocketFactory have the same hash code.
176 */
177 public int hashCode() {
178 return SSLProtocolSocketFactory.class.hashCode();
179 }
180
181 }