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/AbstractPoolEntry.java $
      3  * $Revision: 658775 $
      4  * $Date: 2008-05-21 10:30:45 -0700 (Wed, 21 May 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 
     36 import org.apache.http.HttpHost;
     37 import org.apache.http.params.HttpParams;
     38 import org.apache.http.protocol.HttpContext;
     39 import org.apache.http.conn.routing.HttpRoute;
     40 import org.apache.http.conn.routing.RouteTracker;
     41 import org.apache.http.conn.ClientConnectionOperator;
     42 import org.apache.http.conn.OperatedClientConnection;
     43 
     44 
     45 
     46 /**
     47  * A pool entry for use by connection manager implementations.
     48  * Pool entries work in conjunction with an
     49  * {@link AbstractClientConnAdapter adapter}.
     50  * The adapter is handed out to applications that obtain a connection.
     51  * The pool entry stores the underlying connection and tracks the
     52  * {@link HttpRoute route} established.
     53  * The adapter delegates methods for establishing the route to
     54  * it's pool entry.
     55  * <br/>
     56  * If the managed connections is released or revoked, the adapter
     57  * gets disconnected, but the pool entry still contains the
     58  * underlying connection and the established route.
     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: 658775 $
     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 abstract class AbstractPoolEntry {
     75 
     76     /** The connection operator. */
     77     protected final ClientConnectionOperator connOperator;
     78 
     79     /** The underlying connection being pooled or used. */
     80     protected final OperatedClientConnection connection;
     81 
     82     /** The route for which this entry gets allocated. */
     83     //@@@ currently accessed from connection manager(s) as attribute
     84     //@@@ avoid that, derived classes should decide whether update is allowed
     85     //@@@ SCCM: yes, TSCCM: no
     86     protected volatile HttpRoute route;
     87 
     88     /** Connection state object */
     89     protected volatile Object state;
     90 
     91     /** The tracked route, or <code>null</code> before tracking starts. */
     92     protected volatile RouteTracker tracker;
     93 
     94 
     95     /**
     96      * Creates a new pool entry.
     97      *
     98      * @param connOperator     the Connection Operator for this entry
     99      * @param route   the planned route for the connection,
    100      *                or <code>null</code>
    101      */
    102     protected AbstractPoolEntry(ClientConnectionOperator connOperator,
    103                                 HttpRoute route) {
    104         super();
    105         if (connOperator == null) {
    106             throw new IllegalArgumentException("Connection operator may not be null");
    107         }
    108         this.connOperator = connOperator;
    109         this.connection = connOperator.createConnection();
    110         this.route = route;
    111         this.tracker = null;
    112     }
    113 
    114     /**
    115      * Returns the state object associated with this pool entry.
    116      *
    117      * @return The state object
    118      */
    119     public Object getState() {
    120         return state;
    121     }
    122 
    123     /**
    124      * Assigns a state object to this pool entry.
    125      *
    126      * @param state The state object
    127      */
    128     public void setState(final Object state) {
    129         this.state = state;
    130     }
    131 
    132     /**
    133      * Opens the underlying connection.
    134      *
    135      * @param route         the route along which to open the connection
    136      * @param context       the context for opening the connection
    137      * @param params        the parameters for opening the connection
    138      *
    139      * @throws IOException  in case of a problem
    140      */
    141     public void open(HttpRoute route,
    142                      HttpContext context, HttpParams params)
    143         throws IOException {
    144 
    145         if (route == null) {
    146             throw new IllegalArgumentException
    147                 ("Route must not be null.");
    148         }
    149         //@@@ is context allowed to be null? depends on operator?
    150         if (params == null) {
    151             throw new IllegalArgumentException
    152                 ("Parameters must not be null.");
    153         }
    154         if ((this.tracker != null) && this.tracker.isConnected()) {
    155             throw new IllegalStateException("Connection already open.");
    156         }
    157 
    158         // - collect the arguments
    159         // - call the operator
    160         // - update the tracking data
    161         // In this order, we can be sure that only a successful
    162         // opening of the connection will be tracked.
    163 
    164         //@@@ verify route against planned route?
    165 
    166         this.tracker = new RouteTracker(route);
    167         final HttpHost proxy  = route.getProxyHost();
    168 
    169         connOperator.openConnection
    170             (this.connection,
    171              (proxy != null) ? proxy : route.getTargetHost(),
    172              route.getLocalAddress(),
    173              context, params);
    174 
    175         RouteTracker localTracker = tracker; // capture volatile
    176 
    177         // If this tracker was reset while connecting,
    178         // fail early.
    179         if (localTracker == null) {
    180             throw new IOException("Request aborted");
    181         }
    182 
    183         if (proxy == null) {
    184             localTracker.connectTarget(this.connection.isSecure());
    185         } else {
    186             localTracker.connectProxy(proxy, this.connection.isSecure());
    187         }
    188 
    189     } // open
    190 
    191 
    192     /**
    193      * Tracks tunnelling of the connection to the target.
    194      * The tunnel has to be established outside by sending a CONNECT
    195      * request to the (last) proxy.
    196      *
    197      * @param secure    <code>true</code> if the tunnel should be
    198      *                  considered secure, <code>false</code> otherwise
    199      * @param params    the parameters for tunnelling the connection
    200      *
    201      * @throws IOException  in case of a problem
    202      */
    203     public void tunnelTarget(boolean secure, HttpParams params)
    204         throws IOException {
    205 
    206         if (params == null) {
    207             throw new IllegalArgumentException
    208                 ("Parameters must not be null.");
    209         }
    210 
    211         //@@@ check for proxy in planned route?
    212         if ((this.tracker == null) || !this.tracker.isConnected()) {
    213             throw new IllegalStateException("Connection not open.");
    214         }
    215         if (this.tracker.isTunnelled()) {
    216             throw new IllegalStateException
    217                 ("Connection is already tunnelled.");
    218         }
    219 
    220         // LOG.debug?
    221 
    222         this.connection.update(null, tracker.getTargetHost(),
    223                                secure, params);
    224         this.tracker.tunnelTarget(secure);
    225 
    226     } // tunnelTarget
    227 
    228 
    229     /**
    230      * Tracks tunnelling of the connection to a chained proxy.
    231      * The tunnel has to be established outside by sending a CONNECT
    232      * request to the previous proxy.
    233      *
    234      * @param next      the proxy to which the tunnel was established.
    235      *  See {@link org.apache.http.conn.ManagedClientConnection#tunnelProxy
    236      *                                  ManagedClientConnection.tunnelProxy}
    237      *                  for details.
    238      * @param secure    <code>true</code> if the tunnel should be
    239      *                  considered secure, <code>false</code> otherwise
    240      * @param params    the parameters for tunnelling the connection
    241      *
    242      * @throws IOException  in case of a problem
    243      */
    244     public void tunnelProxy(HttpHost next, boolean secure, HttpParams params)
    245         throws IOException {
    246 
    247         if (next == null) {
    248             throw new IllegalArgumentException
    249                 ("Next proxy must not be null.");
    250         }
    251         if (params == null) {
    252             throw new IllegalArgumentException
    253                 ("Parameters must not be null.");
    254         }
    255 
    256         //@@@ check for proxy in planned route?
    257         if ((this.tracker == null) || !this.tracker.isConnected()) {
    258             throw new IllegalStateException("Connection not open.");
    259         }
    260 
    261         // LOG.debug?
    262 
    263         this.connection.update(null, next, secure, params);
    264         this.tracker.tunnelProxy(next, secure);
    265 
    266     } // tunnelProxy
    267 
    268 
    269     /**
    270      * Layers a protocol on top of an established tunnel.
    271      *
    272      * @param context   the context for layering
    273      * @param params    the parameters for layering
    274      *
    275      * @throws IOException  in case of a problem
    276      */
    277     public void layerProtocol(HttpContext context, HttpParams params)
    278         throws IOException {
    279 
    280         //@@@ is context allowed to be null? depends on operator?
    281         if (params == null) {
    282             throw new IllegalArgumentException
    283                 ("Parameters must not be null.");
    284         }
    285 
    286         if ((this.tracker == null) || !this.tracker.isConnected()) {
    287             throw new IllegalStateException("Connection not open.");
    288         }
    289         if (!this.tracker.isTunnelled()) {
    290             //@@@ allow this?
    291             throw new IllegalStateException
    292                 ("Protocol layering without a tunnel not supported.");
    293         }
    294         if (this.tracker.isLayered()) {
    295             throw new IllegalStateException
    296                 ("Multiple protocol layering not supported.");
    297         }
    298 
    299         // - collect the arguments
    300         // - call the operator
    301         // - update the tracking data
    302         // In this order, we can be sure that only a successful
    303         // layering on top of the connection will be tracked.
    304 
    305         final HttpHost target = tracker.getTargetHost();
    306 
    307         connOperator.updateSecureConnection(this.connection, target,
    308                                              context, params);
    309 
    310         this.tracker.layerProtocol(this.connection.isSecure());
    311 
    312     } // layerProtocol
    313 
    314 
    315     /**
    316      * Shuts down the entry.
    317      *
    318      * If {@link #open(HttpRoute, HttpContext, HttpParams)} is in progress,
    319      * this will cause that open to possibly throw an {@link IOException}.
    320      */
    321     protected void shutdownEntry() {
    322         tracker = null;
    323     }
    324 
    325 
    326 } // class AbstractPoolEntry
    327 
    328