• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/AbstractClientConnAdapter.java $
3  * $Revision: 672969 $
4  * $Date: 2008-06-30 18:09:50 -0700 (Mon, 30 Jun 2008) $
5  *
6  * ====================================================================
7  *
8  *  Licensed to the Apache Software Foundation (ASF) under one or more
9  *  contributor license agreements.  See the NOTICE file distributed with
10  *  this work for additional information regarding copyright ownership.
11  *  The ASF licenses this file to You under the Apache License, Version 2.0
12  *  (the "License"); you may not use this file except in compliance with
13  *  the License.  You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  *  Unless required by applicable law or agreed to in writing, software
18  *  distributed under the License is distributed on an "AS IS" BASIS,
19  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  *  See the License for the specific language governing permissions and
21  *  limitations under the License.
22  * ====================================================================
23  *
24  * This software consists of voluntary contributions made by many
25  * individuals on behalf of the Apache Software Foundation.  For more
26  * information on the Apache Software Foundation, please see
27  * <http://www.apache.org/>.
28  *
29  */
30 
31 package org.apache.http.impl.conn;
32 
33 
34 import java.io.IOException;
35 import java.io.InterruptedIOException;
36 import java.net.InetAddress;
37 import java.net.Socket;
38 import java.util.concurrent.TimeUnit;
39 
40 import javax.net.ssl.SSLSocket;
41 import javax.net.ssl.SSLSession;
42 
43 import org.apache.http.HttpException;
44 import org.apache.http.HttpRequest;
45 import org.apache.http.HttpEntityEnclosingRequest;
46 import org.apache.http.HttpResponse;
47 import org.apache.http.HttpConnectionMetrics;
48 import org.apache.http.conn.OperatedClientConnection;
49 import org.apache.http.conn.ManagedClientConnection;
50 import org.apache.http.conn.ClientConnectionManager;
51 
52 
53 /**
54  * Abstract adapter from {@link OperatedClientConnection operated} to
55  * {@link ManagedClientConnection managed} client connections.
56  * Read and write methods are delegated to the wrapped connection.
57  * Operations affecting the connection state have to be implemented
58  * by derived classes. Operations for querying the connection state
59  * are delegated to the wrapped connection if there is one, or
60  * return a default value if there is none.
61  * <br/>
62  * This adapter tracks the checkpoints for reusable communication states,
63  * as indicated by {@link #markReusable markReusable} and queried by
64  * {@link #isMarkedReusable isMarkedReusable}.
65  * All send and receive operations will automatically clear the mark.
66  * <br/>
67  * Connection release calls are delegated to the connection manager,
68  * if there is one. {@link #abortConnection abortConnection} will
69  * clear the reusability mark first. The connection manager is
70  * expected to tolerate multiple calls to the release method.
71  *
72  * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
73  *
74  *
75  * <!-- empty lines to avoid svn diff problems -->
76  * @version   $Revision: 672969 $ $Date: 2008-06-30 18:09:50 -0700 (Mon, 30 Jun 2008) $
77  *
78  * @since 4.0
79  *
80  * @deprecated Please use {@link java.net.URL#openConnection} instead.
81  *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
82  *     for further details.
83  */
84 @Deprecated
85 public abstract class AbstractClientConnAdapter
86     implements ManagedClientConnection {
87 
88     /** Thread that requested this connection. */
89     private final Thread executionThread;
90 
91     /**
92      * The connection manager, if any.
93      * This attribute MUST NOT be final, so the adapter can be detached
94      * from the connection manager without keeping a hard reference there.
95      */
96     private volatile ClientConnectionManager connManager;
97 
98     /** The wrapped connection. */
99     private volatile OperatedClientConnection wrappedConnection;
100 
101     /** The reusability marker. */
102     private volatile boolean markedReusable;
103 
104     /** True if the connection has been aborted. */
105     private volatile boolean aborted;
106 
107     /** The duration this is valid for while idle (in ms). */
108     private volatile long duration;
109 
110     /**
111      * Creates a new connection adapter.
112      * The adapter is initially <i>not</i>
113      * {@link #isMarkedReusable marked} as reusable.
114      *
115      * @param mgr       the connection manager, or <code>null</code>
116      * @param conn      the connection to wrap, or <code>null</code>
117      */
AbstractClientConnAdapter(ClientConnectionManager mgr, OperatedClientConnection conn)118     protected AbstractClientConnAdapter(ClientConnectionManager mgr,
119                                         OperatedClientConnection conn) {
120         super();
121         executionThread = Thread.currentThread();
122         connManager = mgr;
123         wrappedConnection = conn;
124         markedReusable = false;
125         aborted = false;
126         duration = Long.MAX_VALUE;
127     } // <constructor>
128 
129 
130     /**
131      * Detaches this adapter from the wrapped connection.
132      * This adapter becomes useless.
133      */
detach()134     protected void detach() {
135         wrappedConnection = null;
136         connManager = null; // base class attribute
137         duration = Long.MAX_VALUE;
138     }
139 
getWrappedConnection()140     protected OperatedClientConnection getWrappedConnection() {
141         return wrappedConnection;
142     }
143 
getManager()144     protected ClientConnectionManager getManager() {
145         return connManager;
146     }
147 
148     /**
149      * Asserts that the connection has not been aborted.
150      *
151      * @throws InterruptedIOException   if the connection has been aborted
152      */
assertNotAborted()153     protected final void assertNotAborted() throws InterruptedIOException {
154         if (aborted) {
155             throw new InterruptedIOException("Connection has been shut down.");
156         }
157     }
158 
159     /**
160      * Asserts that there is a wrapped connection to delegate to.
161      *
162      * @throws IllegalStateException    if there is no wrapped connection
163      *                                  or connection has been aborted
164      */
assertValid( final OperatedClientConnection wrappedConn)165     protected final void assertValid(
166             final OperatedClientConnection wrappedConn) {
167         if (wrappedConn == null) {
168             throw new IllegalStateException("No wrapped connection.");
169         }
170     }
171 
172     // non-javadoc, see interface HttpConnection
isOpen()173     public boolean isOpen() {
174         OperatedClientConnection conn = getWrappedConnection();
175         if (conn == null)
176             return false;
177 
178         return conn.isOpen();
179     }
180 
181 
182     // non-javadoc, see interface HttpConnection
isStale()183     public boolean isStale() {
184         if (aborted)
185             return true;
186         OperatedClientConnection conn = getWrappedConnection();
187         if (conn == null)
188             return true;
189 
190         return conn.isStale();
191     }
192 
193 
194     // non-javadoc, see interface HttpConnection
setSocketTimeout(int timeout)195     public void setSocketTimeout(int timeout) {
196         OperatedClientConnection conn = getWrappedConnection();
197         assertValid(conn);
198         conn.setSocketTimeout(timeout);
199     }
200 
201 
202     // non-javadoc, see interface HttpConnection
getSocketTimeout()203     public int getSocketTimeout() {
204         OperatedClientConnection conn = getWrappedConnection();
205         assertValid(conn);
206         return conn.getSocketTimeout();
207     }
208 
209 
210     // non-javadoc, see interface HttpConnection
getMetrics()211     public HttpConnectionMetrics getMetrics() {
212         OperatedClientConnection conn = getWrappedConnection();
213         assertValid(conn);
214         return conn.getMetrics();
215     }
216 
217 
218     // non-javadoc, see interface HttpClientConnection
flush()219     public void flush()
220         throws IOException {
221 
222         assertNotAborted();
223         OperatedClientConnection conn = getWrappedConnection();
224         assertValid(conn);
225 
226         conn.flush();
227     }
228 
229 
230     // non-javadoc, see interface HttpClientConnection
isResponseAvailable(int timeout)231     public boolean isResponseAvailable(int timeout)
232         throws IOException {
233 
234         assertNotAborted();
235         OperatedClientConnection conn = getWrappedConnection();
236         assertValid(conn);
237 
238         return conn.isResponseAvailable(timeout);
239     }
240 
241 
242     // non-javadoc, see interface HttpClientConnection
receiveResponseEntity(HttpResponse response)243     public void receiveResponseEntity(HttpResponse response)
244         throws HttpException, IOException {
245 
246         assertNotAborted();
247         OperatedClientConnection conn = getWrappedConnection();
248         assertValid(conn);
249 
250         unmarkReusable();
251         conn.receiveResponseEntity(response);
252     }
253 
254 
255     // non-javadoc, see interface HttpClientConnection
receiveResponseHeader()256     public HttpResponse receiveResponseHeader()
257         throws HttpException, IOException {
258 
259         assertNotAborted();
260         OperatedClientConnection conn = getWrappedConnection();
261         assertValid(conn);
262 
263         unmarkReusable();
264         return conn.receiveResponseHeader();
265     }
266 
267 
268     // non-javadoc, see interface HttpClientConnection
sendRequestEntity(HttpEntityEnclosingRequest request)269     public void sendRequestEntity(HttpEntityEnclosingRequest request)
270         throws HttpException, IOException {
271 
272         assertNotAborted();
273         OperatedClientConnection conn = getWrappedConnection();
274         assertValid(conn);
275 
276         unmarkReusable();
277         conn.sendRequestEntity(request);
278     }
279 
280 
281     // non-javadoc, see interface HttpClientConnection
sendRequestHeader(HttpRequest request)282     public void sendRequestHeader(HttpRequest request)
283         throws HttpException, IOException {
284 
285         assertNotAborted();
286         OperatedClientConnection conn = getWrappedConnection();
287         assertValid(conn);
288 
289         unmarkReusable();
290         conn.sendRequestHeader(request);
291     }
292 
293 
294     // non-javadoc, see interface HttpInetConnection
getLocalAddress()295     public InetAddress getLocalAddress() {
296         OperatedClientConnection conn = getWrappedConnection();
297         assertValid(conn);
298         return conn.getLocalAddress();
299     }
300 
301     // non-javadoc, see interface HttpInetConnection
getLocalPort()302     public int getLocalPort() {
303         OperatedClientConnection conn = getWrappedConnection();
304         assertValid(conn);
305         return conn.getLocalPort();
306     }
307 
308 
309     // non-javadoc, see interface HttpInetConnection
getRemoteAddress()310     public InetAddress getRemoteAddress() {
311         OperatedClientConnection conn = getWrappedConnection();
312         assertValid(conn);
313         return conn.getRemoteAddress();
314     }
315 
316     // non-javadoc, see interface HttpInetConnection
getRemotePort()317     public int getRemotePort() {
318         OperatedClientConnection conn = getWrappedConnection();
319         assertValid(conn);
320         return conn.getRemotePort();
321     }
322 
323     // non-javadoc, see interface ManagedClientConnection
isSecure()324     public boolean isSecure() {
325         OperatedClientConnection conn = getWrappedConnection();
326         assertValid(conn);
327         return conn.isSecure();
328     }
329 
330     // non-javadoc, see interface ManagedClientConnection
getSSLSession()331     public SSLSession getSSLSession() {
332         OperatedClientConnection conn = getWrappedConnection();
333         assertValid(conn);
334         if (!isOpen())
335             return null;
336 
337         SSLSession result = null;
338         Socket    sock    = conn.getSocket();
339         if (sock instanceof SSLSocket) {
340             result = ((SSLSocket)sock).getSession();
341         }
342         return result;
343     }
344 
345     // non-javadoc, see interface ManagedClientConnection
markReusable()346     public void markReusable() {
347         markedReusable = true;
348     }
349 
350     // non-javadoc, see interface ManagedClientConnection
unmarkReusable()351     public void unmarkReusable() {
352         markedReusable = false;
353     }
354 
355     // non-javadoc, see interface ManagedClientConnection
isMarkedReusable()356     public boolean isMarkedReusable() {
357         return markedReusable;
358     }
359 
setIdleDuration(long duration, TimeUnit unit)360     public void setIdleDuration(long duration, TimeUnit unit) {
361         if(duration > 0) {
362             this.duration = unit.toMillis(duration);
363         } else {
364             this.duration = -1;
365         }
366     }
367 
368     // non-javadoc, see interface ConnectionReleaseTrigger
releaseConnection()369     public void releaseConnection() {
370         if (connManager != null) {
371             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
372         }
373     }
374 
375     // non-javadoc, see interface ConnectionReleaseTrigger
abortConnection()376     public void abortConnection() {
377         if (aborted) {
378             return;
379         }
380         aborted = true;
381         unmarkReusable();
382         try {
383             shutdown();
384         } catch (IOException ignore) {
385         }
386         // Usually #abortConnection() is expected to be called from
387         // a helper thread in order to unblock the main execution thread
388         // blocked in an I/O operation. It may be unsafe to call
389         // #releaseConnection() from the helper thread, so we have to rely
390         // on an IOException thrown by the closed socket on the main thread
391         // to trigger the release of the connection back to the
392         // connection manager.
393         //
394         // However, if this method is called from the main execution thread
395         // it should be safe to release the connection immediately. Besides,
396         // this also helps ensure the connection gets released back to the
397         // manager if #abortConnection() is called from the main execution
398         // thread while there is no blocking I/O operation.
399         if (executionThread.equals(Thread.currentThread())) {
400             releaseConnection();
401         }
402     }
403 
404 } // class AbstractClientConnAdapter
405