View Javadoc

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.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   * @since 4.2
58   *
59   * @deprecated (4.3) use {@link ManagedHttpClientConnectionFactory}.
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      @Override
87      public String getId() {
88          return null;
89      }
90  
91      HttpPoolEntry getPoolEntry() {
92          return this.poolEntry;
93      }
94  
95      HttpPoolEntry detach() {
96          final HttpPoolEntry local = this.poolEntry;
97          this.poolEntry = null;
98          return local;
99      }
100 
101     public ClientConnectionManager getManager() {
102         return this.manager;
103     }
104 
105     private OperatedClientConnection getConnection() {
106         final HttpPoolEntry local = this.poolEntry;
107         if (local == null) {
108             return null;
109         }
110         return local.getConnection();
111     }
112 
113     private OperatedClientConnection ensureConnection() {
114         final HttpPoolEntry local = this.poolEntry;
115         if (local == null) {
116             throw new ConnectionShutdownException();
117         }
118         return local.getConnection();
119     }
120 
121     private HttpPoolEntry ensurePoolEntry() {
122         final HttpPoolEntry local = this.poolEntry;
123         if (local == null) {
124             throw new ConnectionShutdownException();
125         }
126         return local;
127     }
128 
129     @Override
130     public void close() throws IOException {
131         final HttpPoolEntry local = this.poolEntry;
132         if (local != null) {
133             final OperatedClientConnection conn = local.getConnection();
134             local.getTracker().reset();
135             conn.close();
136         }
137     }
138 
139     @Override
140     public void shutdown() throws IOException {
141         final HttpPoolEntry local = this.poolEntry;
142         if (local != null) {
143             final OperatedClientConnection conn = local.getConnection();
144             local.getTracker().reset();
145             conn.shutdown();
146         }
147     }
148 
149     @Override
150     public boolean isOpen() {
151         final OperatedClientConnection conn = getConnection();
152         if (conn != null) {
153             return conn.isOpen();
154         } else {
155             return false;
156         }
157     }
158 
159     @Override
160     public boolean isStale() {
161         final OperatedClientConnection conn = getConnection();
162         if (conn != null) {
163             return conn.isStale();
164         } else {
165             return true;
166         }
167     }
168 
169     @Override
170     public void setSocketTimeout(final int timeout) {
171         final OperatedClientConnection conn = ensureConnection();
172         conn.setSocketTimeout(timeout);
173     }
174 
175     @Override
176     public int getSocketTimeout() {
177         final OperatedClientConnection conn = ensureConnection();
178         return conn.getSocketTimeout();
179     }
180 
181     @Override
182     public HttpConnectionMetrics getMetrics() {
183         final OperatedClientConnection conn = ensureConnection();
184         return conn.getMetrics();
185     }
186 
187     @Override
188     public void flush() throws IOException {
189         final OperatedClientConnection conn = ensureConnection();
190         conn.flush();
191     }
192 
193     @Override
194     public boolean isResponseAvailable(final int timeout) throws IOException {
195         final OperatedClientConnection conn = ensureConnection();
196         return conn.isResponseAvailable(timeout);
197     }
198 
199     @Override
200     public void receiveResponseEntity(
201             final HttpResponse response) throws HttpException, IOException {
202         final OperatedClientConnection conn = ensureConnection();
203         conn.receiveResponseEntity(response);
204     }
205 
206     @Override
207     public HttpResponse receiveResponseHeader() throws HttpException, IOException {
208         final OperatedClientConnection conn = ensureConnection();
209         return conn.receiveResponseHeader();
210     }
211 
212     @Override
213     public void sendRequestEntity(
214             final HttpEntityEnclosingRequest request) throws HttpException, IOException {
215         final OperatedClientConnection conn = ensureConnection();
216         conn.sendRequestEntity(request);
217     }
218 
219     @Override
220     public void sendRequestHeader(
221             final HttpRequest request) throws HttpException, IOException {
222         final OperatedClientConnection conn = ensureConnection();
223         conn.sendRequestHeader(request);
224     }
225 
226     @Override
227     public InetAddress getLocalAddress() {
228         final OperatedClientConnection conn = ensureConnection();
229         return conn.getLocalAddress();
230     }
231 
232     @Override
233     public int getLocalPort() {
234         final OperatedClientConnection conn = ensureConnection();
235         return conn.getLocalPort();
236     }
237 
238     @Override
239     public InetAddress getRemoteAddress() {
240         final OperatedClientConnection conn = ensureConnection();
241         return conn.getRemoteAddress();
242     }
243 
244     @Override
245     public int getRemotePort() {
246         final OperatedClientConnection conn = ensureConnection();
247         return conn.getRemotePort();
248     }
249 
250     @Override
251     public boolean isSecure() {
252         final OperatedClientConnection conn = ensureConnection();
253         return conn.isSecure();
254     }
255 
256     @Override
257     public void bind(final Socket socket) throws IOException {
258         throw new UnsupportedOperationException();
259     }
260 
261     @Override
262     public Socket getSocket() {
263         final OperatedClientConnection conn = ensureConnection();
264         return conn.getSocket();
265     }
266 
267     @Override
268     public SSLSession getSSLSession() {
269         final OperatedClientConnection conn = ensureConnection();
270         SSLSession result = null;
271         final Socket sock = conn.getSocket();
272         if (sock instanceof SSLSocket) {
273             result = ((SSLSocket)sock).getSession();
274         }
275         return result;
276     }
277 
278     public Object getAttribute(final String id) {
279         final OperatedClientConnection conn = ensureConnection();
280         if (conn instanceof HttpContext) {
281             return ((HttpContext) conn).getAttribute(id);
282         } else {
283             return null;
284         }
285     }
286 
287     public Object removeAttribute(final String id) {
288         final OperatedClientConnection conn = ensureConnection();
289         if (conn instanceof HttpContext) {
290             return ((HttpContext) conn).removeAttribute(id);
291         } else {
292             return null;
293         }
294     }
295 
296     public void setAttribute(final String id, final Object obj) {
297         final OperatedClientConnection conn = ensureConnection();
298         if (conn instanceof HttpContext) {
299             ((HttpContext) conn).setAttribute(id, obj);
300         }
301     }
302 
303     @Override
304     public HttpRoute getRoute() {
305         final HttpPoolEntry local = ensurePoolEntry();
306         return local.getEffectiveRoute();
307     }
308 
309     @Override
310     public void open(
311             final HttpRoute route,
312             final HttpContext context,
313             final HttpParams params) throws IOException {
314         Args.notNull(route, "Route");
315         Args.notNull(params, "HTTP parameters");
316         final OperatedClientConnection conn;
317         synchronized (this) {
318             if (this.poolEntry == null) {
319                 throw new ConnectionShutdownException();
320             }
321             final RouteTracker tracker = this.poolEntry.getTracker();
322             Asserts.notNull(tracker, "Route tracker");
323             Asserts.check(!tracker.isConnected(), "Connection already open");
324             conn = this.poolEntry.getConnection();
325         }
326 
327         final HttpHost proxy  = route.getProxyHost();
328         this.operator.openConnection(
329                 conn,
330                 (proxy != null) ? proxy : route.getTargetHost(),
331                 route.getLocalAddress(),
332                 context, params);
333 
334         synchronized (this) {
335             if (this.poolEntry == null) {
336                 throw new InterruptedIOException();
337             }
338             final RouteTracker tracker = this.poolEntry.getTracker();
339             if (proxy == null) {
340                 tracker.connectTarget(conn.isSecure());
341             } else {
342                 tracker.connectProxy(proxy, conn.isSecure());
343             }
344         }
345     }
346 
347     @Override
348     public void tunnelTarget(
349             final boolean secure, final HttpParams params) throws IOException {
350         Args.notNull(params, "HTTP parameters");
351         final HttpHost target;
352         final OperatedClientConnection conn;
353         synchronized (this) {
354             if (this.poolEntry == null) {
355                 throw new ConnectionShutdownException();
356             }
357             final RouteTracker tracker = this.poolEntry.getTracker();
358             Asserts.notNull(tracker, "Route tracker");
359             Asserts.check(tracker.isConnected(), "Connection not open");
360             Asserts.check(!tracker.isTunnelled(), "Connection is already tunnelled");
361             target = tracker.getTargetHost();
362             conn = this.poolEntry.getConnection();
363         }
364 
365         conn.update(null, target, secure, params);
366 
367         synchronized (this) {
368             if (this.poolEntry == null) {
369                 throw new InterruptedIOException();
370             }
371             final RouteTracker tracker = this.poolEntry.getTracker();
372             tracker.tunnelTarget(secure);
373         }
374     }
375 
376     @Override
377     public void tunnelProxy(
378             final HttpHost next, final boolean secure, final HttpParams params) throws IOException {
379         Args.notNull(next, "Next proxy");
380         Args.notNull(params, "HTTP parameters");
381         final 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             conn = this.poolEntry.getConnection();
390         }
391 
392         conn.update(null, next, secure, params);
393 
394         synchronized (this) {
395             if (this.poolEntry == null) {
396                 throw new InterruptedIOException();
397             }
398             final RouteTracker tracker = this.poolEntry.getTracker();
399             tracker.tunnelProxy(next, secure);
400         }
401     }
402 
403     @Override
404     public void layerProtocol(
405             final HttpContext context, final HttpParams params) throws IOException {
406         Args.notNull(params, "HTTP parameters");
407         final HttpHost target;
408         final OperatedClientConnection conn;
409         synchronized (this) {
410             if (this.poolEntry == null) {
411                 throw new ConnectionShutdownException();
412             }
413             final RouteTracker tracker = this.poolEntry.getTracker();
414             Asserts.notNull(tracker, "Route tracker");
415             Asserts.check(tracker.isConnected(), "Connection not open");
416             Asserts.check(tracker.isTunnelled(), "Protocol layering without a tunnel not supported");
417             Asserts.check(!tracker.isLayered(), "Multiple protocol layering not supported");
418             target = tracker.getTargetHost();
419             conn = this.poolEntry.getConnection();
420         }
421         this.operator.updateSecureConnection(conn, target, context, params);
422 
423         synchronized (this) {
424             if (this.poolEntry == null) {
425                 throw new InterruptedIOException();
426             }
427             final RouteTracker tracker = this.poolEntry.getTracker();
428             tracker.layerProtocol(conn.isSecure());
429         }
430     }
431 
432     @Override
433     public Object getState() {
434         final HttpPoolEntry local = ensurePoolEntry();
435         return local.getState();
436     }
437 
438     @Override
439     public void setState(final Object state) {
440         final HttpPoolEntry local = ensurePoolEntry();
441         local.setState(state);
442     }
443 
444     @Override
445     public void markReusable() {
446         this.reusable = true;
447     }
448 
449     @Override
450     public void unmarkReusable() {
451         this.reusable = false;
452     }
453 
454     @Override
455     public boolean isMarkedReusable() {
456         return this.reusable;
457     }
458 
459     @Override
460     public void setIdleDuration(final long duration, final TimeUnit unit) {
461         if(duration > 0) {
462             this.duration = unit.toMillis(duration);
463         } else {
464             this.duration = -1;
465         }
466     }
467 
468     @Override
469     public void releaseConnection() {
470         synchronized (this) {
471             if (this.poolEntry == null) {
472                 return;
473             }
474             this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
475             this.poolEntry = null;
476         }
477     }
478 
479     @Override
480     public void abortConnection() {
481         synchronized (this) {
482             if (this.poolEntry == null) {
483                 return;
484             }
485             this.reusable = false;
486             final OperatedClientConnection conn = this.poolEntry.getConnection();
487             try {
488                 conn.shutdown();
489             } catch (final IOException ignore) {
490             }
491             this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
492             this.poolEntry = null;
493         }
494     }
495 
496 }