mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoute.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2  * ====================================================================
     3  * Licensed to the Apache Software Foundation (ASF) under one
     4  * or more contributor license agreements.  See the NOTICE file
     5  * distributed with this work for additional information
     6  * regarding copyright ownership.  The ASF licenses this file
     7  * to you under the Apache License, Version 2.0 (the
     8  * "License"); you may not use this file except in compliance
     9  * with the License.  You may obtain a copy of the License at
    10  *
    11  *   http://www.apache.org/licenses/LICENSE-2.0
    12  *
    13  * Unless required by applicable law or agreed to in writing,
    14  * software distributed under the License is distributed on an
    15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    16  * KIND, either express or implied.  See the License for the
    17  * specific language governing permissions and limitations
    18  * under the License.
    19  * ====================================================================
    20  *
    21  * This software consists of voluntary contributions made by many
    22  * individuals on behalf of the Apache Software Foundation.  For more
    23  * information on the Apache Software Foundation, please see
    24  * <http://www.apache.org/>.
    25  *
    26  */
    28 package ch.boye.httpclientandroidlib.conn.routing;
    30 import java.net.InetAddress;
    32 import ch.boye.httpclientandroidlib.annotation.Immutable;
    33 import ch.boye.httpclientandroidlib.util.LangUtils;
    35 import ch.boye.httpclientandroidlib.HttpHost;
    37 /**
    38  * The route for a request.
    39  * Instances of this class are unmodifiable and therefore suitable
    40  * for use as lookup keys.
    41  *
    42  * @since 4.0
    43  */
    44 @Immutable
    45 public final class HttpRoute implements RouteInfo, Cloneable {
    47     private static final HttpHost[] EMPTY_HTTP_HOST_ARRAY = new HttpHost[]{};
    49     /** The target host to connect to. */
    50     private final HttpHost targetHost;
    52     /**
    53      * The local address to connect from.
    54      * <code>null</code> indicates that the default should be used.
    55      */
    56     private final InetAddress localAddress;
    58     /** The proxy servers, if any. Never null. */
    59     private final HttpHost[] proxyChain;
    61     /** Whether the the route is tunnelled through the proxy. */
    62     private final TunnelType tunnelled;
    64     /** Whether the route is layered. */
    65     private final LayerType layered;
    67     /** Whether the route is (supposed to be) secure. */
    68     private final boolean secure;
    71     /**
    72      * Internal, fully-specified constructor.
    73      * This constructor does <i>not</i> clone the proxy chain array,
    74      * nor test it for <code>null</code> elements. This conversion and
    75      * check is the responsibility of the public constructors.
    76      * The order of arguments here is different from the similar public
    77      * constructor, as required by Java.
    78      *
    79      * @param local     the local address to route from, or
    80      *                  <code>null</code> for the default
    81      * @param target    the host to which to route
    82      * @param proxies   the proxy chain to use, or
    83      *                  <code>null</code> for a direct route
    84      * @param secure    <code>true</code> if the route is (to be) secure,
    85      *                  <code>false</code> otherwise
    86      * @param tunnelled the tunnel type of this route, or
    87      *                  <code>null</code> for PLAIN
    88      * @param layered   the layering type of this route, or
    89      *                  <code>null</code> for PLAIN
    90      */
    91     private HttpRoute(InetAddress local,
    92                       HttpHost target, HttpHost[] proxies,
    93                       boolean secure,
    94                       TunnelType tunnelled, LayerType layered) {
    95         if (target == null) {
    96             throw new IllegalArgumentException
    97                 ("Target host may not be null.");
    98         }
    99         if (proxies == null) {
   100             throw new IllegalArgumentException
   101                 ("Proxies may not be null.");
   102         }
   103         if ((tunnelled == TunnelType.TUNNELLED) && (proxies.length == 0)) {
   104             throw new IllegalArgumentException
   105                 ("Proxy required if tunnelled.");
   106         }
   108         // tunnelled is already checked above, that is in line with the default
   109         if (tunnelled == null)
   110             tunnelled = TunnelType.PLAIN;
   111         if (layered == null)
   112             layered = LayerType.PLAIN;
   114         this.targetHost   = target;
   115         this.localAddress = local;
   116         this.proxyChain   = proxies;
   117         this.secure       = secure;
   118         this.tunnelled    = tunnelled;
   119         this.layered      = layered;
   120     }
   123     /**
   124      * Creates a new route with all attributes specified explicitly.
   125      *
   126      * @param target    the host to which to route
   127      * @param local     the local address to route from, or
   128      *                  <code>null</code> for the default
   129      * @param proxies   the proxy chain to use, or
   130      *                  <code>null</code> for a direct route
   131      * @param secure    <code>true</code> if the route is (to be) secure,
   132      *                  <code>false</code> otherwise
   133      * @param tunnelled the tunnel type of this route
   134      * @param layered   the layering type of this route
   135      */
   136     public HttpRoute(HttpHost target, InetAddress local, HttpHost[] proxies,
   137                      boolean secure, TunnelType tunnelled, LayerType layered) {
   138         this(local, target, toChain(proxies), secure, tunnelled, layered);
   139     }
   142     /**
   143      * Creates a new route with at most one proxy.
   144      *
   145      * @param target    the host to which to route
   146      * @param local     the local address to route from, or
   147      *                  <code>null</code> for the default
   148      * @param proxy     the proxy to use, or
   149      *                  <code>null</code> for a direct route
   150      * @param secure    <code>true</code> if the route is (to be) secure,
   151      *                  <code>false</code> otherwise
   152      * @param tunnelled <code>true</code> if the route is (to be) tunnelled
   153      *                  via the proxy,
   154      *                  <code>false</code> otherwise
   155      * @param layered   <code>true</code> if the route includes a
   156      *                  layered protocol,
   157      *                  <code>false</code> otherwise
   158      */
   159     public HttpRoute(HttpHost target, InetAddress local, HttpHost proxy,
   160                      boolean secure, TunnelType tunnelled, LayerType layered) {
   161         this(local, target, toChain(proxy), secure, tunnelled, layered);
   162     }
   165     /**
   166      * Creates a new direct route.
   167      * That is a route without a proxy.
   168      *
   169      * @param target    the host to which to route
   170      * @param local     the local address to route from, or
   171      *                  <code>null</code> for the default
   172      * @param secure    <code>true</code> if the route is (to be) secure,
   173      *                  <code>false</code> otherwise
   174      */
   175     public HttpRoute(HttpHost target, InetAddress local, boolean secure) {
   176         this(local, target, EMPTY_HTTP_HOST_ARRAY, secure, TunnelType.PLAIN, LayerType.PLAIN);
   177     }
   180     /**
   181      * Creates a new direct insecure route.
   182      *
   183      * @param target    the host to which to route
   184      */
   185     public HttpRoute(HttpHost target) {
   186         this(null, target, EMPTY_HTTP_HOST_ARRAY, false, TunnelType.PLAIN, LayerType.PLAIN);
   187     }
   190     /**
   191      * Creates a new route through a proxy.
   192      * When using this constructor, the <code>proxy</code> MUST be given.
   193      * For convenience, it is assumed that a secure connection will be
   194      * layered over a tunnel through the proxy.
   195      *
   196      * @param target    the host to which to route
   197      * @param local     the local address to route from, or
   198      *                  <code>null</code> for the default
   199      * @param proxy     the proxy to use
   200      * @param secure    <code>true</code> if the route is (to be) secure,
   201      *                  <code>false</code> otherwise
   202      */
   203     public HttpRoute(HttpHost target, InetAddress local, HttpHost proxy,
   204                      boolean secure) {
   205         this(local, target, toChain(proxy), secure,
   206              secure ? TunnelType.TUNNELLED : TunnelType.PLAIN,
   207              secure ? LayerType.LAYERED    : LayerType.PLAIN);
   208         if (proxy == null) {
   209             throw new IllegalArgumentException
   210                 ("Proxy host may not be null.");
   211         }
   212     }
   215     /**
   216      * Helper to convert a proxy to a proxy chain.
   217      *
   218      * @param proxy     the only proxy in the chain, or <code>null</code>
   219      *
   220      * @return  a proxy chain array, may be empty (never null)
   221      */
   222     private static HttpHost[] toChain(HttpHost proxy) {
   223         if (proxy == null)
   224             return EMPTY_HTTP_HOST_ARRAY;
   226         return new HttpHost[]{ proxy };
   227     }
   230     /**
   231      * Helper to duplicate and check a proxy chain.
   232      * <code>null</code> is converted to an empty proxy chain.
   233      *
   234      * @param proxies   the proxy chain to duplicate, or <code>null</code>
   235      *
   236      * @return  a new proxy chain array, may be empty (never null)
   237      */
   238     private static HttpHost[] toChain(HttpHost[] proxies) {
   239         if ((proxies == null) || (proxies.length < 1))
   240             return EMPTY_HTTP_HOST_ARRAY;
   242         for (HttpHost proxy : proxies) {
   243             if (proxy == null)
   244                 throw new IllegalArgumentException
   245                         ("Proxy chain may not contain null elements.");
   246         }
   248         // copy the proxy chain, the traditional way
   249         HttpHost[] result = new HttpHost[proxies.length];
   250         System.arraycopy(proxies, 0, result, 0, proxies.length);
   252         return result;
   253     }
   257     // non-JavaDoc, see interface RouteInfo
   258     public final HttpHost getTargetHost() {
   259         return this.targetHost;
   260     }
   263     // non-JavaDoc, see interface RouteInfo
   264     public final InetAddress getLocalAddress() {
   265         return this.localAddress;
   266     }
   269     public final int getHopCount() {
   270         return proxyChain.length+1;
   271     }
   274     public final HttpHost getHopTarget(int hop) {
   275         if (hop < 0)
   276             throw new IllegalArgumentException
   277                 ("Hop index must not be negative: " + hop);
   278         final int hopcount = getHopCount();
   279         if (hop >= hopcount)
   280             throw new IllegalArgumentException
   281                 ("Hop index " + hop +
   282                  " exceeds route length " + hopcount);
   284         HttpHost result = null;
   285         if (hop < hopcount-1)
   286             result = this.proxyChain[hop];
   287         else
   288             result = this.targetHost;
   290         return result;
   291     }
   294     public final HttpHost getProxyHost() {
   295         return (this.proxyChain.length == 0) ? null : this.proxyChain[0];
   296     }
   299     public final TunnelType getTunnelType() {
   300         return this.tunnelled;
   301     }
   304     public final boolean isTunnelled() {
   305         return (this.tunnelled == TunnelType.TUNNELLED);
   306     }
   309     public final LayerType getLayerType() {
   310         return this.layered;
   311     }
   314     public final boolean isLayered() {
   315         return (this.layered == LayerType.LAYERED);
   316     }
   319     public final boolean isSecure() {
   320         return this.secure;
   321     }
   324     /**
   325      * Compares this route to another.
   326      *
   327      * @param obj         the object to compare with
   328      *
   329      * @return  <code>true</code> if the argument is the same route,
   330      *          <code>false</code>
   331      */
   332     @Override
   333     public final boolean equals(Object obj) {
   334         if (this == obj) return true;
   335         if (obj instanceof HttpRoute) {
   336             HttpRoute that = (HttpRoute) obj;
   337             return 
   338                 // Do the cheapest tests first
   339                 (this.secure    == that.secure) &&
   340                 (this.tunnelled == that.tunnelled) &&
   341                 (this.layered   == that.layered) &&
   342                 LangUtils.equals(this.targetHost, that.targetHost) &&
   343                 LangUtils.equals(this.localAddress, that.localAddress) &&
   344                 LangUtils.equals(this.proxyChain, that.proxyChain);
   345         } else {
   346             return false;
   347         }
   348     }
   351     /**
   352      * Generates a hash code for this route.
   353      *
   354      * @return  the hash code
   355      */
   356     @Override
   357     public final int hashCode() {
   358         int hash = LangUtils.HASH_SEED;
   359         hash = LangUtils.hashCode(hash, this.targetHost);
   360         hash = LangUtils.hashCode(hash, this.localAddress);
   361         for (int i = 0; i < this.proxyChain.length; i++) {
   362             hash = LangUtils.hashCode(hash, this.proxyChain[i]);
   363         }
   364         hash = LangUtils.hashCode(hash, this.secure);
   365         hash = LangUtils.hashCode(hash, this.tunnelled);
   366         hash = LangUtils.hashCode(hash, this.layered);
   367         return hash;
   368     }
   371     /**
   372      * Obtains a description of this route.
   373      *
   374      * @return  a human-readable representation of this route
   375      */
   376     @Override
   377     public final String toString() {
   378         StringBuilder cab = new StringBuilder(50 + getHopCount()*30);
   380         cab.append("HttpRoute[");
   381         if (this.localAddress != null) {
   382             cab.append(this.localAddress);
   383             cab.append("->");
   384         }
   385         cab.append('{');
   386         if (this.tunnelled == TunnelType.TUNNELLED)
   387             cab.append('t');
   388         if (this.layered == LayerType.LAYERED)
   389             cab.append('l');
   390         if (this.secure)
   391             cab.append('s');
   392         cab.append("}->");
   393         for (HttpHost aProxyChain : this.proxyChain) {
   394             cab.append(aProxyChain);
   395             cab.append("->");
   396         }
   397         cab.append(this.targetHost);
   398         cab.append(']');
   400         return cab.toString();
   401     }
   404     // default implementation of clone() is sufficient
   405     @Override
   406     public Object clone() throws CloneNotSupportedException {
   407         return super.clone();
   408     }
   410 }

mercurial