// ========================================================================
// Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================

package org.eclipse.jetty.client;

import java.io.IOException;

import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.Buffer;

/**
 * RedirectListener
 *
 * Detect and handle the redirect responses
 */
public class RedirectListener extends HttpEventListenerWrapper
{
    private final HttpExchange _exchange;
    private HttpDestination _destination;
    private String _location;
    private int _attempts;
    private boolean _requestComplete;
    private boolean _responseComplete;
    private boolean _redirected;

    public RedirectListener(HttpDestination destination, HttpExchange ex)
    {
        // Start of sending events through to the wrapped listener
        // Next decision point is the onResponseStatus
        super(ex.getEventListener(),true);

        _destination = destination;
        _exchange = ex;
    }

    @Override
    public void onResponseStatus( Buffer version, int status, Buffer reason )
        throws IOException
    {
        _redirected = ((status == HttpStatus.MOVED_PERMANENTLY_301 ||
                        status == HttpStatus.MOVED_TEMPORARILY_302) &&
                       _attempts < _destination.getHttpClient().maxRedirects());

        if (_redirected)
        {
            setDelegatingRequests(false);
            setDelegatingResponses(false);
        }

        super.onResponseStatus(version,status,reason);
    }


    @Override
    public void onResponseHeader( Buffer name, Buffer value )
        throws IOException
    {
        if (_redirected)
        {
            int header = HttpHeaders.CACHE.getOrdinal(name);
            switch (header)
            {
                case HttpHeaders.LOCATION_ORDINAL:
                    _location = value.toString();
                    break;
            }
        }
        super.onResponseHeader(name,value);
    }

    @Override
    public void onRequestComplete() throws IOException
    {
        _requestComplete = true;

        if (checkExchangeComplete())
        {
            super.onRequestComplete();
        }
    }

    @Override
    public void onResponseComplete() throws IOException
    {
        _responseComplete = true;

        if (checkExchangeComplete())
        {
            super.onResponseComplete();
        }
    }

    public boolean checkExchangeComplete()
        throws IOException
    {
        if (_redirected && _requestComplete && _responseComplete)
        {
            if (_location != null)
            {
                if (_location.indexOf("://")>0)
                    _exchange.setURL(_location);
                else
                    _exchange.setRequestURI(_location);

                // destination may have changed
                boolean isHttps = HttpSchemes.HTTPS.equals(String.valueOf(_exchange.getScheme()));
                HttpDestination destination=_destination.getHttpClient().getDestination(_exchange.getAddress(),isHttps);

                if (_destination==destination)
                    _destination.resend(_exchange);
                else
                {
                    // unwrap to find ultimate listener.
                    HttpEventListener listener=this;
                    while(listener instanceof HttpEventListenerWrapper)
                        listener=((HttpEventListenerWrapper)listener).getEventListener();
                    //reset the listener
                    _exchange.getEventListener().onRetry();
                    _exchange.reset();
                    _exchange.setEventListener(listener);

                    // Set the new Host header
                    Address adr = _exchange.getAddress();
                    int port = adr.getPort();
                    StringBuilder hh = new StringBuilder( 64 );
                    hh.append( adr.getHost() );
                    if( !( ( port == 80 && !isHttps ) ||
                           ( port == 443 && isHttps ) ) ) {
                        hh.append( ':' );
                        hh.append( port );
                    }
                    _exchange.setRequestHeader( HttpHeaders.HOST, hh.toString() );

                    destination.send(_exchange);
                }

                return false;
            }
            else
            {
                setDelegationResult(false);
            }
        }

        return true;
    }

    public void onRetry()
    {
        _redirected=false;
        _attempts++;

        setDelegatingRequests(true);
        setDelegatingResponses(true);

        _requestComplete=false;
        _responseComplete=false;

        super.onRetry();
    }

    /**
     * Delegate failed connection
     */
    @Override
    public void onConnectionFailed( Throwable ex )
    {
        setDelegatingRequests(true);
        setDelegatingResponses(true);

        super.onConnectionFailed( ex );
    }

    /**
     * Delegate onException
     */
    @Override
    public void onException( Throwable ex )
    {
        setDelegatingRequests(true);
        setDelegatingResponses(true);

        super.onException( ex );
    }
}

@@ -3347,16 +3347,34 @@
 //%22)%3E0)%0A
+                %7B%0A
         
@@ -3410,24 +3410,42 @@
 _location);%0A
+                %7D%0A
             
@@ -3445,32 +3445,50 @@
            else%0A
+                %7B%0A
                 
@@ -3526,16 +3526,34 @@
 cation);
+%0A                %7D
 %0A%0A      
@@ -3862,16 +3862,34 @@
 nation)%0A
+                %7B%0A
         
@@ -3924,32 +3924,50 @@
 end(_exchange);%0A
+                %7D%0A
                 
@@ -4167,24 +4167,46 @@
 nerWrapper)%0A
+                    %7B%0A
             
@@ -4279,24 +4279,67 @@
 Listener();%0A
+                    %7D%0A                    %0A
             
@@ -4602,17 +4602,21 @@
 dress ad
-r
+dress
  = _exch
@@ -4667,17 +4667,21 @@
 ort = ad
-r
+dress
 .getPort
@@ -4719,17 +4719,25 @@
 uilder h
-h
+ostHeader
  = new S
@@ -4769,33 +4769,41 @@
                h
-h
+ostHeader
 .append( adr.get
@@ -4797,17 +4797,21 @@
 pend( ad
-r
+dress
 .getHost
@@ -4876,35 +4876,8 @@
 ) %7C%7C
-%0A                          
  ( p
@@ -4904,16 +4904,37 @@
 s ) ) ) 
+%0A                    
 %7B%0A      
@@ -4944,33 +4944,41 @@
                h
-h
+ostHeader
 .append( ':' );%0A
@@ -5002,17 +5002,25 @@
        h
-h
+ostHeader
 .append(
@@ -5042,32 +5042,53 @@
               %7D%0A
+                    %0A
                 
@@ -5138,17 +5138,25 @@
 .HOST, h
-h
+ostHeader
 .toStrin

fix some formatting issues with code conventions