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