Home | History | Annotate | Download | only in conn
      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      */
    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      */
    134     protected void detach() {
    135         wrappedConnection = null;
    136         connManager = null; // base class attribute
    137         duration = Long.MAX_VALUE;
    138     }
    139 
    140     protected OperatedClientConnection getWrappedConnection() {
    141         return wrappedConnection;
    142     }
    143 
    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      */
    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      */
    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
    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
    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
    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
    203     public int getSocketTimeout() {
    204         OperatedClientConnection conn = getWrappedConnection();
    205         assertValid(conn);
    206         return conn.getSocketTimeout();
    207     }
    208 
    209 
    210     // non-javadoc, see interface HttpConnection
    211     public HttpConnectionMetrics getMetrics() {
    212         OperatedClientConnection conn = getWrappedConnection();
    213         assertValid(conn);
    214         return conn.getMetrics();
    215     }
    216 
    217 
    218     // non-javadoc, see interface HttpClientConnection
    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
    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
    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
    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
    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
    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
    295     public InetAddress getLocalAddress() {
    296         OperatedClientConnection conn = getWrappedConnection();
    297         assertValid(conn);
    298         return conn.getLocalAddress();
    299     }
    300 
    301     // non-javadoc, see interface HttpInetConnection
    302     public int getLocalPort() {
    303         OperatedClientConnection conn = getWrappedConnection();
    304         assertValid(conn);
    305         return conn.getLocalPort();
    306     }
    307 
    308 
    309     // non-javadoc, see interface HttpInetConnection
    310     public InetAddress getRemoteAddress() {
    311         OperatedClientConnection conn = getWrappedConnection();
    312         assertValid(conn);
    313         return conn.getRemoteAddress();
    314     }
    315 
    316     // non-javadoc, see interface HttpInetConnection
    317     public int getRemotePort() {
    318         OperatedClientConnection conn = getWrappedConnection();
    319         assertValid(conn);
    320         return conn.getRemotePort();
    321     }
    322 
    323     // non-javadoc, see interface ManagedClientConnection
    324     public boolean isSecure() {
    325         OperatedClientConnection conn = getWrappedConnection();
    326         assertValid(conn);
    327         return conn.isSecure();
    328     }
    329 
    330     // non-javadoc, see interface ManagedClientConnection
    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
    346     public void markReusable() {
    347         markedReusable = true;
    348     }
    349 
    350     // non-javadoc, see interface ManagedClientConnection
    351     public void unmarkReusable() {
    352         markedReusable = false;
    353     }
    354 
    355     // non-javadoc, see interface ManagedClientConnection
    356     public boolean isMarkedReusable() {
    357         return markedReusable;
    358     }
    359 
    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
    369     public void releaseConnection() {
    370         if (connManager != null) {
    371             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
    372         }
    373     }
    374 
    375     // non-javadoc, see interface ConnectionReleaseTrigger
    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