Home | History | Annotate | Download | only in routing
      1 /*
      2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/routing/HttpRoute.java $
      3  * $Revision: 653041 $
      4  * $Date: 2008-05-03 03:39:28 -0700 (Sat, 03 May 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.conn.routing;
     33 
     34 import java.net.InetAddress;
     35 
     36 import org.apache.http.HttpHost;
     37 
     38 /**
     39  * The route for a request.
     40  * Instances of this class are unmodifiable and therefore suitable
     41  * for use as lookup keys.
     42  *
     43  * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
     44  *
     45  *
     46  * <!-- empty lines to avoid svn diff problems -->
     47  * @version $Revision: 653041 $
     48  *
     49  * @since 4.0
     50  *
     51  * @deprecated Please use {@link java.net.URL#openConnection} instead.
     52  *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
     53  *     for further details.
     54  */
     55 @Deprecated
     56 public final class HttpRoute implements RouteInfo, Cloneable {
     57 
     58     /** The target host to connect to. */
     59     private final HttpHost targetHost;
     60 
     61     /**
     62      * The local address to connect from.
     63      * <code>null</code> indicates that the default should be used.
     64      */
     65     private final InetAddress localAddress;
     66 
     67     /** The proxy servers, if any. */
     68     private final HttpHost[] proxyChain;
     69 
     70     /** Whether the the route is tunnelled through the proxy. */
     71     private final TunnelType tunnelled;
     72 
     73     /** Whether the route is layered. */
     74     private final LayerType layered;
     75 
     76     /** Whether the route is (supposed to be) secure. */
     77     private final boolean secure;
     78 
     79 
     80     /**
     81      * Internal, fully-specified constructor.
     82      * This constructor does <i>not</i> clone the proxy chain array,
     83      * nor test it for <code>null</code> elements. This conversion and
     84      * check is the responsibility of the public constructors.
     85      * The order of arguments here is different from the similar public
     86      * constructor, as required by Java.
     87      *
     88      * @param local     the local address to route from, or
     89      *                  <code>null</code> for the default
     90      * @param target    the host to which to route
     91      * @param proxies   the proxy chain to use, or
     92      *                  <code>null</code> for a direct route
     93      * @param secure    <code>true</code> if the route is (to be) secure,
     94      *                  <code>false</code> otherwise
     95      * @param tunnelled the tunnel type of this route, or
     96      *                  <code>null</code> for PLAIN
     97      * @param layered   the layering type of this route, or
     98      *                  <code>null</code> for PLAIN
     99      */
    100     private HttpRoute(InetAddress local,
    101                       HttpHost target, HttpHost[] proxies,
    102                       boolean secure,
    103                       TunnelType tunnelled, LayerType layered) {
    104         if (target == null) {
    105             throw new IllegalArgumentException
    106                 ("Target host may not be null.");
    107         }
    108         if ((tunnelled == TunnelType.TUNNELLED) && (proxies == null)) {
    109             throw new IllegalArgumentException
    110                 ("Proxy required if tunnelled.");
    111         }
    112 
    113         // tunnelled is already checked above, that is in line with the default
    114         if (tunnelled == null)
    115             tunnelled = TunnelType.PLAIN;
    116         if (layered == null)
    117             layered = LayerType.PLAIN;
    118 
    119         this.targetHost   = target;
    120         this.localAddress = local;
    121         this.proxyChain   = proxies;
    122         this.secure       = secure;
    123         this.tunnelled    = tunnelled;
    124         this.layered      = layered;
    125     }
    126 
    127 
    128     /**
    129      * Creates a new route with all attributes specified explicitly.
    130      *
    131      * @param target    the host to which to route
    132      * @param local     the local address to route from, or
    133      *                  <code>null</code> for the default
    134      * @param proxies   the proxy chain to use, or
    135      *                  <code>null</code> for a direct route
    136      * @param secure    <code>true</code> if the route is (to be) secure,
    137      *                  <code>false</code> otherwise
    138      * @param tunnelled the tunnel type of this route
    139      * @param layered   the layering type of this route
    140      */
    141     public HttpRoute(HttpHost target, InetAddress local, HttpHost[] proxies,
    142                      boolean secure, TunnelType tunnelled, LayerType layered) {
    143         this(local, target, toChain(proxies), secure, tunnelled, layered);
    144     }
    145 
    146 
    147     /**
    148      * Creates a new route with at most one proxy.
    149      *
    150      * @param target    the host to which to route
    151      * @param local     the local address to route from, or
    152      *                  <code>null</code> for the default
    153      * @param proxy     the proxy to use, or
    154      *                  <code>null</code> for a direct route
    155      * @param secure    <code>true</code> if the route is (to be) secure,
    156      *                  <code>false</code> otherwise
    157      * @param tunnelled <code>true</code> if the route is (to be) tunnelled
    158      *                  via the proxy,
    159      *                  <code>false</code> otherwise
    160      * @param layered   <code>true</code> if the route includes a
    161      *                  layered protocol,
    162      *                  <code>false</code> otherwise
    163      */
    164     public HttpRoute(HttpHost target, InetAddress local, HttpHost proxy,
    165                      boolean secure, TunnelType tunnelled, LayerType layered) {
    166         this(local, target, toChain(proxy), secure, tunnelled, layered);
    167     }
    168 
    169 
    170     /**
    171      * Creates a new direct route.
    172      * That is a route without a proxy.
    173      *
    174      * @param target    the host to which to route
    175      * @param local     the local address to route from, or
    176      *                  <code>null</code> for the default
    177      * @param secure    <code>true</code> if the route is (to be) secure,
    178      *                  <code>false</code> otherwise
    179      */
    180     public HttpRoute(HttpHost target, InetAddress local, boolean secure) {
    181         this(local, target, null, secure, TunnelType.PLAIN, LayerType.PLAIN);
    182     }
    183 
    184 
    185     /**
    186      * Creates a new direct insecure route.
    187      *
    188      * @param target    the host to which to route
    189      */
    190     public HttpRoute(HttpHost target) {
    191         this(null, target, null, false, TunnelType.PLAIN, LayerType.PLAIN);
    192     }
    193 
    194 
    195     /**
    196      * Creates a new route through a proxy.
    197      * When using this constructor, the <code>proxy</code> MUST be given.
    198      * For convenience, it is assumed that a secure connection will be
    199      * layered over a tunnel through the proxy.
    200      *
    201      * @param target    the host to which to route
    202      * @param local     the local address to route from, or
    203      *                  <code>null</code> for the default
    204      * @param proxy     the proxy to use
    205      * @param secure    <code>true</code> if the route is (to be) secure,
    206      *                  <code>false</code> otherwise
    207      */
    208     public HttpRoute(HttpHost target, InetAddress local, HttpHost proxy,
    209                      boolean secure) {
    210         this(local, target, toChain(proxy), secure,
    211              secure ? TunnelType.TUNNELLED : TunnelType.PLAIN,
    212              secure ? LayerType.LAYERED    : LayerType.PLAIN);
    213         if (proxy == null) {
    214             throw new IllegalArgumentException
    215                 ("Proxy host may not be null.");
    216         }
    217     }
    218 
    219 
    220     /**
    221      * Helper to convert a proxy to a proxy chain.
    222      *
    223      * @param proxy     the only proxy in the chain, or <code>null</code>
    224      *
    225      * @return  a proxy chain array, or <code>null</code>
    226      */
    227     private static HttpHost[] toChain(HttpHost proxy) {
    228         if (proxy == null)
    229             return null;
    230 
    231         return new HttpHost[]{ proxy };
    232     }
    233 
    234 
    235     /**
    236      * Helper to duplicate and check a proxy chain.
    237      * An empty proxy chain is converted to <code>null</code>.
    238      *
    239      * @param proxies   the proxy chain to duplicate, or <code>null</code>
    240      *
    241      * @return  a new proxy chain array, or <code>null</code>
    242      */
    243     private static HttpHost[] toChain(HttpHost[] proxies) {
    244         if ((proxies == null) || (proxies.length < 1))
    245             return null;
    246 
    247         for (HttpHost proxy : proxies) {
    248             if (proxy == null)
    249                 throw new IllegalArgumentException
    250                         ("Proxy chain may not contain null elements.");
    251         }
    252 
    253         // copy the proxy chain, the traditional way
    254         HttpHost[] result = new HttpHost[proxies.length];
    255         System.arraycopy(proxies, 0, result, 0, proxies.length);
    256 
    257         return result;
    258     }
    259 
    260 
    261 
    262     // non-JavaDoc, see interface RouteInfo
    263     public final HttpHost getTargetHost() {
    264         return this.targetHost;
    265     }
    266 
    267 
    268     // non-JavaDoc, see interface RouteInfo
    269     public final InetAddress getLocalAddress() {
    270         return this.localAddress;
    271     }
    272 
    273 
    274     // non-JavaDoc, see interface RouteInfo
    275     public final int getHopCount() {
    276         return (proxyChain == null) ? 1 : (proxyChain.length+1);
    277     }
    278 
    279 
    280     // non-JavaDoc, see interface RouteInfo
    281     public final HttpHost getHopTarget(int hop) {
    282         if (hop < 0)
    283             throw new IllegalArgumentException
    284                 ("Hop index must not be negative: " + hop);
    285         final int hopcount = getHopCount();
    286         if (hop >= hopcount)
    287             throw new IllegalArgumentException
    288                 ("Hop index " + hop +
    289                  " exceeds route length " + hopcount);
    290 
    291         HttpHost result = null;
    292         if (hop < hopcount-1)
    293             result = this.proxyChain[hop];
    294         else
    295             result = this.targetHost;
    296 
    297         return result;
    298     }
    299 
    300 
    301     // non-JavaDoc, see interface RouteInfo
    302     public final HttpHost getProxyHost() {
    303         return (this.proxyChain == null) ? null : this.proxyChain[0];
    304     }
    305 
    306 
    307     // non-JavaDoc, see interface RouteInfo
    308     public final TunnelType getTunnelType() {
    309         return this.tunnelled;
    310     }
    311 
    312 
    313     // non-JavaDoc, see interface RouteInfo
    314     public final boolean isTunnelled() {
    315         return (this.tunnelled == TunnelType.TUNNELLED);
    316     }
    317 
    318 
    319     // non-JavaDoc, see interface RouteInfo
    320     public final LayerType getLayerType() {
    321         return this.layered;
    322     }
    323 
    324 
    325     // non-JavaDoc, see interface RouteInfo
    326     public final boolean isLayered() {
    327         return (this.layered == LayerType.LAYERED);
    328     }
    329 
    330 
    331     // non-JavaDoc, see interface RouteInfo
    332     public final boolean isSecure() {
    333         return this.secure;
    334     }
    335 
    336 
    337     /**
    338      * Compares this route to another.
    339      *
    340      * @param o         the object to compare with
    341      *
    342      * @return  <code>true</code> if the argument is the same route,
    343      *          <code>false</code>
    344      */
    345     @Override
    346     public final boolean equals(Object o) {
    347         if (o == this)
    348             return true;
    349         if (!(o instanceof HttpRoute))
    350             return false;
    351 
    352         HttpRoute that = (HttpRoute) o;
    353         boolean equal = this.targetHost.equals(that.targetHost);
    354         equal &=
    355             ( this.localAddress == that.localAddress) ||
    356             ((this.localAddress != null) &&
    357               this.localAddress.equals(that.localAddress));
    358         equal &=
    359             ( this.proxyChain        == that.proxyChain) ||
    360             ((this.proxyChain        != null) &&
    361              (that.proxyChain        != null) &&
    362              (this.proxyChain.length == that.proxyChain.length));
    363         // comparison of actual proxies follows below
    364         equal &=
    365             (this.secure    == that.secure) &&
    366             (this.tunnelled == that.tunnelled) &&
    367             (this.layered   == that.layered);
    368 
    369         // chain length has been compared above, now check the proxies
    370         if (equal && (this.proxyChain != null)) {
    371             for (int i=0; equal && (i<this.proxyChain.length); i++)
    372                 equal = this.proxyChain[i].equals(that.proxyChain[i]);
    373         }
    374 
    375         return equal;
    376     }
    377 
    378 
    379     /**
    380      * Generates a hash code for this route.
    381      *
    382      * @return  the hash code
    383      */
    384     @Override
    385     public final int hashCode() {
    386 
    387         int hc = this.targetHost.hashCode();
    388 
    389         if (this.localAddress != null)
    390             hc ^= localAddress.hashCode();
    391         if (this.proxyChain != null) {
    392             hc ^= proxyChain.length;
    393             for (HttpHost aProxyChain : proxyChain) hc ^= aProxyChain.hashCode();
    394         }
    395 
    396         if (this.secure)
    397             hc ^= 0x11111111;
    398 
    399         hc ^= this.tunnelled.hashCode();
    400         hc ^= this.layered.hashCode();
    401 
    402         return hc;
    403     }
    404 
    405 
    406     /**
    407      * Obtains a description of this route.
    408      *
    409      * @return  a human-readable representation of this route
    410      */
    411     @Override
    412     public final String toString() {
    413         StringBuilder cab = new StringBuilder(50 + getHopCount()*30);
    414 
    415         cab.append("HttpRoute[");
    416         if (this.localAddress != null) {
    417             cab.append(this.localAddress);
    418             cab.append("->");
    419         }
    420         cab.append('{');
    421         if (this.tunnelled == TunnelType.TUNNELLED)
    422             cab.append('t');
    423         if (this.layered == LayerType.LAYERED)
    424             cab.append('l');
    425         if (this.secure)
    426             cab.append('s');
    427         cab.append("}->");
    428         if (this.proxyChain != null) {
    429             for (HttpHost aProxyChain : this.proxyChain) {
    430                 cab.append(aProxyChain);
    431                 cab.append("->");
    432             }
    433         }
    434         cab.append(this.targetHost);
    435         cab.append(']');
    436 
    437         return cab.toString();
    438     }
    439 
    440 
    441     // default implementation of clone() is sufficient
    442     @Override
    443     public Object clone() throws CloneNotSupportedException {
    444         return super.clone();
    445     }
    446 
    447 
    448 } // class HttpRoute
    449