package org.safehaus.subutai.common.util;


import java.security.KeyStore;
import java.util.Map;

import javax.ws.rs.core.Response;

import org.safehaus.subutai.common.exception.HTTPException;
import org.safehaus.subutai.common.security.crypto.keystore.KeyStoreData;
import org.safehaus.subutai.common.security.crypto.keystore.KeyStoreManager;
import org.safehaus.subutai.common.security.crypto.ssl.SSLManager;

import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.jaxrs.ext.form.Form;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;


public class RestUtil
{
    private static long defaultReceiveTimeout = 1000 * 60 * 5;
    private static long defaultConnectionTimeout = 1000 * 60;


    public static enum RequestType
    {
        GET, POST
    }


    public RestUtil()
    {
    }


    public RestUtil( final long defaultReceiveTimeout, final long defaultConnectionTimeout )
    {
        Preconditions.checkArgument( defaultReceiveTimeout > 0, "Receive timeout must be greater than 0" );
        Preconditions.checkArgument( defaultConnectionTimeout > 0, "Connection timeout must be greater than 0" );

        RestUtil.defaultReceiveTimeout = defaultReceiveTimeout;
        RestUtil.defaultConnectionTimeout = defaultConnectionTimeout;
    }


    public String request( RequestType requestType, String url, Map<String, String> params,
                           Map<String, String> headers ) throws HTTPException
    {

        Preconditions.checkNotNull( requestType, "Invalid request type" );
        Preconditions.checkArgument( !Strings.isNullOrEmpty( url ), "Invalid url" );

        WebClient client = null;
        Response response = null;
        try
        {
            client = createWebClient( url );
            Form form = new Form();
            if ( params != null )
            {
                for ( Map.Entry<String, String> entry : params.entrySet() )
                {
                    if ( requestType == RequestType.GET )
                    {
                        client.query( entry.getKey(), entry.getValue() );
                    }
                    else
                    {
                        form.set( entry.getKey(), entry.getValue() );
                    }
                }
            }
            if ( headers != null )
            {
                for ( Map.Entry<String, String> entry : headers.entrySet() )
                {
                    client.header( entry.getKey(), entry.getValue() );
                }
            }
            response = requestType == RequestType.GET ? client.get() : client.form( form );
            if ( !NumUtil.isIntBetween( response.getStatus(), 200, 299 ) )
            {
                if ( response.hasEntity() )
                {
                    throw new HTTPException( response.readEntity( String.class ) );
                }
                else
                {
                    throw new HTTPException( String.format( "Http status code: %d", response.getStatus() ) );
                }
            }
            else if ( response.hasEntity() )
            {
                return response.readEntity( String.class );
            }
        }
        finally
        {
            if ( response != null )
            {
                try
                {
                    response.close();
                }
                catch ( Exception ignore )
                {
                }
            }
            if ( client != null )
            {
                try
                {
                    client.close();
                }
                catch ( Exception ignore )
                {
                }
            }
        }

        return null;
    }


    public static WebClient createWebClient( String url )
    {
        WebClient client = WebClient.create( url );
        HTTPConduit httpConduit = ( HTTPConduit ) WebClient.getConfig( client ).getConduit();

        HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
        httpClientPolicy.setConnectionTimeout( defaultConnectionTimeout );
        httpClientPolicy.setReceiveTimeout( defaultReceiveTimeout );

        httpConduit.setClient( httpClientPolicy );
        return client;
    }


    public static WebClient createTrustedWebClient( String url )
    {
        WebClient client = WebClient.create( url );
        HTTPConduit httpConduit = ( HTTPConduit ) WebClient.getConfig( client ).getConduit();

        HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
        httpClientPolicy.setConnectionTimeout( defaultConnectionTimeout );
        httpClientPolicy.setReceiveTimeout( defaultReceiveTimeout );

        httpConduit.setClient( httpClientPolicy );

        SSLManager sslManager = new SSLManager( null, null, null, null );

        TLSClientParameters tlsClientParameters = new TLSClientParameters();
        tlsClientParameters.setDisableCNCheck( true );
        tlsClientParameters.setTrustManagers( sslManager.getClientFullTrustManagers() );
        httpConduit.setTlsClientParameters( tlsClientParameters );

        return client;
    }


    public static WebClient createTrustedWebClientWithAuth( String url )
    {
        WebClient client = WebClient.create( url );
        HTTPConduit httpConduit = ( HTTPConduit ) WebClient.getConfig( client ).getConduit();

        HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
        httpClientPolicy.setConnectionTimeout( defaultConnectionTimeout );
        httpClientPolicy.setReceiveTimeout( defaultReceiveTimeout );

        httpConduit.setClient( httpClientPolicy );

        KeyStoreManager keyStoreManager = new KeyStoreManager();
        KeyStoreData keyStoreData = new KeyStoreData();
        keyStoreData.setupKeyStorePx2();
        KeyStore keyStore = keyStoreManager.load( keyStoreData );

        KeyStoreData trustStoreData = new KeyStoreData();
        trustStoreData.setupTrustStorePx2();
        KeyStore trustStore = keyStoreManager.load( trustStoreData );

        SSLManager sslManager = new SSLManager( keyStore, keyStoreData, trustStore, trustStoreData );


        TLSClientParameters tlsClientParameters = new TLSClientParameters();
        tlsClientParameters.setDisableCNCheck( true );
        tlsClientParameters.setTrustManagers( sslManager.getClientTrustManagers() );
        tlsClientParameters.setKeyManagers( sslManager.getClientKeyManagers() );
        httpConduit.setTlsClientParameters( tlsClientParameters );

        return client;
    }
}

@@ -912,16 +912,66 @@
 0 * 60;%0A
+    private static int defaultMaxRetransmits = 3;%0A
 %0A%0A    pu
@@ -1157,16 +1157,42 @@
 nTimeout
+, final int maxRetransmits
  )%0A    %7B
@@ -1545,24 +1545,81 @@
 ionTimeout;%0A
+        RestUtil.defaultMaxRetransmits = maxRetransmits;%0A
     %7D%0A%0A%0A    
@@ -4477,32 +4477,101 @@
 eceiveTimeout );
+%0A        httpClientPolicy.setMaxRetransmits( defaultMaxRetransmits );
 %0A%0A        httpCo
@@ -5060,32 +5060,102 @@
 ceiveTimeout );%0A
+        httpClientPolicy.setMaxRetransmits( defaultMaxRetransmits );%0A%0A
 %0A        httpCon
@@ -6020,24 +6020,94 @@
 eTimeout );%0A
+        httpClientPolicy.setMaxRetransmits( defaultMaxRetransmits );%0A%0A
 %0A        htt

Fix Environment Manager bugs