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
31 package org.apache.commons.httpclient.protocol;
32
33 import java.util.Collections;
34 import java.util.HashMap;
35 import java.util.Map;
36
37 /***
38 * A class to encapsulate the specifics of a protocol. This class class also
39 * provides the ability to customize the set and characteristics of the
40 * protocols used.
41 *
42 * <p>One use case for modifying the default set of protocols would be to set a
43 * custom SSL socket factory. This would look something like the following:
44 * <pre>
45 * Protocol myHTTPS = new Protocol( "https", new MySSLSocketFactory(), 443 );
46 *
47 * Protocol.registerProtocol( "https", myHTTPS );
48 * </pre>
49 *
50 * @author Michael Becke
51 * @author Jeff Dever
52 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
53 *
54 * @since 2.0
55 */
56 public class Protocol {
57
58 /*** The available protocols */
59 private static final Map PROTOCOLS = Collections.synchronizedMap(new HashMap());
60
61 /***
62 * Registers a new protocol with the given identifier. If a protocol with
63 * the given ID already exists it will be overridden. This ID is the same
64 * one used to retrieve the protocol from getProtocol(String).
65 *
66 * @param id the identifier for this protocol
67 * @param protocol the protocol to register
68 *
69 * @see #getProtocol(String)
70 */
71 public static void registerProtocol(String id, Protocol protocol) {
72
73 if (id == null) {
74 throw new IllegalArgumentException("id is null");
75 }
76 if (protocol == null) {
77 throw new IllegalArgumentException("protocol is null");
78 }
79
80 PROTOCOLS.put(id, protocol);
81 }
82
83 /***
84 * Unregisters the protocol with the given ID.
85 *
86 * @param id the ID of the protocol to remove
87 */
88 public static void unregisterProtocol(String id) {
89
90 if (id == null) {
91 throw new IllegalArgumentException("id is null");
92 }
93
94 PROTOCOLS.remove(id);
95 }
96
97 /***
98 * Gets the protocol with the given ID.
99 *
100 * @param id the protocol ID
101 *
102 * @return Protocol a protocol
103 *
104 * @throws IllegalStateException if a protocol with the ID cannot be found
105 */
106 public static Protocol getProtocol(String id)
107 throws IllegalStateException {
108
109 if (id == null) {
110 throw new IllegalArgumentException("id is null");
111 }
112
113 Protocol protocol = (Protocol) PROTOCOLS.get(id);
114
115 if (protocol == null) {
116 protocol = lazyRegisterProtocol(id);
117 }
118
119 return protocol;
120 }
121
122 /***
123 * Lazily registers the protocol with the given id.
124 *
125 * @param id the protocol ID
126 *
127 * @return the lazily registered protocol
128 *
129 * @throws IllegalStateException if the protocol with id is not recognized
130 */
131 private static Protocol lazyRegisterProtocol(String id)
132 throws IllegalStateException {
133
134 if ("http".equals(id)) {
135 final Protocol http
136 = new Protocol("http", DefaultProtocolSocketFactory.getSocketFactory(), 80);
137 Protocol.registerProtocol("http", http);
138 return http;
139 }
140
141 if ("https".equals(id)) {
142 final Protocol https
143 = new Protocol("https", SSLProtocolSocketFactory.getSocketFactory(), 443);
144 Protocol.registerProtocol("https", https);
145 return https;
146 }
147
148 throw new IllegalStateException("unsupported protocol: '" + id + "'");
149 }
150
151
152 /*** the scheme of this protocol (e.g. http, https) */
153 private String scheme;
154
155 /*** The socket factory for this protocol */
156 private ProtocolSocketFactory socketFactory;
157
158 /*** The default port for this protocol */
159 private int defaultPort;
160
161 /*** True if this protocol is secure */
162 private boolean secure;
163
164 /***
165 * Constructs a new Protocol. The created protcol is insecure.
166 *
167 * @param scheme the scheme (e.g. http, https)
168 * @param factory the factory for creating sockets for communication using
169 * this protocol
170 * @param defaultPort the port this protocol defaults to
171 */
172 public Protocol(String scheme, ProtocolSocketFactory factory, int defaultPort) {
173
174 if (scheme == null) {
175 throw new IllegalArgumentException("scheme is null");
176 }
177 if (factory == null) {
178 throw new IllegalArgumentException("socketFactory is null");
179 }
180 if (defaultPort <= 0) {
181 throw new IllegalArgumentException("port is invalid: " + defaultPort);
182 }
183
184 this.scheme = scheme;
185 this.socketFactory = factory;
186 this.defaultPort = defaultPort;
187 this.secure = false;
188 }
189
190 /***
191 * Constructs a new Protocol. The created protcol is secure.
192 *
193 * @param scheme the scheme (e.g. http, https)
194 * @param factory the factory for creating sockets for communication using
195 * this protocol
196 * @param defaultPort the port this protocol defaults to
197 */
198 public Protocol(String scheme,
199 SecureProtocolSocketFactory factory, int defaultPort) {
200
201 if (scheme == null) {
202 throw new IllegalArgumentException("scheme is null");
203 }
204 if (factory == null) {
205 throw new IllegalArgumentException("socketFactory is null");
206 }
207 if (defaultPort <= 0) {
208 throw new IllegalArgumentException("port is invalid: " + defaultPort);
209 }
210
211 this.scheme = scheme;
212 this.socketFactory = factory;
213 this.defaultPort = defaultPort;
214 this.secure = true;
215 }
216
217 /***
218 * Returns the defaultPort.
219 * @return int
220 */
221 public int getDefaultPort() {
222 return defaultPort;
223 }
224
225 /***
226 * Returns the socketFactory. If secure the factory is a
227 * SecureProtocolSocketFactory.
228 * @return SocketFactory
229 */
230 public ProtocolSocketFactory getSocketFactory() {
231 return socketFactory;
232 }
233
234 /***
235 * Returns the scheme.
236 * @return The scheme
237 */
238 public String getScheme() {
239 return scheme;
240 }
241
242 /***
243 * Returns true if this protocol is secure
244 * @return true if this protocol is secure
245 */
246 public boolean isSecure() {
247 return secure;
248 }
249
250 /***
251 * Resolves the correct port for this protocol. Returns the given port if
252 * valid or the default port otherwise.
253 *
254 * @param port the port to be resolved
255 *
256 * @return the given port or the defaultPort
257 */
258 public int resolvePort(int port) {
259 return port <= 0 ? getDefaultPort() : port;
260 }
261
262 /***
263 * Return a string representation of this object.
264 * @return a string representation of this object.
265 */
266 public String toString() {
267 return scheme + ":" + defaultPort;
268 }
269
270 /***
271 * Return true if the specified object equals this object.
272 * @param obj The object to compare against.
273 * @return true if the objects are equal.
274 */
275 public boolean equals(Object obj) {
276
277 if (obj instanceof Protocol) {
278
279 Protocol p = (Protocol) obj;
280
281 return (
282 defaultPort == p.getDefaultPort()
283 && scheme.equalsIgnoreCase(p.getScheme())
284 && secure == p.isSecure()
285 && socketFactory.equals(p.getSocketFactory()));
286
287 } else {
288 return false;
289 }
290
291 }
292
293 /***
294 * Return a hash code for this object
295 * @return The hash code.
296 */
297 public int hashCode() {
298 return scheme.hashCode();
299 }
300 }