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 package org.apache.http.impl.conn;
28
29 import java.io.IOException;
30 import java.io.InterruptedIOException;
31 import java.net.InetAddress;
32 import java.net.Socket;
33 import java.util.concurrent.TimeUnit;
34
35 import javax.net.ssl.SSLSession;
36 import javax.net.ssl.SSLSocket;
37
38 import org.apache.http.HttpConnectionMetrics;
39 import org.apache.http.HttpEntityEnclosingRequest;
40 import org.apache.http.HttpException;
41 import org.apache.http.HttpHost;
42 import org.apache.http.HttpRequest;
43 import org.apache.http.HttpResponse;
44 import org.apache.http.annotation.NotThreadSafe;
45 import org.apache.http.conn.ClientConnectionManager;
46 import org.apache.http.conn.ClientConnectionOperator;
47 import org.apache.http.conn.ManagedClientConnection;
48 import org.apache.http.conn.OperatedClientConnection;
49 import org.apache.http.conn.routing.HttpRoute;
50 import org.apache.http.conn.routing.RouteTracker;
51 import org.apache.http.params.HttpParams;
52 import org.apache.http.protocol.HttpContext;
53 import org.apache.http.util.Args;
54 import org.apache.http.util.Asserts;
55
56
57
58
59
60
61 @Deprecated
62 @NotThreadSafe
63 class ManagedClientConnectionImpl implements ManagedClientConnection {
64
65 private final ClientConnectionManager manager;
66 private final ClientConnectionOperator operator;
67 private volatile HttpPoolEntry poolEntry;
68 private volatile boolean reusable;
69 private volatile long duration;
70
71 ManagedClientConnectionImpl(
72 final ClientConnectionManager manager,
73 final ClientConnectionOperator operator,
74 final HttpPoolEntry entry) {
75 super();
76 Args.notNull(manager, "Connection manager");
77 Args.notNull(operator, "Connection operator");
78 Args.notNull(entry, "HTTP pool entry");
79 this.manager = manager;
80 this.operator = operator;
81 this.poolEntry = entry;
82 this.reusable = false;
83 this.duration = Long.MAX_VALUE;
84 }
85
86 public String getId() {
87 return null;
88 }
89
90 HttpPoolEntry getPoolEntry() {
91 return this.poolEntry;
92 }
93
94 HttpPoolEntry detach() {
95 final HttpPoolEntry local = this.poolEntry;
96 this.poolEntry = null;
97 return local;
98 }
99
100 public ClientConnectionManager getManager() {
101 return this.manager;
102 }
103
104 private OperatedClientConnection getConnection() {
105 final HttpPoolEntry local = this.poolEntry;
106 if (local == null) {
107 return null;
108 }
109 return local.getConnection();
110 }
111
112 private OperatedClientConnection ensureConnection() {
113 final HttpPoolEntry local = this.poolEntry;
114 if (local == null) {
115 throw new ConnectionShutdownException();
116 }
117 return local.getConnection();
118 }
119
120 private HttpPoolEntry ensurePoolEntry() {
121 final HttpPoolEntry local = this.poolEntry;
122 if (local == null) {
123 throw new ConnectionShutdownException();
124 }
125 return local;
126 }
127
128 public void close() throws IOException {
129 final HttpPoolEntry local = this.poolEntry;
130 if (local != null) {
131 final OperatedClientConnection conn = local.getConnection();
132 local.getTracker().reset();
133 conn.close();
134 }
135 }
136
137 public void shutdown() throws IOException {
138 final HttpPoolEntry local = this.poolEntry;
139 if (local != null) {
140 final OperatedClientConnection conn = local.getConnection();
141 local.getTracker().reset();
142 conn.shutdown();
143 }
144 }
145
146 public boolean isOpen() {
147 final OperatedClientConnection conn = getConnection();
148 if (conn != null) {
149 return conn.isOpen();
150 } else {
151 return false;
152 }
153 }
154
155 public boolean isStale() {
156 final OperatedClientConnection conn = getConnection();
157 if (conn != null) {
158 return conn.isStale();
159 } else {
160 return true;
161 }
162 }
163
164 public void setSocketTimeout(final int timeout) {
165 final OperatedClientConnection conn = ensureConnection();
166 conn.setSocketTimeout(timeout);
167 }
168
169 public int getSocketTimeout() {
170 final OperatedClientConnection conn = ensureConnection();
171 return conn.getSocketTimeout();
172 }
173
174 public HttpConnectionMetrics getMetrics() {
175 final OperatedClientConnection conn = ensureConnection();
176 return conn.getMetrics();
177 }
178
179 public void flush() throws IOException {
180 final OperatedClientConnection conn = ensureConnection();
181 conn.flush();
182 }
183
184 public boolean isResponseAvailable(final int timeout) throws IOException {
185 final OperatedClientConnection conn = ensureConnection();
186 return conn.isResponseAvailable(timeout);
187 }
188
189 public void receiveResponseEntity(
190 final HttpResponse response) throws HttpException, IOException {
191 final OperatedClientConnection conn = ensureConnection();
192 conn.receiveResponseEntity(response);
193 }
194
195 public HttpResponse receiveResponseHeader() throws HttpException, IOException {
196 final OperatedClientConnection conn = ensureConnection();
197 return conn.receiveResponseHeader();
198 }
199
200 public void sendRequestEntity(
201 final HttpEntityEnclosingRequest request) throws HttpException, IOException {
202 final OperatedClientConnection conn = ensureConnection();
203 conn.sendRequestEntity(request);
204 }
205
206 public void sendRequestHeader(
207 final HttpRequest request) throws HttpException, IOException {
208 final OperatedClientConnection conn = ensureConnection();
209 conn.sendRequestHeader(request);
210 }
211
212 public InetAddress getLocalAddress() {
213 final OperatedClientConnection conn = ensureConnection();
214 return conn.getLocalAddress();
215 }
216
217 public int getLocalPort() {
218 final OperatedClientConnection conn = ensureConnection();
219 return conn.getLocalPort();
220 }
221
222 public InetAddress getRemoteAddress() {
223 final OperatedClientConnection conn = ensureConnection();
224 return conn.getRemoteAddress();
225 }
226
227 public int getRemotePort() {
228 final OperatedClientConnection conn = ensureConnection();
229 return conn.getRemotePort();
230 }
231
232 public boolean isSecure() {
233 final OperatedClientConnection conn = ensureConnection();
234 return conn.isSecure();
235 }
236
237 public void bind(final Socket socket) throws IOException {
238 throw new UnsupportedOperationException();
239 }
240
241 public Socket getSocket() {
242 final OperatedClientConnection conn = ensureConnection();
243 return conn.getSocket();
244 }
245
246 public SSLSession getSSLSession() {
247 final OperatedClientConnection conn = ensureConnection();
248 SSLSession result = null;
249 final Socket sock = conn.getSocket();
250 if (sock instanceof SSLSocket) {
251 result = ((SSLSocket)sock).getSession();
252 }
253 return result;
254 }
255
256 public Object getAttribute(final String id) {
257 final OperatedClientConnection conn = ensureConnection();
258 if (conn instanceof HttpContext) {
259 return ((HttpContext) conn).getAttribute(id);
260 } else {
261 return null;
262 }
263 }
264
265 public Object removeAttribute(final String id) {
266 final OperatedClientConnection conn = ensureConnection();
267 if (conn instanceof HttpContext) {
268 return ((HttpContext) conn).removeAttribute(id);
269 } else {
270 return null;
271 }
272 }
273
274 public void setAttribute(final String id, final Object obj) {
275 final OperatedClientConnection conn = ensureConnection();
276 if (conn instanceof HttpContext) {
277 ((HttpContext) conn).setAttribute(id, obj);
278 }
279 }
280
281 public HttpRoute getRoute() {
282 final HttpPoolEntry local = ensurePoolEntry();
283 return local.getEffectiveRoute();
284 }
285
286 public void open(
287 final HttpRoute route,
288 final HttpContext context,
289 final HttpParams params) throws IOException {
290 Args.notNull(route, "Route");
291 Args.notNull(params, "HTTP parameters");
292 OperatedClientConnection conn;
293 synchronized (this) {
294 if (this.poolEntry == null) {
295 throw new ConnectionShutdownException();
296 }
297 final RouteTracker tracker = this.poolEntry.getTracker();
298 Asserts.notNull(tracker, "Route tracker");
299 Asserts.check(!tracker.isConnected(), "Connection already open");
300 conn = this.poolEntry.getConnection();
301 }
302
303 final HttpHost proxy = route.getProxyHost();
304 this.operator.openConnection(
305 conn,
306 (proxy != null) ? proxy : route.getTargetHost(),
307 route.getLocalAddress(),
308 context, params);
309
310 synchronized (this) {
311 if (this.poolEntry == null) {
312 throw new InterruptedIOException();
313 }
314 final RouteTracker tracker = this.poolEntry.getTracker();
315 if (proxy == null) {
316 tracker.connectTarget(conn.isSecure());
317 } else {
318 tracker.connectProxy(proxy, conn.isSecure());
319 }
320 }
321 }
322
323 public void tunnelTarget(
324 final boolean secure, final HttpParams params) throws IOException {
325 Args.notNull(params, "HTTP parameters");
326 HttpHost target;
327 OperatedClientConnection conn;
328 synchronized (this) {
329 if (this.poolEntry == null) {
330 throw new ConnectionShutdownException();
331 }
332 final RouteTracker tracker = this.poolEntry.getTracker();
333 Asserts.notNull(tracker, "Route tracker");
334 Asserts.check(tracker.isConnected(), "Connection not open");
335 Asserts.check(!tracker.isTunnelled(), "Connection is already tunnelled");
336 target = tracker.getTargetHost();
337 conn = this.poolEntry.getConnection();
338 }
339
340 conn.update(null, target, secure, params);
341
342 synchronized (this) {
343 if (this.poolEntry == null) {
344 throw new InterruptedIOException();
345 }
346 final RouteTracker tracker = this.poolEntry.getTracker();
347 tracker.tunnelTarget(secure);
348 }
349 }
350
351 public void tunnelProxy(
352 final HttpHost next, final boolean secure, final HttpParams params) throws IOException {
353 Args.notNull(next, "Next proxy");
354 Args.notNull(params, "HTTP parameters");
355 OperatedClientConnection conn;
356 synchronized (this) {
357 if (this.poolEntry == null) {
358 throw new ConnectionShutdownException();
359 }
360 final RouteTracker tracker = this.poolEntry.getTracker();
361 Asserts.notNull(tracker, "Route tracker");
362 Asserts.check(tracker.isConnected(), "Connection not open");
363 conn = this.poolEntry.getConnection();
364 }
365
366 conn.update(null, next, secure, params);
367
368 synchronized (this) {
369 if (this.poolEntry == null) {
370 throw new InterruptedIOException();
371 }
372 final RouteTracker tracker = this.poolEntry.getTracker();
373 tracker.tunnelProxy(next, secure);
374 }
375 }
376
377 public void layerProtocol(
378 final HttpContext context, final HttpParams params) throws IOException {
379 Args.notNull(params, "HTTP parameters");
380 HttpHost target;
381 OperatedClientConnection conn;
382 synchronized (this) {
383 if (this.poolEntry == null) {
384 throw new ConnectionShutdownException();
385 }
386 final RouteTracker tracker = this.poolEntry.getTracker();
387 Asserts.notNull(tracker, "Route tracker");
388 Asserts.check(tracker.isConnected(), "Connection not open");
389 Asserts.check(tracker.isTunnelled(), "Protocol layering without a tunnel not supported");
390 Asserts.check(!tracker.isLayered(), "Multiple protocol layering not supported");
391 target = tracker.getTargetHost();
392 conn = this.poolEntry.getConnection();
393 }
394 this.operator.updateSecureConnection(conn, target, context, params);
395
396 synchronized (this) {
397 if (this.poolEntry == null) {
398 throw new InterruptedIOException();
399 }
400 final RouteTracker tracker = this.poolEntry.getTracker();
401 tracker.layerProtocol(conn.isSecure());
402 }
403 }
404
405 public Object getState() {
406 final HttpPoolEntry local = ensurePoolEntry();
407 return local.getState();
408 }
409
410 public void setState(final Object state) {
411 final HttpPoolEntry local = ensurePoolEntry();
412 local.setState(state);
413 }
414
415 public void markReusable() {
416 this.reusable = true;
417 }
418
419 public void unmarkReusable() {
420 this.reusable = false;
421 }
422
423 public boolean isMarkedReusable() {
424 return this.reusable;
425 }
426
427 public void setIdleDuration(final long duration, final TimeUnit unit) {
428 if(duration > 0) {
429 this.duration = unit.toMillis(duration);
430 } else {
431 this.duration = -1;
432 }
433 }
434
435 public void releaseConnection() {
436 synchronized (this) {
437 if (this.poolEntry == null) {
438 return;
439 }
440 this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
441 this.poolEntry = null;
442 }
443 }
444
445 public void abortConnection() {
446 synchronized (this) {
447 if (this.poolEntry == null) {
448 return;
449 }
450 this.reusable = false;
451 final OperatedClientConnection conn = this.poolEntry.getConnection();
452 try {
453 conn.shutdown();
454 } catch (final IOException ignore) {
455 }
456 this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
457 this.poolEntry = null;
458 }
459 }
460
461 }