1. /*
  2. * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HostConfiguration.java,v 1.19 2004/07/17 18:58:33 mbecke Exp $
  3. * $Revision: 1.19 $
  4. * $Date: 2004/07/17 18:58:33 $
  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;
  30. import org.apache.commons.httpclient.params.HostParams;
  31. import org.apache.commons.httpclient.protocol.Protocol;
  32. import java.net.InetAddress;
  33. /**
  34. * Holds all of the variables needed to describe an HTTP connection to a host. This includes
  35. * remote host, port and protocol, proxy host and port, local address, and virtual host.
  36. *
  37. * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
  38. * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
  39. * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
  40. * @author Laura Werner
  41. *
  42. * @since 2.0
  43. */
  44. public class HostConfiguration implements Cloneable {
  45. /**
  46. * A value to represent any host configuration, instead of using something like
  47. * <code>null</code>. This value should be treated as immutable and only used in
  48. * lookups and other such places to represent "any" host config.
  49. */
  50. public static final HostConfiguration ANY_HOST_CONFIGURATION = new HostConfiguration();
  51. /** The host to use. */
  52. private String host;
  53. /** The virtual host to use. */
  54. private String virtualHost;
  55. /** The port to use. */
  56. private int port;
  57. /** The protocol */
  58. private Protocol protocol;
  59. /** True if a host has been set */
  60. private boolean hostSet;
  61. /** The host name of the proxy server */
  62. private String proxyHost;
  63. /** The port number of the proxy server */
  64. private int proxyPort;
  65. /** True if a proxy server has been set */
  66. private boolean proxySet;
  67. /** The local address to use when creating the socket, or null to use the default */
  68. private InetAddress localAddress;
  69. /** Parameters specific to this host */
  70. private HostParams params;
  71. /**
  72. * Constructor for HostConfiguration.
  73. */
  74. public HostConfiguration() {
  75. this.host = null;
  76. this.virtualHost = null;
  77. this.port = -1;
  78. this.protocol = null;
  79. this.hostSet = false;
  80. this.proxyHost = null;
  81. this.proxyPort = -1;
  82. this.proxySet = false;
  83. this.localAddress = null;
  84. this.params = new HostParams();
  85. }
  86. /**
  87. * Copy constructor for HostConfiguration
  88. *
  89. * @param hostConfiguration the hostConfiguration to copy
  90. */
  91. public HostConfiguration (HostConfiguration hostConfiguration) {
  92. // wrap all of the assignments in a synchronized block to avoid
  93. // having to negotiate the monitor for each method call
  94. synchronized (hostConfiguration) {
  95. this.host = hostConfiguration.getHost();
  96. this.virtualHost = hostConfiguration.getVirtualHost();
  97. this.port = hostConfiguration.getPort();
  98. this.protocol = hostConfiguration.getProtocol();
  99. this.hostSet = hostConfiguration.isHostSet();
  100. this.proxyHost = hostConfiguration.getProxyHost();
  101. this.proxyPort = hostConfiguration.getProxyPort();
  102. this.proxySet = hostConfiguration.isProxySet();
  103. this.localAddress = hostConfiguration.getLocalAddress();
  104. try {
  105. this.params = (HostParams)hostConfiguration.getParams().clone();
  106. } catch (CloneNotSupportedException e) {
  107. this.params = new HostParams();
  108. }
  109. }
  110. }
  111. /**
  112. * @see java.lang.Object#clone()
  113. */
  114. public Object clone() {
  115. return new HostConfiguration(this);
  116. }
  117. /**
  118. * @see java.lang.Object#toString()
  119. */
  120. public synchronized String toString() {
  121. boolean appendComma = false;
  122. StringBuffer b = new StringBuffer(50);
  123. b.append("HostConfiguration[");
  124. if (isHostSet()) {
  125. appendComma = true;
  126. b.append("host=").append(host);
  127. b.append(", protocol=").append(protocol);
  128. b.append(", port=").append(port);
  129. if (virtualHost != null) {
  130. b.append(", virtualHost=").append(virtualHost);
  131. }
  132. }
  133. if (isProxySet()) {
  134. if (appendComma) {
  135. b.append(", ");
  136. } else {
  137. appendComma = true;
  138. }
  139. b.append("proxyHost=").append(proxyHost);
  140. b.append(", proxyPort=").append(proxyPort);
  141. }
  142. if (localAddress != null) {
  143. if (appendComma) {
  144. b.append(", ");
  145. } else {
  146. appendComma = true;
  147. }
  148. b.append("localAddress=").append(localAddress);
  149. }
  150. b.append("]");
  151. return b.toString();
  152. }
  153. /**
  154. * Tests if the host configuration equals the configuration set on the
  155. * connection. True only if the host, port, protocol, local address and virtual address
  156. * are equal. If no host configuration has been set false will be returned.
  157. *
  158. * @param connection the connection to test against
  159. * @return <code>true</code> if the connection's host information equals that of this
  160. * configuration
  161. *
  162. * @see #proxyEquals(HttpConnection)
  163. * @see #isHostSet()
  164. */
  165. public synchronized boolean hostEquals(HttpConnection connection) {
  166. if (hostSet) {
  167. if (!this.host.equalsIgnoreCase(connection.getHost())) {
  168. return false;
  169. }
  170. if (this.virtualHost != null) {
  171. if (!this.virtualHost.equalsIgnoreCase(connection.getVirtualHost())) {
  172. return false;
  173. }
  174. } else {
  175. if (connection.getVirtualHost() != null) {
  176. return false;
  177. }
  178. }
  179. if (this.port != connection.getPort()) {
  180. return false;
  181. }
  182. if (!this.protocol.equals(connection.getProtocol())) {
  183. return false;
  184. }
  185. if (this.localAddress != null) {
  186. if (!this.localAddress.equals(connection.getLocalAddress())) {
  187. return false;
  188. }
  189. } else {
  190. if (connection.getLocalAddress() != null) {
  191. return false;
  192. }
  193. }
  194. return true;
  195. } else {
  196. return false;
  197. }
  198. }
  199. /**
  200. * Tests if the proxy configuration equals the configuration set on the
  201. * connection. True only if the proxyHost and proxyPort are equal.
  202. *
  203. * @param connection the connection to test against
  204. * @return <code>true</code> if the connection's proxy information equals that of this
  205. * configuration
  206. *
  207. * @see #hostEquals(HttpConnection)
  208. */
  209. public synchronized boolean proxyEquals(HttpConnection connection) {
  210. if (proxyHost == null) {
  211. return connection.getProxyHost() == null;
  212. } else {
  213. return (
  214. proxyHost.equalsIgnoreCase(connection.getProxyHost())
  215. && proxyPort == connection.getProxyPort()
  216. );
  217. }
  218. }
  219. /**
  220. * Returns true if the host is set.
  221. * @return <code>true</code> if the host is set.
  222. */
  223. public synchronized boolean isHostSet() {
  224. return hostSet;
  225. }
  226. /**
  227. * Sets the given host, port and protocol
  228. *
  229. * @param host the host(IP or DNS name)
  230. * @param port The port
  231. * @param protocol The protocol.
  232. */
  233. public synchronized void setHost(String host, int port, String protocol) {
  234. setHost(host, null, port, Protocol.getProtocol(protocol));
  235. }
  236. /**
  237. * Sets the given host, virtual host, port and protocol.
  238. *
  239. * @param host the host(IP or DNS name)
  240. * @param virtualHost the virtual host name or <code>null</code>
  241. * @param port the host port or -1 to use protocol default
  242. * @param protocol the protocol
  243. */
  244. public synchronized void setHost(String host, String virtualHost, int port,
  245. Protocol protocol) {
  246. if (host == null) {
  247. throw new IllegalArgumentException("host must not be null");
  248. }
  249. if (protocol == null) {
  250. throw new IllegalArgumentException("protocol must not be null");
  251. }
  252. this.host = host;
  253. this.virtualHost = virtualHost;
  254. this.port = port == -1 ? protocol.getDefaultPort() : port;
  255. this.protocol = protocol;
  256. this.hostSet = true;
  257. }
  258. /**
  259. * Sets the given host, port and protocol.
  260. *
  261. * @param host the host(IP or DNS name)
  262. * @param port The port
  263. * @param protocol the protocol
  264. */
  265. public synchronized void setHost(String host, int port, Protocol protocol) {
  266. setHost(host, null, port, protocol);
  267. }
  268. /**
  269. * Sets the given host and port. Uses the default protocol "http".
  270. *
  271. * @param host the host(IP or DNS name)
  272. * @param port The port
  273. */
  274. public synchronized void setHost(String host, int port) {
  275. setHost(host, null, port, Protocol.getProtocol("http"));
  276. }
  277. /**
  278. * Set the given host. Uses the default protocol("http") and its port.
  279. *
  280. * @param host The host(IP or DNS name).
  281. */
  282. public synchronized void setHost(String host) {
  283. Protocol defaultProtocol = Protocol.getProtocol("http");
  284. setHost(host, null, defaultProtocol.getDefaultPort(), defaultProtocol);
  285. }
  286. /**
  287. * Sets the protocol, host and port from the given URI.
  288. * @param uri the URI.
  289. */
  290. public synchronized void setHost(URI uri) {
  291. try {
  292. setHost(uri.getHost(), uri.getPort(), uri.getScheme());
  293. } catch (URIException e) {
  294. throw new IllegalArgumentException(e.toString());
  295. }
  296. }
  297. /**
  298. * Return the host url.
  299. *
  300. * @return The host url.
  301. */
  302. public synchronized String getHostURL() {
  303. if (!hostSet) {
  304. throw new IllegalStateException("a default host must be set to "
  305. + "create a host URL"
  306. );
  307. }
  308. String url = protocol.getScheme() + "://" + host;
  309. if (port != -1 && port != protocol.getDefaultPort()) {
  310. url += ":" + port;
  311. }
  312. return url;
  313. }
  314. /**
  315. * Returns the host.
  316. *
  317. * @return the host(IP or DNS name), or <code>null</code> if not set
  318. *
  319. * @see #isHostSet()
  320. */
  321. public synchronized String getHost() {
  322. return host;
  323. }
  324. /**
  325. * Returns the virtual host.
  326. *
  327. * @return the virtual host name, or <code>null</code> if not set
  328. */
  329. public synchronized String getVirtualHost() {
  330. return virtualHost;
  331. }
  332. /**
  333. * Returns the port.
  334. *
  335. * @return the host port, or <code>-1</code> if not set
  336. *
  337. * @see #isHostSet()
  338. */
  339. public synchronized int getPort() {
  340. return port;
  341. }
  342. /**
  343. * Returns the protocol.
  344. * @return The protocol.
  345. */
  346. public synchronized Protocol getProtocol() {
  347. return protocol;
  348. }
  349. /**
  350. * Tests if the proxy host/port have been set.
  351. *
  352. * @return <code>true</code> if a proxy server has been set.
  353. *
  354. * @see #setProxy(String, int)
  355. */
  356. public synchronized boolean isProxySet() {
  357. return proxySet;
  358. }
  359. /**
  360. * Set the proxy settings.
  361. * @param proxyHost The proxy host
  362. * @param proxyPort The proxy port
  363. */
  364. public synchronized void setProxy(String proxyHost, int proxyPort) {
  365. this.proxyHost = proxyHost;
  366. this.proxyPort = proxyPort;
  367. this.proxySet = true;
  368. }
  369. /**
  370. * Returns the proxyHost.
  371. *
  372. * @return the proxy host, or <code>null</code> if not set
  373. *
  374. * @see #isProxySet()
  375. */
  376. public synchronized String getProxyHost() {
  377. return proxyHost;
  378. }
  379. /**
  380. * Returns the proxyPort.
  381. *
  382. * @return the proxy port, or <code>-1</code> if not set
  383. *
  384. * @see #isProxySet()
  385. */
  386. public synchronized int getProxyPort() {
  387. return proxyPort;
  388. }
  389. /**
  390. * Set the local address to be used when creating connections.
  391. * If this is unset, the default address will be used.
  392. * This is useful for specifying the interface to use on multi-homed or clustered systems.
  393. *
  394. * @param localAddress the local address to use
  395. */
  396. public synchronized void setLocalAddress(InetAddress localAddress) {
  397. this.localAddress = localAddress;
  398. }
  399. /**
  400. * Return the local address to be used when creating connections.
  401. * If this is unset, the default address should be used.
  402. *
  403. * @return the local address to be used when creating Sockets, or <code>null</code>
  404. */
  405. public synchronized InetAddress getLocalAddress() {
  406. return this.localAddress;
  407. }
  408. /**
  409. * Returns {@link HostParams HTTP protocol parameters} associated with this host.
  410. *
  411. * @return HTTP parameters.
  412. *
  413. * @since 3.0
  414. */
  415. public HostParams getParams() {
  416. return this.params;
  417. }
  418. /**
  419. * Assigns {@link HostParams HTTP protocol parameters} specific to this host.
  420. *
  421. * @since 3.0
  422. *
  423. * @see HostParams
  424. */
  425. public void setParams(final HostParams params) {
  426. if (params == null) {
  427. throw new IllegalArgumentException("Parameters may not be null");
  428. }
  429. this.params = params;
  430. }
  431. /**
  432. * @see java.lang.Object#equals(java.lang.Object)
  433. */
  434. public synchronized boolean equals(Object o) {
  435. if (o instanceof HostConfiguration) {
  436. // shortcut if we're comparing with ourselves
  437. if (o == this) {
  438. return true;
  439. }
  440. HostConfiguration config = (HostConfiguration) o;
  441. if (hostSet) {
  442. if (!host.equalsIgnoreCase(config.getHost())) {
  443. return false;
  444. }
  445. if (virtualHost != null) {
  446. if (!virtualHost.equalsIgnoreCase(config.getVirtualHost())) {
  447. return false;
  448. }
  449. } else {
  450. if (config.getVirtualHost() != null) {
  451. return false;
  452. }
  453. }
  454. if (port != config.getPort()) {
  455. return false;
  456. }
  457. if (!protocol.equals(config.getProtocol())) {
  458. return false;
  459. }
  460. } else if (config.isHostSet()) {
  461. return false;
  462. }
  463. if (proxyHost != null) {
  464. if (!proxyHost.equalsIgnoreCase (config.getProxyHost())
  465. || proxyPort != config.getProxyPort()) {
  466. // either proxyHost or proxyPort don't match
  467. return false;
  468. }
  469. } else if (config.getProxyHost() != null) {
  470. return false;
  471. }
  472. if (localAddress != null) {
  473. if (!localAddress.equals(config.getLocalAddress())) {
  474. return false;
  475. }
  476. } else {
  477. if (config.getLocalAddress() != null) {
  478. return false;
  479. }
  480. }
  481. // everything matches
  482. return true;
  483. } else {
  484. return false;
  485. }
  486. }
  487. /**
  488. * @see java.lang.Object#hashCode()
  489. */
  490. public int hashCode() {
  491. if (host != null) {
  492. return host.hashCode();
  493. } else if (proxyHost != null) {
  494. return proxyHost.hashCode();
  495. } else {
  496. return super.hashCode();
  497. }
  498. }
  499. }