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