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/DefaultClientConnectionOperator.java $
      3  * $Revision: 652193 $
      4  * $Date: 2008-04-29 17:10:36 -0700 (Tue, 29 Apr 2008) $
      5  *
      6  * ====================================================================
      7  * Licensed to the Apache Software Foundation (ASF) under one
      8  * or more contributor license agreements.  See the NOTICE file
      9  * distributed with this work for additional information
     10  * regarding copyright ownership.  The ASF licenses this file
     11  * to you under the Apache License, Version 2.0 (the
     12  * "License"); you may not use this file except in compliance
     13  * with 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,
     18  * software distributed under the License is distributed on an
     19  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     20  * KIND, either express or implied.  See the License for the
     21  * specific language governing permissions and limitations
     22  * under the License.
     23  * ====================================================================
     24  *
     25  * This software consists of voluntary contributions made by many
     26  * individuals on behalf of the Apache Software Foundation.  For more
     27  * information on the Apache Software Foundation, please see
     28  * <http://www.apache.org/>.
     29  *
     30  */
     31 
     32 package org.apache.http.impl.conn;
     33 
     34 import java.io.IOException;
     35 import java.net.ConnectException;
     36 import java.net.Socket;
     37 import java.net.InetAddress;
     38 
     39 import java.net.SocketException;
     40 import org.apache.http.HttpHost;
     41 import org.apache.http.params.HttpParams;
     42 import org.apache.http.params.HttpConnectionParams;
     43 import org.apache.http.protocol.HttpContext;
     44 
     45 import org.apache.http.conn.HttpHostConnectException;
     46 import org.apache.http.conn.OperatedClientConnection;
     47 import org.apache.http.conn.ClientConnectionOperator;
     48 import org.apache.http.conn.ConnectTimeoutException;
     49 import org.apache.http.conn.scheme.LayeredSocketFactory;
     50 import org.apache.http.conn.scheme.PlainSocketFactory;
     51 import org.apache.http.conn.scheme.Scheme;
     52 import org.apache.http.conn.scheme.SchemeRegistry;
     53 import org.apache.http.conn.scheme.SocketFactory;
     54 
     55 
     56 /**
     57  * Default implementation of a
     58  * {@link ClientConnectionOperator ClientConnectionOperator}.
     59  * It uses a {@link SchemeRegistry SchemeRegistry} to look up
     60  * {@link SocketFactory SocketFactory} objects.
     61  *
     62  * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
     63  *
     64  *
     65  * <!-- empty lines to avoid svn diff problems -->
     66  * @version   $Revision: 652193 $ $Date: 2008-04-29 17:10:36 -0700 (Tue, 29 Apr 2008) $
     67  *
     68  * @since 4.0
     69  *
     70  * @deprecated Please use {@link java.net.URL#openConnection} instead.
     71  *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
     72  *     for further details.
     73  */
     74 @Deprecated
     75 public class DefaultClientConnectionOperator
     76     implements ClientConnectionOperator {
     77 
     78     private static final PlainSocketFactory staticPlainSocketFactory = new PlainSocketFactory();
     79 
     80     /** The scheme registry for looking up socket factories. */
     81     protected SchemeRegistry schemeRegistry;
     82 
     83 
     84     /**
     85      * Creates a new client connection operator for the given scheme registry.
     86      *
     87      * @param schemes   the scheme registry
     88      */
     89     public DefaultClientConnectionOperator(SchemeRegistry schemes) {
     90         if (schemes == null) {
     91             throw new IllegalArgumentException
     92                 ("Scheme registry must not be null.");
     93         }
     94         schemeRegistry = schemes;
     95     }
     96 
     97 
     98     // non-javadoc, see interface ClientConnectionOperator
     99     public OperatedClientConnection createConnection() {
    100         return new DefaultClientConnection();
    101     }
    102 
    103 
    104     // non-javadoc, see interface ClientConnectionOperator
    105     public void openConnection(OperatedClientConnection conn,
    106                                HttpHost target,
    107                                InetAddress local,
    108                                HttpContext context,
    109                                HttpParams params)
    110         throws IOException {
    111 
    112         if (conn == null) {
    113             throw new IllegalArgumentException
    114                 ("Connection must not be null.");
    115         }
    116         if (target == null) {
    117             throw new IllegalArgumentException
    118                 ("Target host must not be null.");
    119         }
    120         // local address may be null
    121         //@@@ is context allowed to be null?
    122         if (params == null) {
    123             throw new IllegalArgumentException
    124                 ("Parameters must not be null.");
    125         }
    126         if (conn.isOpen()) {
    127             throw new IllegalArgumentException
    128                 ("Connection must not be open.");
    129         }
    130 
    131         final Scheme schm = schemeRegistry.getScheme(target.getSchemeName());
    132         final SocketFactory sf = schm.getSocketFactory();
    133         final SocketFactory plain_sf;
    134         final LayeredSocketFactory layered_sf;
    135         if (sf instanceof LayeredSocketFactory) {
    136             plain_sf = staticPlainSocketFactory;
    137             layered_sf = (LayeredSocketFactory)sf;
    138         } else {
    139             plain_sf = sf;
    140             layered_sf = null;
    141         }
    142         InetAddress[] addresses = InetAddress.getAllByName(target.getHostName());
    143 
    144         for (int i = 0; i < addresses.length; ++i) {
    145             Socket sock = plain_sf.createSocket();
    146             conn.opening(sock, target);
    147 
    148             try {
    149                 Socket connsock = plain_sf.connectSocket(sock,
    150                     addresses[i].getHostAddress(),
    151                     schm.resolvePort(target.getPort()),
    152                     local, 0, params);
    153                 if (sock != connsock) {
    154                     sock = connsock;
    155                     conn.opening(sock, target);
    156                 }
    157                 /*
    158                  * prepareSocket is called on the just connected
    159                  * socket before the creation of the layered socket to
    160                  * ensure that desired socket options such as
    161                  * TCP_NODELAY, SO_RCVTIMEO, SO_LINGER will be set
    162                  * before any I/O is performed on the socket. This
    163                  * happens in the common case as
    164                  * SSLSocketFactory.createSocket performs hostname
    165                  * verification which requires that SSL handshaking be
    166                  * performed.
    167                  */
    168                 prepareSocket(sock, context, params);
    169                 if (layered_sf != null) {
    170                     Socket layeredsock = layered_sf.createSocket(sock,
    171                         target.getHostName(),
    172                         schm.resolvePort(target.getPort()),
    173                         true);
    174                     if (layeredsock != sock) {
    175                         conn.opening(layeredsock, target);
    176                     }
    177                     conn.openCompleted(sf.isSecure(layeredsock), params);
    178                 } else {
    179                     conn.openCompleted(sf.isSecure(sock), params);
    180                 }
    181                 break;
    182             // BEGIN android-changed
    183             //       catch SocketException to cover any kind of connect failure
    184             } catch (SocketException ex) {
    185                 if (i == addresses.length - 1) {
    186                     final ConnectException cause;
    187                     if (ex instanceof ConnectException) {
    188                         cause = (ConnectException) ex;
    189                     } else {
    190                         cause = new ConnectException(ex.getMessage());
    191                         cause.initCause(ex);
    192                     }
    193                     throw new HttpHostConnectException(target, cause);
    194                 }
    195             // END android-changed
    196             } catch (ConnectTimeoutException ex) {
    197                 if (i == addresses.length - 1) {
    198                     throw ex;
    199                 }
    200             }
    201         }
    202     } // openConnection
    203 
    204 
    205     // non-javadoc, see interface ClientConnectionOperator
    206     public void updateSecureConnection(OperatedClientConnection conn,
    207                                        HttpHost target,
    208                                        HttpContext context,
    209                                        HttpParams params)
    210         throws IOException {
    211 
    212 
    213         if (conn == null) {
    214             throw new IllegalArgumentException
    215                 ("Connection must not be null.");
    216         }
    217         if (target == null) {
    218             throw new IllegalArgumentException
    219                 ("Target host must not be null.");
    220         }
    221         //@@@ is context allowed to be null?
    222         if (params == null) {
    223             throw new IllegalArgumentException
    224                 ("Parameters must not be null.");
    225         }
    226         if (!conn.isOpen()) {
    227             throw new IllegalArgumentException
    228                 ("Connection must be open.");
    229         }
    230 
    231         final Scheme schm = schemeRegistry.getScheme(target.getSchemeName());
    232         if (!(schm.getSocketFactory() instanceof LayeredSocketFactory)) {
    233             throw new IllegalArgumentException
    234                 ("Target scheme (" + schm.getName() +
    235                  ") must have layered socket factory.");
    236         }
    237 
    238         final LayeredSocketFactory lsf = (LayeredSocketFactory) schm.getSocketFactory();
    239         final Socket sock;
    240         try {
    241             sock = lsf.createSocket
    242                 (conn.getSocket(), target.getHostName(), schm.resolvePort(target.getPort()), true);
    243         } catch (ConnectException ex) {
    244             throw new HttpHostConnectException(target, ex);
    245         }
    246         prepareSocket(sock, context, params);
    247         conn.update(sock, target, lsf.isSecure(sock), params);
    248         //@@@ error handling: close the layered socket in case of exception?
    249 
    250     } // updateSecureConnection
    251 
    252 
    253     /**
    254      * Performs standard initializations on a newly created socket.
    255      *
    256      * @param sock      the socket to prepare
    257      * @param context   the context for the connection
    258      * @param params    the parameters from which to prepare the socket
    259      *
    260      * @throws IOException      in case of an IO problem
    261      */
    262     protected void prepareSocket(Socket sock, HttpContext context,
    263                                  HttpParams params)
    264         throws IOException {
    265 
    266         // context currently not used, but derived classes may need it
    267         //@@@ is context allowed to be null?
    268 
    269         sock.setTcpNoDelay(HttpConnectionParams.getTcpNoDelay(params));
    270         sock.setSoTimeout(HttpConnectionParams.getSoTimeout(params));
    271 
    272         int linger = HttpConnectionParams.getLinger(params);
    273         if (linger >= 0) {
    274             sock.setSoLinger(linger > 0, linger);
    275         }
    276 
    277     } // prepareSocket
    278 
    279 
    280 } // class DefaultClientConnectionOperator
    281