1. /*
  2. * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/protocol/Protocol.java,v 1.10 2004/04/18 23:51:38 jsdever Exp $
  3. * $Revision: 1.10 $
  4. * $Date: 2004/04/18 23:51:38 $
  5. *
  6. * ====================================================================
  7. *
  8. * Copyright 2002-2004 The Apache Software Foundation
  9. *
  10. * Licensed under the Apache License, Version 2.0 (the "License");
  11. * you may not use this file except in compliance with the License.
  12. * You may obtain a copy of the License at
  13. *
  14. * http://www.apache.org/licenses/LICENSE-2.0
  15. *
  16. * Unless required by applicable law or agreed to in writing, software
  17. * distributed under the License is distributed on an "AS IS" BASIS,
  18. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. * See the License for the specific language governing permissions and
  20. * limitations under the License.
  21. * ====================================================================
  22. *
  23. * This software consists of voluntary contributions made by many
  24. * individuals on behalf of the Apache Software Foundation. For more
  25. * information on the Apache Software Foundation, please see
  26. * <http://www.apache.org/>.
  27. *
  28. */
  29. package org.apache.commons.httpclient.protocol;
  30. import java.util.Collections;
  31. import java.util.HashMap;
  32. import java.util.Map;
  33. /**
  34. * A class to encapsulate the specifics of a protocol. This class class also
  35. * provides the ability to customize the set and characteristics of the
  36. * protocols used.
  37. *
  38. * <p>One use case for modifying the default set of protocols would be to set a
  39. * custom SSL socket factory. This would look something like the following:
  40. * <pre>
  41. * Protocol myHTTPS = new Protocol( "https", new MySSLSocketFactory(), 443 );
  42. *
  43. * Protocol.registerProtocol( "https", myHTTPS );
  44. * </pre>
  45. *
  46. * @author Michael Becke
  47. * @author Jeff Dever
  48. * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
  49. *
  50. * @since 2.0
  51. */
  52. public class Protocol {
  53. /** The available protocols */
  54. private static final Map PROTOCOLS = Collections.synchronizedMap(new HashMap());
  55. /**
  56. * Registers a new protocol with the given identifier. If a protocol with
  57. * the given ID already exists it will be overridden. This ID is the same
  58. * one used to retrieve the protocol from getProtocol(String).
  59. *
  60. * @param id the identifier for this protocol
  61. * @param protocol the protocol to register
  62. *
  63. * @see #getProtocol(String)
  64. */
  65. public static void registerProtocol(String id, Protocol protocol) {
  66. if (id == null) {
  67. throw new IllegalArgumentException("id is null");
  68. }
  69. if (protocol == null) {
  70. throw new IllegalArgumentException("protocol is null");
  71. }
  72. PROTOCOLS.put(id, protocol);
  73. }
  74. /**
  75. * Unregisters the protocol with the given ID.
  76. *
  77. * @param id the ID of the protocol to remove
  78. */
  79. public static void unregisterProtocol(String id) {
  80. if (id == null) {
  81. throw new IllegalArgumentException("id is null");
  82. }
  83. PROTOCOLS.remove(id);
  84. }
  85. /**
  86. * Gets the protocol with the given ID.
  87. *
  88. * @param id the protocol ID
  89. *
  90. * @return Protocol a protocol
  91. *
  92. * @throws IllegalStateException if a protocol with the ID cannot be found
  93. */
  94. public static Protocol getProtocol(String id)
  95. throws IllegalStateException {
  96. if (id == null) {
  97. throw new IllegalArgumentException("id is null");
  98. }
  99. Protocol protocol = (Protocol) PROTOCOLS.get(id);
  100. if (protocol == null) {
  101. protocol = lazyRegisterProtocol(id);
  102. }
  103. return protocol;
  104. }
  105. /**
  106. * Lazily registers the protocol with the given id.
  107. *
  108. * @param id the protocol ID
  109. *
  110. * @return the lazily registered protocol
  111. *
  112. * @throws IllegalStateException if the protocol with id is not recognized
  113. */
  114. private static Protocol lazyRegisterProtocol(String id)
  115. throws IllegalStateException {
  116. if ("http".equals(id)) {
  117. final Protocol http
  118. = new Protocol("http", DefaultProtocolSocketFactory.getSocketFactory(), 80);
  119. Protocol.registerProtocol("http", http);
  120. return http;
  121. }
  122. if ("https".equals(id)) {
  123. final Protocol https
  124. = new Protocol("https", SSLProtocolSocketFactory.getSocketFactory(), 443);
  125. Protocol.registerProtocol("https", https);
  126. return https;
  127. }
  128. throw new IllegalStateException("unsupported protocol: '" + id + "'");
  129. }
  130. /** the scheme of this protocol (e.g. http, https) */
  131. private String scheme;
  132. /** The socket factory for this protocol */
  133. private ProtocolSocketFactory socketFactory;
  134. /** The default port for this protocol */
  135. private int defaultPort;
  136. /** True if this protocol is secure */
  137. private boolean secure;
  138. /**
  139. * Constructs a new Protocol. Whether the created protocol is secure depends on
  140. * the class of <code>factory</code>.
  141. *
  142. * @param scheme the scheme (e.g. http, https)
  143. * @param factory the factory for creating sockets for communication using
  144. * this protocol
  145. * @param defaultPort the port this protocol defaults to
  146. */
  147. public Protocol(String scheme, ProtocolSocketFactory factory, int defaultPort) {
  148. if (scheme == null) {
  149. throw new IllegalArgumentException("scheme is null");
  150. }
  151. if (factory == null) {
  152. throw new IllegalArgumentException("socketFactory is null");
  153. }
  154. if (defaultPort <= 0) {
  155. throw new IllegalArgumentException("port is invalid: " + defaultPort);
  156. }
  157. this.scheme = scheme;
  158. this.socketFactory = factory;
  159. this.defaultPort = defaultPort;
  160. this.secure = (factory instanceof SecureProtocolSocketFactory);
  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. * @deprecated Use the constructor that uses ProtocolSocketFactory, this version of
  171. * the constructor is only kept for backwards API compatibility.
  172. */
  173. public Protocol(String scheme,
  174. SecureProtocolSocketFactory factory, int defaultPort) {
  175. this(scheme, (ProtocolSocketFactory) factory, defaultPort);
  176. }
  177. /**
  178. * Returns the defaultPort.
  179. * @return int
  180. */
  181. public int getDefaultPort() {
  182. return defaultPort;
  183. }
  184. /**
  185. * Returns the socketFactory. If secure the factory is a
  186. * SecureProtocolSocketFactory.
  187. * @return SocketFactory
  188. */
  189. public ProtocolSocketFactory getSocketFactory() {
  190. return socketFactory;
  191. }
  192. /**
  193. * Returns the scheme.
  194. * @return The scheme
  195. */
  196. public String getScheme() {
  197. return scheme;
  198. }
  199. /**
  200. * Returns true if this protocol is secure
  201. * @return true if this protocol is secure
  202. */
  203. public boolean isSecure() {
  204. return secure;
  205. }
  206. /**
  207. * Resolves the correct port for this protocol. Returns the given port if
  208. * valid or the default port otherwise.
  209. *
  210. * @param port the port to be resolved
  211. *
  212. * @return the given port or the defaultPort
  213. */
  214. public int resolvePort(int port) {
  215. return port <= 0 ? getDefaultPort() : port;
  216. }
  217. /**
  218. * Return a string representation of this object.
  219. * @return a string representation of this object.
  220. */
  221. public String toString() {
  222. return scheme + ":" + defaultPort;
  223. }
  224. /**
  225. * Return true if the specified object equals this object.
  226. * @param obj The object to compare against.
  227. * @return true if the objects are equal.
  228. */
  229. public boolean equals(Object obj) {
  230. if (obj instanceof Protocol) {
  231. Protocol p = (Protocol) obj;
  232. return (
  233. defaultPort == p.getDefaultPort()
  234. && scheme.equalsIgnoreCase(p.getScheme())
  235. && secure == p.isSecure()
  236. && socketFactory.equals(p.getSocketFactory()));
  237. } else {
  238. return false;
  239. }
  240. }
  241. /**
  242. * Return a hash code for this object
  243. * @return The hash code.
  244. */
  245. public int hashCode() {
  246. return scheme.hashCode();
  247. }
  248. }