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 package org.apache.http.conn.routing;
29
30 import java.net.InetAddress;
31
32 import org.apache.http.HttpHost;
33 import org.apache.http.util.Args;
34 import org.apache.http.util.Asserts;
35 import org.apache.http.util.LangUtils;
36
37
38
39
40
41
42 public final class RouteTracker implements RouteInfo, Cloneable {
43
44
45 private final HttpHost targetHost;
46
47
48
49
50
51 private final InetAddress localAddress;
52
53
54
55
56
57 private boolean connected;
58
59
60 private HttpHost[] proxyChain;
61
62
63 private TunnelType tunnelled;
64
65
66 private LayerType layered;
67
68
69 private boolean secure;
70
71
72
73
74
75
76
77
78
79 public RouteTracker(final HttpHost target, final InetAddress local) {
80 Args.notNull(target, "Target host");
81 this.targetHost = target;
82 this.localAddress = local;
83 this.tunnelled = TunnelType.PLAIN;
84 this.layered = LayerType.PLAIN;
85 }
86
87
88
89
90 public void reset() {
91 this.connected = false;
92 this.proxyChain = null;
93 this.tunnelled = TunnelType.PLAIN;
94 this.layered = LayerType.PLAIN;
95 this.secure = false;
96 }
97
98
99
100
101
102
103
104
105 public RouteTracker(final HttpRoute route) {
106 this(route.getTargetHost(), route.getLocalAddress());
107 }
108
109
110
111
112
113
114
115 public void connectTarget(final boolean secure) {
116 Asserts.check(!this.connected, "Already connected");
117 this.connected = true;
118 this.secure = secure;
119 }
120
121
122
123
124
125
126
127
128 public void connectProxy(final HttpHost proxy, final boolean secure) {
129 Args.notNull(proxy, "Proxy host");
130 Asserts.check(!this.connected, "Already connected");
131 this.connected = true;
132 this.proxyChain = new HttpHost[]{ proxy };
133 this.secure = secure;
134 }
135
136
137
138
139
140
141
142 public void tunnelTarget(final boolean secure) {
143 Asserts.check(this.connected, "No tunnel unless connected");
144 Asserts.notNull(this.proxyChain, "No tunnel without proxy");
145 this.tunnelled = TunnelType.TUNNELLED;
146 this.secure = secure;
147 }
148
149
150
151
152
153
154
155
156
157
158 public void tunnelProxy(final HttpHost proxy, final boolean secure) {
159 Args.notNull(proxy, "Proxy host");
160 Asserts.check(this.connected, "No tunnel unless connected");
161 Asserts.notNull(this.proxyChain, "No tunnel without proxy");
162
163 final HttpHost[] proxies = new HttpHost[this.proxyChain.length+1];
164 System.arraycopy(this.proxyChain, 0,
165 proxies, 0, this.proxyChain.length);
166 proxies[proxies.length-1] = proxy;
167
168 this.proxyChain = proxies;
169 this.secure = secure;
170 }
171
172
173
174
175
176
177
178 public void layerProtocol(final boolean secure) {
179
180
181 Asserts.check(this.connected, "No layered protocol unless connected");
182 this.layered = LayerType.LAYERED;
183 this.secure = secure;
184 }
185
186 @Override
187 public HttpHost getTargetHost() {
188 return this.targetHost;
189 }
190
191 @Override
192 public InetAddress getLocalAddress() {
193 return this.localAddress;
194 }
195
196 @Override
197 public int getHopCount() {
198 int hops = 0;
199 if (this.connected) {
200 if (proxyChain == null) {
201 hops = 1;
202 } else {
203 hops = proxyChain.length + 1;
204 }
205 }
206 return hops;
207 }
208
209 @Override
210 public HttpHost getHopTarget(final int hop) {
211 Args.notNegative(hop, "Hop index");
212 final int hopcount = getHopCount();
213 Args.check(hop < hopcount, "Hop index exceeds tracked route length");
214 HttpHost result = null;
215 if (hop < hopcount-1) {
216 result = this.proxyChain[hop];
217 } else {
218 result = this.targetHost;
219 }
220
221 return result;
222 }
223
224 @Override
225 public HttpHost getProxyHost() {
226 return (this.proxyChain == null) ? null : this.proxyChain[0];
227 }
228
229 public boolean isConnected() {
230 return this.connected;
231 }
232
233 @Override
234 public TunnelType getTunnelType() {
235 return this.tunnelled;
236 }
237
238 @Override
239 public boolean isTunnelled() {
240 return (this.tunnelled == TunnelType.TUNNELLED);
241 }
242
243 @Override
244 public LayerType getLayerType() {
245 return this.layered;
246 }
247
248 @Override
249 public boolean isLayered() {
250 return (this.layered == LayerType.LAYERED);
251 }
252
253 @Override
254 public boolean isSecure() {
255 return this.secure;
256 }
257
258
259
260
261
262
263
264
265
266 public HttpRoute toRoute() {
267 return !this.connected ?
268 null : new HttpRoute(this.targetHost, this.localAddress,
269 this.proxyChain, this.secure,
270 this.tunnelled, this.layered);
271 }
272
273
274
275
276
277
278
279
280
281 @Override
282 public boolean equals(final Object o) {
283 if (o == this) {
284 return true;
285 }
286 if (!(o instanceof RouteTracker)) {
287 return false;
288 }
289
290 final RouteTracker./../../../org/apache/http/conn/routing/RouteTracker.html#RouteTracker">RouteTracker that = (RouteTracker) o;
291 return
292
293 (this.connected == that.connected) &&
294 (this.secure == that.secure) &&
295 (this.tunnelled == that.tunnelled) &&
296 (this.layered == that.layered) &&
297 LangUtils.equals(this.targetHost, that.targetHost) &&
298 LangUtils.equals(this.localAddress, that.localAddress) &&
299 LangUtils.equals(this.proxyChain, that.proxyChain);
300 }
301
302
303
304
305
306
307
308
309
310 @Override
311 public int hashCode() {
312 int hash = LangUtils.HASH_SEED;
313 hash = LangUtils.hashCode(hash, this.targetHost);
314 hash = LangUtils.hashCode(hash, this.localAddress);
315 if (this.proxyChain != null) {
316 for (final HttpHost element : this.proxyChain) {
317 hash = LangUtils.hashCode(hash, element);
318 }
319 }
320 hash = LangUtils.hashCode(hash, this.connected);
321 hash = LangUtils.hashCode(hash, this.secure);
322 hash = LangUtils.hashCode(hash, this.tunnelled);
323 hash = LangUtils.hashCode(hash, this.layered);
324 return hash;
325 }
326
327
328
329
330
331
332 @Override
333 public String toString() {
334 final StringBuilder cab = new StringBuilder(50 + getHopCount()*30);
335
336 cab.append("RouteTracker[");
337 if (this.localAddress != null) {
338 cab.append(this.localAddress);
339 cab.append("->");
340 }
341 cab.append('{');
342 if (this.connected) {
343 cab.append('c');
344 }
345 if (this.tunnelled == TunnelType.TUNNELLED) {
346 cab.append('t');
347 }
348 if (this.layered == LayerType.LAYERED) {
349 cab.append('l');
350 }
351 if (this.secure) {
352 cab.append('s');
353 }
354 cab.append("}->");
355 if (this.proxyChain != null) {
356 for (final HttpHost element : this.proxyChain) {
357 cab.append(element);
358 cab.append("->");
359 }
360 }
361 cab.append(this.targetHost);
362 cab.append(']');
363
364 return cab.toString();
365 }
366
367
368
369 @Override
370 public Object clone() throws CloneNotSupportedException {
371 return super.clone();
372 }
373
374 }