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