PageRenderTime 70ms CodeModel.GetById 43ms RepoModel.GetById 1ms app.codeStats 0ms

/sdks/httpcomponents-client-4.1.2-src/httpcomponents-client-4.1.2/httpclient/src/main/java/org/apache/http/conn/routing/HttpRoute.java

https://github.com/steveclark7/Test1
Java | 410 lines | 183 code | 68 blank | 159 comment | 44 complexity | c84e343bb99cf503f8cabc3d4042fb99 MD5 | raw file
  1. /*
  2. * ====================================================================
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. * ====================================================================
  20. *
  21. * This software consists of voluntary contributions made by many
  22. * individuals on behalf of the Apache Software Foundation. For more
  23. * information on the Apache Software Foundation, please see
  24. * <http://www.apache.org/>.
  25. *
  26. */
  27. package org.apache.http.conn.routing;
  28. import java.net.InetAddress;
  29. import org.apache.http.annotation.Immutable;
  30. import org.apache.http.util.LangUtils;
  31. import org.apache.http.HttpHost;
  32. /**
  33. * The route for a request.
  34. * Instances of this class are unmodifiable and therefore suitable
  35. * for use as lookup keys.
  36. *
  37. * @since 4.0
  38. */
  39. @Immutable
  40. public final class HttpRoute implements RouteInfo, Cloneable {
  41. private static final HttpHost[] EMPTY_HTTP_HOST_ARRAY = new HttpHost[]{};
  42. /** The target host to connect to. */
  43. private final HttpHost targetHost;
  44. /**
  45. * The local address to connect from.
  46. * <code>null</code> indicates that the default should be used.
  47. */
  48. private final InetAddress localAddress;
  49. /** The proxy servers, if any. Never null. */
  50. private final HttpHost[] proxyChain;
  51. /** Whether the the route is tunnelled through the proxy. */
  52. private final TunnelType tunnelled;
  53. /** Whether the route is layered. */
  54. private final LayerType layered;
  55. /** Whether the route is (supposed to be) secure. */
  56. private final boolean secure;
  57. /**
  58. * Internal, fully-specified constructor.
  59. * This constructor does <i>not</i> clone the proxy chain array,
  60. * nor test it for <code>null</code> elements. This conversion and
  61. * check is the responsibility of the public constructors.
  62. * The order of arguments here is different from the similar public
  63. * constructor, as required by Java.
  64. *
  65. * @param local the local address to route from, or
  66. * <code>null</code> for the default
  67. * @param target the host to which to route
  68. * @param proxies the proxy chain to use, or
  69. * <code>null</code> for a direct route
  70. * @param secure <code>true</code> if the route is (to be) secure,
  71. * <code>false</code> otherwise
  72. * @param tunnelled the tunnel type of this route, or
  73. * <code>null</code> for PLAIN
  74. * @param layered the layering type of this route, or
  75. * <code>null</code> for PLAIN
  76. */
  77. private HttpRoute(InetAddress local,
  78. HttpHost target, HttpHost[] proxies,
  79. boolean secure,
  80. TunnelType tunnelled, LayerType layered) {
  81. if (target == null) {
  82. throw new IllegalArgumentException
  83. ("Target host may not be null.");
  84. }
  85. if (proxies == null) {
  86. throw new IllegalArgumentException
  87. ("Proxies may not be null.");
  88. }
  89. if ((tunnelled == TunnelType.TUNNELLED) && (proxies.length == 0)) {
  90. throw new IllegalArgumentException
  91. ("Proxy required if tunnelled.");
  92. }
  93. // tunnelled is already checked above, that is in line with the default
  94. if (tunnelled == null)
  95. tunnelled = TunnelType.PLAIN;
  96. if (layered == null)
  97. layered = LayerType.PLAIN;
  98. this.targetHost = target;
  99. this.localAddress = local;
  100. this.proxyChain = proxies;
  101. this.secure = secure;
  102. this.tunnelled = tunnelled;
  103. this.layered = layered;
  104. }
  105. /**
  106. * Creates a new route with all attributes specified explicitly.
  107. *
  108. * @param target the host to which to route
  109. * @param local the local address to route from, or
  110. * <code>null</code> for the default
  111. * @param proxies the proxy chain to use, or
  112. * <code>null</code> for a direct route
  113. * @param secure <code>true</code> if the route is (to be) secure,
  114. * <code>false</code> otherwise
  115. * @param tunnelled the tunnel type of this route
  116. * @param layered the layering type of this route
  117. */
  118. public HttpRoute(HttpHost target, InetAddress local, HttpHost[] proxies,
  119. boolean secure, TunnelType tunnelled, LayerType layered) {
  120. this(local, target, toChain(proxies), secure, tunnelled, layered);
  121. }
  122. /**
  123. * Creates a new route with at most one proxy.
  124. *
  125. * @param target the host to which to route
  126. * @param local the local address to route from, or
  127. * <code>null</code> for the default
  128. * @param proxy the proxy to use, or
  129. * <code>null</code> for a direct route
  130. * @param secure <code>true</code> if the route is (to be) secure,
  131. * <code>false</code> otherwise
  132. * @param tunnelled <code>true</code> if the route is (to be) tunnelled
  133. * via the proxy,
  134. * <code>false</code> otherwise
  135. * @param layered <code>true</code> if the route includes a
  136. * layered protocol,
  137. * <code>false</code> otherwise
  138. */
  139. public HttpRoute(HttpHost target, InetAddress local, HttpHost proxy,
  140. boolean secure, TunnelType tunnelled, LayerType layered) {
  141. this(local, target, toChain(proxy), secure, tunnelled, layered);
  142. }
  143. /**
  144. * Creates a new direct route.
  145. * That is a route without a proxy.
  146. *
  147. * @param target the host to which to route
  148. * @param local the local address to route from, or
  149. * <code>null</code> for the default
  150. * @param secure <code>true</code> if the route is (to be) secure,
  151. * <code>false</code> otherwise
  152. */
  153. public HttpRoute(HttpHost target, InetAddress local, boolean secure) {
  154. this(local, target, EMPTY_HTTP_HOST_ARRAY, secure, TunnelType.PLAIN, LayerType.PLAIN);
  155. }
  156. /**
  157. * Creates a new direct insecure route.
  158. *
  159. * @param target the host to which to route
  160. */
  161. public HttpRoute(HttpHost target) {
  162. this(null, target, EMPTY_HTTP_HOST_ARRAY, false, TunnelType.PLAIN, LayerType.PLAIN);
  163. }
  164. /**
  165. * Creates a new route through a proxy.
  166. * When using this constructor, the <code>proxy</code> MUST be given.
  167. * For convenience, it is assumed that a secure connection will be
  168. * layered over a tunnel through the proxy.
  169. *
  170. * @param target the host to which to route
  171. * @param local the local address to route from, or
  172. * <code>null</code> for the default
  173. * @param proxy the proxy to use
  174. * @param secure <code>true</code> if the route is (to be) secure,
  175. * <code>false</code> otherwise
  176. */
  177. public HttpRoute(HttpHost target, InetAddress local, HttpHost proxy,
  178. boolean secure) {
  179. this(local, target, toChain(proxy), secure,
  180. secure ? TunnelType.TUNNELLED : TunnelType.PLAIN,
  181. secure ? LayerType.LAYERED : LayerType.PLAIN);
  182. if (proxy == null) {
  183. throw new IllegalArgumentException
  184. ("Proxy host may not be null.");
  185. }
  186. }
  187. /**
  188. * Helper to convert a proxy to a proxy chain.
  189. *
  190. * @param proxy the only proxy in the chain, or <code>null</code>
  191. *
  192. * @return a proxy chain array, may be empty (never null)
  193. */
  194. private static HttpHost[] toChain(HttpHost proxy) {
  195. if (proxy == null)
  196. return EMPTY_HTTP_HOST_ARRAY;
  197. return new HttpHost[]{ proxy };
  198. }
  199. /**
  200. * Helper to duplicate and check a proxy chain.
  201. * <code>null</code> is converted to an empty proxy chain.
  202. *
  203. * @param proxies the proxy chain to duplicate, or <code>null</code>
  204. *
  205. * @return a new proxy chain array, may be empty (never null)
  206. */
  207. private static HttpHost[] toChain(HttpHost[] proxies) {
  208. if ((proxies == null) || (proxies.length < 1))
  209. return EMPTY_HTTP_HOST_ARRAY;
  210. for (HttpHost proxy : proxies) {
  211. if (proxy == null)
  212. throw new IllegalArgumentException
  213. ("Proxy chain may not contain null elements.");
  214. }
  215. // copy the proxy chain, the traditional way
  216. HttpHost[] result = new HttpHost[proxies.length];
  217. System.arraycopy(proxies, 0, result, 0, proxies.length);
  218. return result;
  219. }
  220. // non-JavaDoc, see interface RouteInfo
  221. public final HttpHost getTargetHost() {
  222. return this.targetHost;
  223. }
  224. // non-JavaDoc, see interface RouteInfo
  225. public final InetAddress getLocalAddress() {
  226. return this.localAddress;
  227. }
  228. public final int getHopCount() {
  229. return proxyChain.length+1;
  230. }
  231. public final HttpHost getHopTarget(int hop) {
  232. if (hop < 0)
  233. throw new IllegalArgumentException
  234. ("Hop index must not be negative: " + hop);
  235. final int hopcount = getHopCount();
  236. if (hop >= hopcount)
  237. throw new IllegalArgumentException
  238. ("Hop index " + hop +
  239. " exceeds route length " + hopcount);
  240. HttpHost result = null;
  241. if (hop < hopcount-1)
  242. result = this.proxyChain[hop];
  243. else
  244. result = this.targetHost;
  245. return result;
  246. }
  247. public final HttpHost getProxyHost() {
  248. return (this.proxyChain.length == 0) ? null : this.proxyChain[0];
  249. }
  250. public final TunnelType getTunnelType() {
  251. return this.tunnelled;
  252. }
  253. public final boolean isTunnelled() {
  254. return (this.tunnelled == TunnelType.TUNNELLED);
  255. }
  256. public final LayerType getLayerType() {
  257. return this.layered;
  258. }
  259. public final boolean isLayered() {
  260. return (this.layered == LayerType.LAYERED);
  261. }
  262. public final boolean isSecure() {
  263. return this.secure;
  264. }
  265. /**
  266. * Compares this route to another.
  267. *
  268. * @param obj the object to compare with
  269. *
  270. * @return <code>true</code> if the argument is the same route,
  271. * <code>false</code>
  272. */
  273. @Override
  274. public final boolean equals(Object obj) {
  275. if (this == obj) return true;
  276. if (obj instanceof HttpRoute) {
  277. HttpRoute that = (HttpRoute) obj;
  278. return
  279. // Do the cheapest tests first
  280. (this.secure == that.secure) &&
  281. (this.tunnelled == that.tunnelled) &&
  282. (this.layered == that.layered) &&
  283. LangUtils.equals(this.targetHost, that.targetHost) &&
  284. LangUtils.equals(this.localAddress, that.localAddress) &&
  285. LangUtils.equals(this.proxyChain, that.proxyChain);
  286. } else {
  287. return false;
  288. }
  289. }
  290. /**
  291. * Generates a hash code for this route.
  292. *
  293. * @return the hash code
  294. */
  295. @Override
  296. public final int hashCode() {
  297. int hash = LangUtils.HASH_SEED;
  298. hash = LangUtils.hashCode(hash, this.targetHost);
  299. hash = LangUtils.hashCode(hash, this.localAddress);
  300. for (int i = 0; i < this.proxyChain.length; i++) {
  301. hash = LangUtils.hashCode(hash, this.proxyChain[i]);
  302. }
  303. hash = LangUtils.hashCode(hash, this.secure);
  304. hash = LangUtils.hashCode(hash, this.tunnelled);
  305. hash = LangUtils.hashCode(hash, this.layered);
  306. return hash;
  307. }
  308. /**
  309. * Obtains a description of this route.
  310. *
  311. * @return a human-readable representation of this route
  312. */
  313. @Override
  314. public final String toString() {
  315. StringBuilder cab = new StringBuilder(50 + getHopCount()*30);
  316. cab.append("HttpRoute[");
  317. if (this.localAddress != null) {
  318. cab.append(this.localAddress);
  319. cab.append("->");
  320. }
  321. cab.append('{');
  322. if (this.tunnelled == TunnelType.TUNNELLED)
  323. cab.append('t');
  324. if (this.layered == LayerType.LAYERED)
  325. cab.append('l');
  326. if (this.secure)
  327. cab.append('s');
  328. cab.append("}->");
  329. for (HttpHost aProxyChain : this.proxyChain) {
  330. cab.append(aProxyChain);
  331. cab.append("->");
  332. }
  333. cab.append(this.targetHost);
  334. cab.append(']');
  335. return cab.toString();
  336. }
  337. // default implementation of clone() is sufficient
  338. @Override
  339. public Object clone() throws CloneNotSupportedException {
  340. return super.clone();
  341. }
  342. }