Home | History | Annotate | Download | only in tsccm
      1 /*
      2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/tsccm/ThreadSafeClientConnManager.java $
      3  * $Revision: 673450 $
      4  * $Date: 2008-07-02 10:35:05 -0700 (Wed, 02 Jul 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.tsccm;
     32 
     33 import java.io.IOException;
     34 import java.net.Socket;
     35 import java.util.concurrent.TimeUnit;
     36 
     37 import android.net.TrafficStats;
     38 import org.apache.commons.logging.Log;
     39 import org.apache.commons.logging.LogFactory;
     40 import org.apache.http.conn.routing.HttpRoute;
     41 import org.apache.http.conn.scheme.SchemeRegistry;
     42 import org.apache.http.conn.ClientConnectionManager;
     43 import org.apache.http.conn.ClientConnectionOperator;
     44 import org.apache.http.conn.ClientConnectionRequest;
     45 import org.apache.http.conn.ConnectionPoolTimeoutException;
     46 import org.apache.http.conn.ManagedClientConnection;
     47 import org.apache.http.conn.OperatedClientConnection;
     48 import org.apache.http.params.HttpParams;
     49 import org.apache.http.impl.conn.DefaultClientConnectionOperator;
     50 
     51 
     52 
     53 /**
     54  * Manages a pool of {@link OperatedClientConnection client connections}.
     55  * <p>
     56  * This class is derived from <code>MultiThreadedHttpConnectionManager</code>
     57  * in HttpClient 3. See there for original authors.
     58  * </p>
     59  *
     60  * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
     61  * @author <a href="mailto:becke (at) u.washington.edu">Michael Becke</a>
     62  *
     63  *
     64  * <!-- empty lines to avoid svn diff problems -->
     65  * @version $Revision: 673450 $ $Date: 2008-07-02 10:35:05 -0700 (Wed, 02 Jul 2008) $
     66  *
     67  * @since 4.0
     68  *
     69  * @deprecated Please use {@link java.net.URL#openConnection} instead.
     70  *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
     71  *     for further details.
     72  */
     73 @Deprecated
     74 public class ThreadSafeClientConnManager implements ClientConnectionManager {
     75 
     76     private final Log log = LogFactory.getLog(getClass());
     77 
     78     /** The schemes supported by this connection manager. */
     79     protected SchemeRegistry schemeRegistry;
     80 
     81     /** The pool of connections being managed. */
     82     protected final AbstractConnPool connectionPool;
     83 
     84     /** The operator for opening and updating connections. */
     85     protected ClientConnectionOperator connOperator;
     86 
     87 
     88 
     89     /**
     90      * Creates a new thread safe connection manager.
     91      *
     92      * @param params    the parameters for this manager
     93      * @param schreg    the scheme registry
     94      */
     95     public ThreadSafeClientConnManager(HttpParams params,
     96                                        SchemeRegistry schreg) {
     97 
     98         if (params == null) {
     99             throw new IllegalArgumentException("HTTP parameters may not be null");
    100         }
    101         this.schemeRegistry = schreg;
    102         this.connOperator   = createConnectionOperator(schreg);
    103         this.connectionPool = createConnectionPool(params);
    104 
    105     } // <constructor>
    106 
    107 
    108     @Override
    109     protected void finalize() throws Throwable {
    110         shutdown();
    111         super.finalize();
    112     }
    113 
    114 
    115     /**
    116      * Hook for creating the connection pool.
    117      *
    118      * @return  the connection pool to use
    119      */
    120     protected AbstractConnPool createConnectionPool(final HttpParams params) {
    121 
    122         AbstractConnPool acp = new ConnPoolByRoute(connOperator, params);
    123         boolean conngc = true; //@@@ check parameters to decide
    124         if (conngc) {
    125             acp.enableConnectionGC();
    126         }
    127         return acp;
    128     }
    129 
    130 
    131     /**
    132      * Hook for creating the connection operator.
    133      * It is called by the constructor.
    134      * Derived classes can override this method to change the
    135      * instantiation of the operator.
    136      * The default implementation here instantiates
    137      * {@link DefaultClientConnectionOperator DefaultClientConnectionOperator}.
    138      *
    139      * @param schreg    the scheme registry to use, or <code>null</code>
    140      *
    141      * @return  the connection operator to use
    142      */
    143     protected ClientConnectionOperator
    144         createConnectionOperator(SchemeRegistry schreg) {
    145 
    146         return new DefaultClientConnectionOperator(schreg);
    147     }
    148 
    149 
    150     // non-javadoc, see interface ClientConnectionManager
    151     public SchemeRegistry getSchemeRegistry() {
    152         return this.schemeRegistry;
    153     }
    154 
    155 
    156     public ClientConnectionRequest requestConnection(
    157             final HttpRoute route,
    158             final Object state) {
    159 
    160         final PoolEntryRequest poolRequest = connectionPool.requestPoolEntry(
    161                 route, state);
    162 
    163         return new ClientConnectionRequest() {
    164 
    165             public void abortRequest() {
    166                 poolRequest.abortRequest();
    167             }
    168 
    169             public ManagedClientConnection getConnection(
    170                     long timeout, TimeUnit tunit) throws InterruptedException,
    171                     ConnectionPoolTimeoutException {
    172                 if (route == null) {
    173                     throw new IllegalArgumentException("Route may not be null.");
    174                 }
    175 
    176                 if (log.isDebugEnabled()) {
    177                     log.debug("ThreadSafeClientConnManager.getConnection: "
    178                         + route + ", timeout = " + timeout);
    179                 }
    180 
    181                 BasicPoolEntry entry = poolRequest.getPoolEntry(timeout, tunit);
    182                 // BEGIN android-changed
    183                 // When using a recycled Socket, we need to re-tag it with any
    184                 // updated statistics options.
    185                 try {
    186                     final Socket socket = entry.getConnection().getSocket();
    187                     if (socket != null) {
    188                         TrafficStats.tagSocket(socket);
    189                     }
    190                 } catch (IOException iox) {
    191                     log.debug("Problem tagging socket.", iox);
    192                 }
    193                 // END android-changed
    194                 return new BasicPooledConnAdapter(ThreadSafeClientConnManager.this, entry);
    195             }
    196 
    197         };
    198 
    199     }
    200 
    201 
    202     // non-javadoc, see interface ClientConnectionManager
    203     public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
    204 
    205         if (!(conn instanceof BasicPooledConnAdapter)) {
    206             throw new IllegalArgumentException
    207                 ("Connection class mismatch, " +
    208                  "connection not obtained from this manager.");
    209         }
    210         BasicPooledConnAdapter hca = (BasicPooledConnAdapter) conn;
    211         if ((hca.getPoolEntry() != null) && (hca.getManager() != this)) {
    212             throw new IllegalArgumentException
    213                 ("Connection not obtained from this manager.");
    214         }
    215 
    216         try {
    217             // BEGIN android-changed
    218             // When recycling a Socket, we un-tag it to avoid collecting
    219             // statistics from future users.
    220             final BasicPoolEntry entry = (BasicPoolEntry) hca.getPoolEntry();
    221             final Socket socket = entry.getConnection().getSocket();
    222             if (socket != null) {
    223                 TrafficStats.untagSocket(socket);
    224             }
    225             // END android-changed
    226 
    227             // make sure that the response has been read completely
    228             if (hca.isOpen() && !hca.isMarkedReusable()) {
    229                 if (log.isDebugEnabled()) {
    230                     log.debug
    231                         ("Released connection open but not marked reusable.");
    232                 }
    233                 // In MTHCM, there would be a call to
    234                 // SimpleHttpConnectionManager.finishLastResponse(conn);
    235                 // Consuming the response is handled outside in 4.0.
    236 
    237                 // make sure this connection will not be re-used
    238                 // Shut down rather than close, we might have gotten here
    239                 // because of a shutdown trigger.
    240                 // Shutdown of the adapter also clears the tracked route.
    241                 hca.shutdown();
    242             }
    243         } catch (IOException iox) {
    244             //@@@ log as warning? let pass?
    245             if (log.isDebugEnabled())
    246                 log.debug("Exception shutting down released connection.",
    247                           iox);
    248         } finally {
    249             BasicPoolEntry entry = (BasicPoolEntry) hca.getPoolEntry();
    250             boolean reusable = hca.isMarkedReusable();
    251             hca.detach();
    252             if (entry != null) {
    253                 connectionPool.freeEntry(entry, reusable, validDuration, timeUnit);
    254             }
    255         }
    256     }
    257 
    258 
    259     // non-javadoc, see interface ClientConnectionManager
    260     public void shutdown() {
    261         connectionPool.shutdown();
    262     }
    263 
    264 
    265     /**
    266      * Gets the total number of pooled connections for the given route.
    267      * This is the total number of connections that have been created and
    268      * are still in use by this connection manager for the route.
    269      * This value will not exceed the maximum number of connections per host.
    270      *
    271      * @param route     the route in question
    272      *
    273      * @return  the total number of pooled connections for that route
    274      */
    275     public int getConnectionsInPool(HttpRoute route) {
    276         return ((ConnPoolByRoute)connectionPool).getConnectionsInPool(
    277                 route);
    278     }
    279 
    280 
    281     /**
    282      * Gets the total number of pooled connections.  This is the total number of
    283      * connections that have been created and are still in use by this connection
    284      * manager.  This value will not exceed the maximum number of connections
    285      * in total.
    286      *
    287      * @return the total number of pooled connections
    288      */
    289     public int getConnectionsInPool() {
    290         synchronized (connectionPool) {
    291             return connectionPool.numConnections; //@@@
    292         }
    293     }
    294 
    295 
    296     // non-javadoc, see interface ClientConnectionManager
    297     public void closeIdleConnections(long idleTimeout, TimeUnit tunit) {
    298         // combine these two in a single call?
    299         connectionPool.closeIdleConnections(idleTimeout, tunit);
    300         connectionPool.deleteClosedConnections();
    301     }
    302 
    303     public void closeExpiredConnections() {
    304         connectionPool.closeExpiredConnections();
    305         connectionPool.deleteClosedConnections();
    306     }
    307 
    308 
    309 } // class ThreadSafeClientConnManager
    310 
    311