FileDocCategorySizeDatePackage
RouteTracker.javaAPI DocAndroid 1.5 API13380Wed May 06 22:41:10 BST 2009org.apache.http.conn.routing

RouteTracker

public final class RouteTracker extends Object implements Cloneable, RouteInfo
Helps tracking the steps in establishing a route.
author
Roland Weber
version
$Revision: 620254 $
since
4.0

Fields Summary
private final HttpHost
targetHost
The target host to connect to.
private final InetAddress
localAddress
The local address to connect from. null indicates that the default should be used.
private boolean
connected
Whether the first hop of the route is established.
private HttpHost[]
proxyChain
The proxy chain, if any.
private TunnelType
tunnelled
Whether the the route is tunnelled end-to-end through proxies.
private LayerType
layered
Whether the route is layered over a tunnel.
private boolean
secure
Whether the route is secure.
Constructors Summary
public RouteTracker(HttpHost target, InetAddress local)
Creates a new route tracker. The target and origin need to be specified at creation time.

param
target the host to which to route
param
local the local address to route from, or null for the default

        if (target == null) {
            throw new IllegalArgumentException("Target host may not be null.");
        }
        this.targetHost   = target;
        this.localAddress = local;
        this.tunnelled    = TunnelType.PLAIN;
        this.layered      = LayerType.PLAIN;
    
public RouteTracker(HttpRoute route)
Creates a new tracker for the given route. Only target and origin are taken from the route, everything else remains to be tracked.

param
route the route to track

        this(route.getTargetHost(), route.getLocalAddress());
    
Methods Summary
public java.lang.Objectclone()

        return super.clone();
    
public final voidconnectProxy(org.apache.http.HttpHost proxy, boolean secure)
Tracks connecting to the first proxy.

param
proxy the proxy connected to
param
secure true if the route is secure, false otherwise

        if (proxy == null) {
            throw new IllegalArgumentException("Proxy host may not be null.");
        }
        if (this.connected) {
            throw new IllegalStateException("Already connected.");
        }
        this.connected  = true;
        this.proxyChain = new HttpHost[]{ proxy };
        this.secure     = secure;
    
public final voidconnectTarget(boolean secure)
Tracks connecting to the target.

param
secure true if the route is secure, false otherwise

        if (this.connected) {
            throw new IllegalStateException("Already connected.");
        }
        this.connected = true;
        this.secure = secure;
    
public final booleanequals(java.lang.Object o)
Compares this tracked route to another.

param
o the object to compare with
return
true if the argument is the same tracked route, false

        if (o == this)
            return true;
        if (!(o instanceof RouteTracker))
            return false;

        RouteTracker that = (RouteTracker) o;
        boolean equal = this.targetHost.equals(that.targetHost);
        equal &=
            ( this.localAddress == that.localAddress) ||
            ((this.localAddress != null) &&
              this.localAddress.equals(that.localAddress));
        equal &=
            ( this.proxyChain        == that.proxyChain) ||
            ((this.proxyChain        != null) &&
             (that.proxyChain        != null) &&
             (this.proxyChain.length == that.proxyChain.length));
        // comparison of actual proxies follows below
        equal &=
            (this.connected == that.connected) &&
            (this.secure    == that.secure) &&
            (this.tunnelled == that.tunnelled) &&
            (this.layered   == that.layered);

        // chain length has been compared above, now check the proxies
        if (equal && (this.proxyChain != null)) {
            for (int i=0; equal && (i<this.proxyChain.length); i++)
                equal = this.proxyChain[i].equals(that.proxyChain[i]);
        }

        return equal;
    
public final intgetHopCount()

        int hops = 0;
        if (this.connected) {
            if (proxyChain == null)
                hops = 1;
            else
                hops = proxyChain.length + 1;
        }
        return hops;
    
public final org.apache.http.HttpHostgetHopTarget(int hop)

        if (hop < 0)
            throw new IllegalArgumentException
                ("Hop index must not be negative: " + hop);
        final int hopcount = getHopCount();
        if (hop >= hopcount) {
            throw new IllegalArgumentException
                ("Hop index " + hop +
                 " exceeds tracked route length " + hopcount +".");
        }

        HttpHost result = null;
        if (hop < hopcount-1)
            result = this.proxyChain[hop];
        else
            result = this.targetHost;

        return result;
    
public final LayerTypegetLayerType()

        return this.layered;
    
public final java.net.InetAddressgetLocalAddress()

        return this.localAddress;
    
public final org.apache.http.HttpHostgetProxyHost()

        return (this.proxyChain == null) ? null : this.proxyChain[0];
    
public final org.apache.http.HttpHostgetTargetHost()

        return this.targetHost;
    
public final TunnelTypegetTunnelType()

        return this.tunnelled;
    
public final inthashCode()
Generates a hash code for this tracked route. Route trackers are modifiable and should therefore not be used as lookup keys. Use {@link #toRoute toRoute} to obtain an unmodifiable representation of the tracked route.

return
the hash code


        int hc = this.targetHost.hashCode();

        if (this.localAddress != null)
            hc ^= localAddress.hashCode();
        if (this.proxyChain != null) {
            hc ^= proxyChain.length;
            for (int i=0; i<proxyChain.length; i++)
                hc ^= proxyChain[i].hashCode();
        }

        if (this.connected)
            hc ^= 0x11111111;
        if (this.secure)
            hc ^= 0x22222222;

        hc ^= this.tunnelled.hashCode();
        hc ^= this.layered.hashCode();

        return hc;
    
public final booleanisConnected()

        return this.connected;
    
public final booleanisLayered()

        return (this.layered == LayerType.LAYERED);
    
public final booleanisSecure()

        return this.secure;
    
public final booleanisTunnelled()

        return (this.tunnelled == TunnelType.TUNNELLED);
    
public final voidlayerProtocol(boolean secure)
Tracks layering a protocol.

param
secure true if the route is secure, false otherwise

        // it is possible to layer a protocol over a direct connection,
        // although this case is probably not considered elsewhere
        if (!this.connected) {
            throw new IllegalStateException
                ("No layered protocol unless connected.");
        }
        this.layered = LayerType.LAYERED;
        this.secure  = secure;
    
public final org.apache.http.conn.routing.HttpRoutetoRoute()
Obtains the tracked route. If a route has been tracked, it is {@link #isConnected connected}. If not connected, nothing has been tracked so far.

return
the tracked route, or null if nothing has been tracked so far

        return !this.connected ?
            null : new HttpRoute(this.targetHost, this.localAddress,
                                 this.proxyChain, this.secure,
                                 this.tunnelled, this.layered);
    
public final java.lang.StringtoString()
Obtains a description of the tracked route.

return
a human-readable representation of the tracked route

        StringBuilder cab = new StringBuilder(50 + getHopCount()*30);

        cab.append("RouteTracker[");
        if (this.localAddress != null) {
            cab.append(this.localAddress);
            cab.append("->");
        }
        cab.append('{");
        if (this.connected)
            cab.append('c");
        if (this.tunnelled == TunnelType.TUNNELLED)
            cab.append('t");
        if (this.layered == LayerType.LAYERED)
            cab.append('l");
        if (this.secure)
            cab.append('s");
        cab.append("}->");
        if (this.proxyChain != null) {
            for (int i=0; i<this.proxyChain.length; i++) {
                cab.append(this.proxyChain[i]);
                cab.append("->");
            }
        }
        cab.append(this.targetHost);
        cab.append(']");

        return cab.toString();
    
public final voidtunnelProxy(org.apache.http.HttpHost proxy, boolean secure)
Tracks tunnelling to a proxy in a proxy chain. This will extend the tracked proxy chain, but it does not mark the route as tunnelled. Only end-to-end tunnels are considered there.

param
proxy the proxy tunnelled to
param
secure true if the route is secure, false otherwise

        if (proxy == null) {
            throw new IllegalArgumentException("Proxy host may not be null.");
        }
        if (!this.connected) {
            throw new IllegalStateException("No tunnel unless connected.");
        }
        if (this.proxyChain == null) {
            throw new IllegalStateException("No proxy tunnel without proxy.");
        }

        // prepare an extended proxy chain
        HttpHost[] proxies = new HttpHost[this.proxyChain.length+1];
        System.arraycopy(this.proxyChain, 0,
                         proxies, 0, this.proxyChain.length);
        proxies[proxies.length-1] = proxy;

        this.proxyChain = proxies;
        this.secure     = secure;
    
public final voidtunnelTarget(boolean secure)
Tracks tunnelling to the target.

param
secure true if the route is secure, false otherwise

        if (!this.connected) {
            throw new IllegalStateException("No tunnel unless connected.");
        }
        if (this.proxyChain == null) {
            throw new IllegalStateException("No tunnel without proxy.");
        }
        this.tunnelled = TunnelType.TUNNELLED;
        this.secure    = secure;