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 org.apache.commons.httpclient.ConnectTimeoutException;
38 import org.apache.commons.httpclient.params.HttpConnectionParams;
39
40 /***
41 * The default class for creating protocol sockets. This class just uses the
42 * {@link java.net.Socket socket} constructors.
43 *
44 * @author Michael Becke
45 *
46 * @since 2.0
47 */
48 public class DefaultProtocolSocketFactory implements ProtocolSocketFactory {
49
50 /***
51 * The factory singleton.
52 */
53 private static final DefaultProtocolSocketFactory factory = new DefaultProtocolSocketFactory();
54
55 /***
56 * Gets an singleton instance of the DefaultProtocolSocketFactory.
57 * @return a DefaultProtocolSocketFactory
58 */
59 static DefaultProtocolSocketFactory getSocketFactory() {
60 return factory;
61 }
62
63 /***
64 * Constructor for DefaultProtocolSocketFactory.
65 */
66 public DefaultProtocolSocketFactory() {
67 super();
68 }
69
70 /***
71 * @see #createSocket(java.lang.String,int,java.net.InetAddress,int)
72 */
73 public Socket createSocket(
74 String host,
75 int port,
76 InetAddress localAddress,
77 int localPort
78 ) throws IOException, UnknownHostException {
79 return new Socket(host, port, localAddress, localPort);
80 }
81
82 /***
83 * Attempts to get a new socket connection to the given host within the given time limit.
84 * <p>
85 * This method employs several techniques to circumvent the limitations of older JREs that
86 * do not support connect timeout. When running in JRE 1.4 or above reflection is used to
87 * call Socket#connect(SocketAddress endpoint, int timeout) method. When executing in older
88 * JREs a controller thread is executed. The controller thread attempts to create a new socket
89 * within the given limit of time. If socket constructor does not return until the timeout
90 * expires, the controller terminates and throws an {@link ConnectTimeoutException}
91 * </p>
92 *
93 * @param host the host name/IP
94 * @param port the port on the host
95 * @param localAddress the local host name/IP to bind the socket to
96 * @param localPort the port on the local machine
97 * @param params {@link HttpConnectionParams Http connection parameters}
98 *
99 * @return Socket a new socket
100 *
101 * @throws IOException if an I/O error occurs while creating the socket
102 * @throws UnknownHostException if the IP address of the host cannot be
103 * determined
104 * @throws ConnectTimeoutException if socket cannot be connected within the
105 * given time limit
106 *
107 * @since 3.0
108 */
109 public Socket createSocket(
110 final String host,
111 final int port,
112 final InetAddress localAddress,
113 final int localPort,
114 final HttpConnectionParams params
115 ) throws IOException, UnknownHostException, ConnectTimeoutException {
116 if (params == null) {
117 throw new IllegalArgumentException("Parameters may not be null");
118 }
119 int timeout = params.getConnectionTimeout();
120 if (timeout == 0) {
121 return createSocket(host, port, localAddress, localPort);
122 } else {
123
124 Socket socket = ReflectionSocketFactory.createSocket(
125 "javax.net.SocketFactory", host, port, localAddress, localPort, timeout);
126 if (socket == null) {
127 socket = ControllerThreadSocketFactory.createSocket(
128 this, host, port, localAddress, localPort, timeout);
129 }
130 return socket;
131 }
132 }
133
134 /***
135 * @see ProtocolSocketFactory#createSocket(java.lang.String,int)
136 */
137 public Socket createSocket(String host, int port)
138 throws IOException, UnknownHostException {
139 return new Socket(host, port);
140 }
141
142 /***
143 * All instances of DefaultProtocolSocketFactory are the same.
144 */
145 public boolean equals(Object obj) {
146 return ((obj != null) && obj.getClass().equals(DefaultProtocolSocketFactory.class));
147 }
148
149 /***
150 * All instances of DefaultProtocolSocketFactory have the same hash code.
151 */
152 public int hashCode() {
153 return DefaultProtocolSocketFactory.class.hashCode();
154 }
155
156 }