1069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/*
2069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/routing/HttpRoute.java $
3069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Revision: 653041 $
4069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Date: 2008-05-03 03:39:28 -0700 (Sat, 03 May 2008) $
5069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
6069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ====================================================================
7069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one
8069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * or more contributor license agreements.  See the NOTICE file
9069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * distributed with this work for additional information
10069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * regarding copyright ownership.  The ASF licenses this file
11069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to you under the Apache License, Version 2.0 (the
12069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "License"); you may not use this file except in compliance
13069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * with the License.  You may obtain a copy of the License at
14069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
15069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *   http://www.apache.org/licenses/LICENSE-2.0
16069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
17069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Unless required by applicable law or agreed to in writing,
18069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * software distributed under the License is distributed on an
19069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * KIND, either express or implied.  See the License for the
21069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * specific language governing permissions and limitations
22069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * under the License.
23069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ====================================================================
24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This software consists of voluntary contributions made by many
26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * individuals on behalf of the Apache Software Foundation.  For more
27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * information on the Apache Software Foundation, please see
28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <http://www.apache.org/>.
29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpackage org.apache.http.conn.routing;
33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.net.InetAddress;
35069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
36069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.HttpHost;
37069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
38069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/**
39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The route for a request.
40069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Instances of this class are unmodifiable and therefore suitable
41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * for use as lookup keys.
42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <!-- empty lines to avoid svn diff problems -->
47069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @version $Revision: 653041 $
48069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
49069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @since 4.0
50069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
51069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic final class HttpRoute implements RouteInfo, Cloneable {
52069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
53069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** The target host to connect to. */
54069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final HttpHost targetHost;
55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
56069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
57069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The local address to connect from.
58069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <code>null</code> indicates that the default should be used.
59069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
60069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final InetAddress localAddress;
61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
62069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** The proxy servers, if any. */
63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final HttpHost[] proxyChain;
64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** Whether the the route is tunnelled through the proxy. */
66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final TunnelType tunnelled;
67069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** Whether the route is layered. */
69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final LayerType layered;
70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** Whether the route is (supposed to be) secure. */
72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final boolean secure;
73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Internal, fully-specified constructor.
77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * This constructor does <i>not</i> clone the proxy chain array,
78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * nor test it for <code>null</code> elements. This conversion and
79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * check is the responsibility of the public constructors.
80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The order of arguments here is different from the similar public
81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * constructor, as required by Java.
82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param local     the local address to route from, or
84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>null</code> for the default
85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param target    the host to which to route
86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param proxies   the proxy chain to use, or
87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>null</code> for a direct route
88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param secure    <code>true</code> if the route is (to be) secure,
89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>false</code> otherwise
90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param tunnelled the tunnel type of this route, or
91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>null</code> for PLAIN
92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param layered   the layering type of this route, or
93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>null</code> for PLAIN
94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private HttpRoute(InetAddress local,
96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                      HttpHost target, HttpHost[] proxies,
97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                      boolean secure,
98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                      TunnelType tunnelled, LayerType layered) {
99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (target == null) {
100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Target host may not be null.");
102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if ((tunnelled == TunnelType.TUNNELLED) && (proxies == null)) {
104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Proxy required if tunnelled.");
106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // tunnelled is already checked above, that is in line with the default
109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (tunnelled == null)
110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            tunnelled = TunnelType.PLAIN;
111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (layered == null)
112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            layered = LayerType.PLAIN;
113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.targetHost   = target;
115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.localAddress = local;
116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.proxyChain   = proxies;
117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.secure       = secure;
118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.tunnelled    = tunnelled;
119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.layered      = layered;
120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Creates a new route with all attributes specified explicitly.
125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param target    the host to which to route
127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param local     the local address to route from, or
128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>null</code> for the default
129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param proxies   the proxy chain to use, or
130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>null</code> for a direct route
131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param secure    <code>true</code> if the route is (to be) secure,
132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>false</code> otherwise
133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param tunnelled the tunnel type of this route
134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param layered   the layering type of this route
135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public HttpRoute(HttpHost target, InetAddress local, HttpHost[] proxies,
137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                     boolean secure, TunnelType tunnelled, LayerType layered) {
138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this(local, target, toChain(proxies), secure, tunnelled, layered);
139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Creates a new route with at most one proxy.
144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param target    the host to which to route
146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param local     the local address to route from, or
147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>null</code> for the default
148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param proxy     the proxy to use, or
149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>null</code> for a direct route
150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param secure    <code>true</code> if the route is (to be) secure,
151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>false</code> otherwise
152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param tunnelled <code>true</code> if the route is (to be) tunnelled
153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  via the proxy,
154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>false</code> otherwise
155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param layered   <code>true</code> if the route includes a
156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  layered protocol,
157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>false</code> otherwise
158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public HttpRoute(HttpHost target, InetAddress local, HttpHost proxy,
160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                     boolean secure, TunnelType tunnelled, LayerType layered) {
161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this(local, target, toChain(proxy), secure, tunnelled, layered);
162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Creates a new direct route.
167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * That is a route without a proxy.
168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param target    the host to which to route
170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param local     the local address to route from, or
171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>null</code> for the default
172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param secure    <code>true</code> if the route is (to be) secure,
173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>false</code> otherwise
174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public HttpRoute(HttpHost target, InetAddress local, boolean secure) {
176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this(local, target, null, secure, TunnelType.PLAIN, LayerType.PLAIN);
177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Creates a new direct insecure route.
182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param target    the host to which to route
184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public HttpRoute(HttpHost target) {
186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this(null, target, null, false, TunnelType.PLAIN, LayerType.PLAIN);
187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Creates a new route through a proxy.
192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * When using this constructor, the <code>proxy</code> MUST be given.
193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * For convenience, it is assumed that a secure connection will be
194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * layered over a tunnel through the proxy.
195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param target    the host to which to route
197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param local     the local address to route from, or
198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>null</code> for the default
199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param proxy     the proxy to use
200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param secure    <code>true</code> if the route is (to be) secure,
201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  <code>false</code> otherwise
202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public HttpRoute(HttpHost target, InetAddress local, HttpHost proxy,
204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                     boolean secure) {
205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this(local, target, toChain(proxy), secure,
206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project             secure ? TunnelType.TUNNELLED : TunnelType.PLAIN,
207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project             secure ? LayerType.LAYERED    : LayerType.PLAIN);
208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (proxy == null) {
209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Proxy host may not be null.");
211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Helper to convert a proxy to a proxy chain.
217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param proxy     the only proxy in the chain, or <code>null</code>
219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  a proxy chain array, or <code>null</code>
221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static HttpHost[] toChain(HttpHost proxy) {
223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (proxy == null)
224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return null;
225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return new HttpHost[]{ proxy };
227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Helper to duplicate and check a proxy chain.
232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * An empty proxy chain is converted to <code>null</code>.
233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param proxies   the proxy chain to duplicate, or <code>null</code>
235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  a new proxy chain array, or <code>null</code>
237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static HttpHost[] toChain(HttpHost[] proxies) {
239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if ((proxies == null) || (proxies.length < 1))
240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return null;
241069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
242069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        for (HttpHost proxy : proxies) {
243069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (proxy == null)
244069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                throw new IllegalArgumentException
245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        ("Proxy chain may not contain null elements.");
246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
248069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // copy the proxy chain, the traditional way
249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        HttpHost[] result = new HttpHost[proxies.length];
250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        System.arraycopy(proxies, 0, result, 0, proxies.length);
251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return result;
253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-JavaDoc, see interface RouteInfo
258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final HttpHost getTargetHost() {
259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return this.targetHost;
260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-JavaDoc, see interface RouteInfo
264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final InetAddress getLocalAddress() {
265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return this.localAddress;
266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-JavaDoc, see interface RouteInfo
270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final int getHopCount() {
271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return (proxyChain == null) ? 1 : (proxyChain.length+1);
272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-JavaDoc, see interface RouteInfo
276069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final HttpHost getHopTarget(int hop) {
277069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (hop < 0)
278069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
279069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Hop index must not be negative: " + hop);
280069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        final int hopcount = getHopCount();
281069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (hop >= hopcount)
282069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
283069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Hop index " + hop +
284069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                 " exceeds route length " + hopcount);
285069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
286069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        HttpHost result = null;
287069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (hop < hopcount-1)
288069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result = this.proxyChain[hop];
289069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        else
290069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result = this.targetHost;
291069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
292069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return result;
293069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
294069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
295069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
296069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-JavaDoc, see interface RouteInfo
297069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final HttpHost getProxyHost() {
298069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return (this.proxyChain == null) ? null : this.proxyChain[0];
299069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
300069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
301069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
302069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-JavaDoc, see interface RouteInfo
303069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final TunnelType getTunnelType() {
304069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return this.tunnelled;
305069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
306069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
307069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
308069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-JavaDoc, see interface RouteInfo
309069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final boolean isTunnelled() {
310069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return (this.tunnelled == TunnelType.TUNNELLED);
311069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
312069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
313069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
314069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-JavaDoc, see interface RouteInfo
315069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final LayerType getLayerType() {
316069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return this.layered;
317069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
318069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
319069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
320069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-JavaDoc, see interface RouteInfo
321069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final boolean isLayered() {
322069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return (this.layered == LayerType.LAYERED);
323069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
324069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
325069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
326069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-JavaDoc, see interface RouteInfo
327069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final boolean isSecure() {
328069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return this.secure;
329069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
330069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
331069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
332069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
333069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Compares this route to another.
334069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
335069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param o         the object to compare with
336069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
337069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  <code>true</code> if the argument is the same route,
338069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *          <code>false</code>
339069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
340069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    @Override
341069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final boolean equals(Object o) {
342069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (o == this)
343069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return true;
344069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (!(o instanceof HttpRoute))
345069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return false;
346069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
347069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        HttpRoute that = (HttpRoute) o;
348069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean equal = this.targetHost.equals(that.targetHost);
349069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        equal &=
350069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            ( this.localAddress == that.localAddress) ||
351069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            ((this.localAddress != null) &&
352069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project              this.localAddress.equals(that.localAddress));
353069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        equal &=
354069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            ( this.proxyChain        == that.proxyChain) ||
355069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            ((this.proxyChain        != null) &&
356069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project             (that.proxyChain        != null) &&
357069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project             (this.proxyChain.length == that.proxyChain.length));
358069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // comparison of actual proxies follows below
359069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        equal &=
360069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            (this.secure    == that.secure) &&
361069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            (this.tunnelled == that.tunnelled) &&
362069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            (this.layered   == that.layered);
363069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
364069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // chain length has been compared above, now check the proxies
365069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (equal && (this.proxyChain != null)) {
366069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            for (int i=0; equal && (i<this.proxyChain.length); i++)
367069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                equal = this.proxyChain[i].equals(that.proxyChain[i]);
368069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
369069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
370069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return equal;
371069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
372069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
373069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
374069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
375069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Generates a hash code for this route.
376069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
377069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  the hash code
378069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
379069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    @Override
380069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final int hashCode() {
381069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
382069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int hc = this.targetHost.hashCode();
383069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
384069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.localAddress != null)
385069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            hc ^= localAddress.hashCode();
386069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.proxyChain != null) {
387069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            hc ^= proxyChain.length;
388069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            for (HttpHost aProxyChain : proxyChain) hc ^= aProxyChain.hashCode();
389069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
390069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
391069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.secure)
392069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            hc ^= 0x11111111;
393069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
394069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        hc ^= this.tunnelled.hashCode();
395069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        hc ^= this.layered.hashCode();
396069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
397069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return hc;
398069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
399069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
400069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
401069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
402069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Obtains a description of this route.
403069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
404069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  a human-readable representation of this route
405069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
406069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    @Override
407069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final String toString() {
408069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        StringBuilder cab = new StringBuilder(50 + getHopCount()*30);
409069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
410069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        cab.append("HttpRoute[");
411069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.localAddress != null) {
412069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            cab.append(this.localAddress);
413069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            cab.append("->");
414069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
415069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        cab.append('{');
416069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.tunnelled == TunnelType.TUNNELLED)
417069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            cab.append('t');
418069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.layered == LayerType.LAYERED)
419069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            cab.append('l');
420069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.secure)
421069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            cab.append('s');
422069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        cab.append("}->");
423069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.proxyChain != null) {
424069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            for (HttpHost aProxyChain : this.proxyChain) {
425069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                cab.append(aProxyChain);
426069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                cab.append("->");
427069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
428069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
429069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        cab.append(this.targetHost);
430069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        cab.append(']');
431069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
432069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return cab.toString();
433069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
434069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
435069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
436069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // default implementation of clone() is sufficient
437069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    @Override
438069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public Object clone() throws CloneNotSupportedException {
439069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return super.clone();
440069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
441069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
442069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
443069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project} // class HttpRoute
444