/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package flex.messaging.services.http;

import flex.management.runtime.messaging.services.http.HTTPProxyAdapterControl;
import flex.messaging.Destination;
import flex.messaging.FlexContext;
import flex.messaging.MessageException;
import flex.messaging.config.ConfigMap;
import flex.messaging.messages.AcknowledgeMessage;
import flex.messaging.messages.HTTPMessage;
import flex.messaging.messages.Message;
import flex.messaging.messages.SOAPMessage;
import flex.messaging.services.ServiceAdapter;
import flex.messaging.services.http.proxy.AccessFilter;
import flex.messaging.services.http.proxy.ErrorFilter;
import flex.messaging.services.http.proxy.ProxyContext;
import flex.messaging.services.http.proxy.ProxyContextFilter;
import flex.messaging.services.http.proxy.ProxyFilter;
import flex.messaging.services.http.proxy.RequestFilter;
import flex.messaging.services.http.proxy.ResponseFilter;
import flex.messaging.services.http.proxy.SecurityFilter;
import flex.messaging.services.http.proxy.Target;
import flex.messaging.util.ClassUtil;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.params.HostParams;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.protocol.Protocol;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Adapter class for proxy services.
 */
public class HTTPProxyAdapter extends ServiceAdapter {
    // NOTE: any changes to this class should also be made to the corresponding version in the .NET.
    // The corresponding class is at src/dotNet/libs/FlexASPlib/Aspx/Proxy/ServiceProxyModule.cs


    public static final String CONTENT_TYPE_XML = "application/xml";

    public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";

    public static final int DEFAULT_COOKIE_LIMIT = 200;

    private static final String COOKIE_LIMIT = "cookie-limit";
    private static final String ALLOW_LAX_SSL = "allow-lax-ssl";
    private static final String CONTENT_CHUNKED = "content-chunked";
    private static final String ID = "id";
    private static final String CLASS = "class";
    private static final String PROPERTIES = "properties";
    private static final String REQUEST_HEADERS = "requestHeaders";
    private static final String RESPONSE_HEADERS = "responseHeaders";

    // HTTPProxyAdapter's properties
    protected boolean allowLaxSSL = false;
    protected boolean contentChunked = false;
    protected int cookieLimit = DEFAULT_COOKIE_LIMIT;
    protected ExternalProxySettings externalProxy;
    protected HTTPConnectionManagerSettings connectionManagerSettings;

    // HTTPProxyAdapter internal
    protected HttpConnectionManager connectionManager;
    protected HttpConnectionManagerParams connectionParams;
    protected ProxyFilter filterChain;
    protected UsernamePasswordCredentials proxyCredentials;

    private HTTPProxyAdapterControl controller;

    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     * Constructs an unmanaged <code>HTTPProxyAdapter</code> instance.
     */
    public HTTPProxyAdapter() {
        this(false);
    }

    /**
     * Constructs a <code>HTTPProxyAdapter</code> instance.
     *
     * @param enableManagement <code>true</code> if the <code>HTTPProxyAdapter</code> has a
     *                         corresponding MBean control for management; otherwise <code>false</code>.
     */
    public HTTPProxyAdapter(boolean enableManagement) {
        super(enableManagement);

        createFilterChain();
        externalProxy = new ExternalProxySettings();
        connectionManagerSettings = new HTTPConnectionManagerSettings();
    }

    //--------------------------------------------------------------------------
    //
    // Initialize, validate, start, and stop methods.
    //
    //--------------------------------------------------------------------------

    /**
     * Initializes the <code>HTTPProxyAdapter</code> with the properties.
     *
     * <pre>
     * &lt;connection-manager&gt;
     *     &lt;cookie-policy&gt;rfc2109&lt;/cookie-policy&gt;
     *     &lt;max-total-connections&gt;100&lt;/max-total-connections&gt;
     *     &lt;default-max-connections-per-host&gt;2&lt;/default-max-connections-per-host&gt;
     *     &lt;connection-timeout&gt;0&lt;/connection-timeout&gt;
     *     &lt;socket-timeout&gt;&lt;/socket-timeout&gt;
     *     &lt;stale-checking-enabled&gt;&lt;/stale-checking-enabled&gt;
     *     &lt;send-buffer-size&gt;&lt;/send-buffer-size&gt;
     *     &lt;receive-buffer-size&gt;&lt;/receive-buffer-size&gt;
     *     &lt;tcp-no-delay&gt;true&lt;/tcp-no-delay&gt;
     *     &lt;linger&gt;-1&lt;/linger&gt;
     *     &lt;max-per-host&gt;
     *           &lt;host&gt;...&lt;/host&gt;
     *           &lt;port&gt;80&lt;/port&gt;
     *           &lt;protocol&gt;http&lt;/protocol&gt;
     *           &lt;protocol-factory class="flex.messaging.services.http.ProtocolFactory"&gt;
     *               &lt;properties&gt;...&lt;/properties&gt;
     *           &lt;/protocol-factory&gt;
     *           &lt;max-connections&gt;2&lt;/max-connections&gt;
     *           &lt;proxy&gt;
     *               &lt;host&gt;...&lt;/host&gt;
     *               &lt;port&gt;80&lt;/port&gt;
     *           &lt;/proxy&gt;
     *           &lt;local-address&gt;...&lt;/local-address&gt;
     *           &lt;virtual-host&gt;...&lt;/virtual-host&gt;
     *     &lt;/max-per-host&gt;
     *  &lt;/connection-manager&gt;
     *  &lt;cookie-limit&gt;200&lt;/cookie-limit&gt;
     *  &lt;allow-lax-ssl&gt;false&lt;/allow-lax-ssl&gt;
     *  &lt;content-chunked&gt;false&lt;/content-chunked&gt;
     *  &lt;external-proxy&gt;
     *      &lt;server&gt;...&lt;/server&gt;
     *      &lt;port&gt;80&lt;/port&gt;
     *      &lt;nt-domain&gt;...&lt;/nt-domain&gt;
     *      &lt;username&gt;...&lt;/username&gt;
     *      &lt;password&gt;...&lt;/password&gt;
     *  &lt;/external-proxy&gt;
     *  </pre>
     *
     * @param id         The id of the destination.
     * @param properties Properties for the <code>Destination</code>.
     */
    public void initialize(String id, ConfigMap properties) {
        super.initialize(id, properties);

        if (properties == null || properties.size() == 0)
            return;

        // Connection Manager
        ConfigMap conn = properties.getPropertyAsMap(HTTPConnectionManagerSettings.CONNECTION_MANAGER, null);
        if (conn != null) {
            // Cookie policy.
            if (conn.getProperty(HTTPConnectionManagerSettings.COOKIE_POLICY) != null) {
                connectionManagerSettings.setCookiePolicy(conn.getPropertyAsString(HTTPConnectionManagerSettings.COOKIE_POLICY,
                        CookiePolicy.DEFAULT));
            }

            // Max Connections Total
            if (conn.getProperty(HTTPConnectionManagerSettings.MAX_TOTAL_CONNECTIONS) != null) {
                int maxTotal = conn.getPropertyAsInt(HTTPConnectionManagerSettings.MAX_TOTAL_CONNECTIONS,
                        MultiThreadedHttpConnectionManager.DEFAULT_MAX_TOTAL_CONNECTIONS);
                connectionManagerSettings.setMaxTotalConnections(maxTotal);
            }

            // Default Max Connections Per Host
            int defaultMaxConnsPerHost = MultiThreadedHttpConnectionManager.DEFAULT_MAX_HOST_CONNECTIONS;
            if (conn.getProperty(HTTPConnectionManagerSettings.DEFAULT_MAX_CONNECTIONS_PER_HOST) != null) {
                defaultMaxConnsPerHost = conn.getPropertyAsInt(HTTPConnectionManagerSettings.DEFAULT_MAX_CONNECTIONS_PER_HOST,
                        MultiThreadedHttpConnectionManager.DEFAULT_MAX_HOST_CONNECTIONS);
                connectionManagerSettings.setDefaultMaxConnectionsPerHost(defaultMaxConnsPerHost);
            }

            // Connection Timeout
            if (conn.getProperty(HTTPConnectionManagerSettings.CONNECTION_TIMEOUT) != null) {
                int timeout = conn.getPropertyAsInt(HTTPConnectionManagerSettings.CONNECTION_TIMEOUT, 0);
                if (timeout >= 0)
                    connectionManagerSettings.setConnectionTimeout(timeout);
            }

            // Socket Timeout
            if (conn.getProperty(HTTPConnectionManagerSettings.SOCKET_TIMEOUT) != null) {
                int timeout = conn.getPropertyAsInt(HTTPConnectionManagerSettings.SOCKET_TIMEOUT, 0);
                if (timeout >= 0)
                    connectionManagerSettings.setSocketTimeout(timeout);
            }

            // Stale Checking
            if (conn.getProperty(HTTPConnectionManagerSettings.STALE_CHECKING_ENABLED) != null) {
                boolean staleCheck = conn.getPropertyAsBoolean(HTTPConnectionManagerSettings.STALE_CHECKING_ENABLED, true);
                connectionManagerSettings.setStaleCheckingEnabled(staleCheck);
            }

            // Send Buffer Size
            if (conn.getProperty(HTTPConnectionManagerSettings.SEND_BUFFER_SIZE) != null) {
                int bufferSize = conn.getPropertyAsInt(HTTPConnectionManagerSettings.SEND_BUFFER_SIZE, 0);
                if (bufferSize > 0)
                    connectionManagerSettings.setSendBufferSize(bufferSize);
            }

            // Send Receive Size
            if (conn.getProperty(HTTPConnectionManagerSettings.RECEIVE_BUFFER_SIZE) != null) {
                int bufferSize = conn.getPropertyAsInt(HTTPConnectionManagerSettings.RECEIVE_BUFFER_SIZE, 0);
                if (bufferSize > 0)
                    connectionManagerSettings.setReceiveBufferSize(bufferSize);
            }

            // TCP No Delay (Nagel's Algorithm)
            if (conn.getProperty(HTTPConnectionManagerSettings.TCP_NO_DELAY) != null) {
                boolean noNagel = conn.getPropertyAsBoolean(HTTPConnectionManagerSettings.TCP_NO_DELAY, true);
                connectionManagerSettings.setTcpNoDelay(noNagel);
            }

            // Linger
            if (conn.getProperty(HTTPConnectionManagerSettings.LINGER) != null) {
                int linger = conn.getPropertyAsInt(HTTPConnectionManagerSettings.LINGER, -1);
                connectionManagerSettings.setLinger(linger);
            }

            // Max Connections Per Host
            List hosts = conn.getPropertyAsList(HTTPConnectionManagerSettings.MAX_PER_HOST, null);
            if (hosts != null) {
                List hostSettings = new ArrayList();
                Iterator it = hosts.iterator();
                while (it.hasNext()) {
                    ConfigMap maxPerHost = (ConfigMap) it.next();
                    HostConfigurationSettings hostConfig = new HostConfigurationSettings();

                    // max-connections
                    if (maxPerHost.getProperty(HostConfigurationSettings.MAX_CONNECTIONS) != null) {
                        int maxConn = maxPerHost.getPropertyAsInt(HostConfigurationSettings.MAX_CONNECTIONS,
                                defaultMaxConnsPerHost);
                        hostConfig.setMaximumConnections(maxConn);
                    }

                    // host
                    if (maxPerHost.getProperty(HostConfigurationSettings.HOST) != null) {
                        String host = maxPerHost.getPropertyAsString(HostConfigurationSettings.HOST, null);
                        hostConfig.setHost(host);
                        if (host != null) {
                            // port
                            int port = maxPerHost.getPropertyAsInt(HostConfigurationSettings.PORT, 0);
                            hostConfig.setPort(port);

                            // protocol-factory
                            ConfigMap factoryMap = maxPerHost.getPropertyAsMap(HostConfigurationSettings.PROTOCOL_FACFORY, null);
                            if (factoryMap != null) {
                                String className = factoryMap.getPropertyAsString(CLASS, null);
                                if (className != null) {
                                    Class factoryClass = ClassUtil.createClass(className);
                                    ProtocolFactory protocolFactory = (ProtocolFactory) ClassUtil.createDefaultInstance(factoryClass, ProtocolFactory.class);
                                    String factoryId = factoryMap.getPropertyAsString(ID, host + "_protocol_factory");
                                    ConfigMap protocolProperties = factoryMap.getPropertyAsMap(PROPERTIES, null);
                                    protocolFactory.initialize(factoryId, protocolProperties);
                                }
                            }
                            // protocol
                            else {
                                String protocol = maxPerHost.getPropertyAsString(HostConfigurationSettings.PROTOCOL, null);
                                hostConfig.setProtocol(protocol);
                            }
                        }
                    }

                    // proxy
                    ConfigMap proxy = maxPerHost.getPropertyAsMap(HostConfigurationSettings.PROXY, null);
                    if (proxy != null) {
                        // host
                        String proxyHost = proxy.getPropertyAsString(HostConfigurationSettings.HOST, null);
                        hostConfig.setProxyHost(proxyHost);
                        if (proxyHost != null) {
                            // port
                            int port = proxy.getPropertyAsInt(HostConfigurationSettings.PORT, 0);
                            hostConfig.setProxyPort(port);
                        }
                    }

                    // local-address
                    if (maxPerHost.getProperty(HostConfigurationSettings.LOCAL_ADDRESS) != null) {
                        String localAddress = maxPerHost.getPropertyAsString(HostConfigurationSettings.LOCAL_ADDRESS, null);
                        hostConfig.setLocalAddress(localAddress);
                    }

                    // virtual-host
                    if (maxPerHost.getProperty(HostConfigurationSettings.VIRTUAL_HOST) != null) {
                        String virtualHost = maxPerHost.getPropertyAsString(HostConfigurationSettings.VIRTUAL_HOST, null);
                        hostConfig.setVirtualHost(virtualHost);
                    }
                    hostSettings.add(hostConfig);
                }

                if (hostSettings.size() > 0)
                    connectionManagerSettings.setMaxConnectionsPerHost(hostSettings);
            }
            setConnectionManagerSettings(connectionManagerSettings);
        }

        // Cookie Limit
        if (properties.getProperty(COOKIE_LIMIT) != null) {
            int cl = properties.getPropertyAsInt(COOKIE_LIMIT, DEFAULT_COOKIE_LIMIT);
            setCookieLimit(cl);
        }

        // Allow Lax SSL
        if (properties.getProperty(ALLOW_LAX_SSL) != null) {
            boolean lax = properties.getPropertyAsBoolean(ALLOW_LAX_SSL, false);
            setAllowLaxSSL(lax);
        }

        // Content Chunked
        if (properties.getProperty(CONTENT_CHUNKED) != null) {
            boolean ch = properties.getPropertyAsBoolean(CONTENT_CHUNKED, false);
            setContentChunked(ch);
        }

        // External Proxy
        ConfigMap extern = properties.getPropertyAsMap(ExternalProxySettings.EXTERNAL_PROXY, null);
        if (extern != null) {
            ExternalProxySettings proxy = new ExternalProxySettings();

            String proxyServer = extern.getPropertyAsString(ExternalProxySettings.SERVER, null);
            proxy.setProxyServer(proxyServer);
            int proxyPort = extern.getPropertyAsInt(ExternalProxySettings.PORT, ExternalProxySettings.DEFAULT_PROXY_PORT);
            proxy.setProxyPort(proxyPort);
            String ntdomain = extern.getPropertyAsString(ExternalProxySettings.NT_DOMAIN, null);
            proxy.setNTDomain(ntdomain);
            String username = extern.getPropertyAsString(ExternalProxySettings.USERNAME, null);
            proxy.setUsername(username);
            String password = extern.getPropertyAsString(ExternalProxySettings.PASSWORD, null);
            proxy.setPassword(password);

            setExternalProxySettings(proxy);
        }
    }

    //--------------------------------------------------------------------------
    //
    // Public Getters and Setters for Destination properties
    //
    //--------------------------------------------------------------------------

    /**
     * Returns <code>allow-lax-ssl</code> property.
     *
     * @return <code>true</code> if <code>allow-lax-ssl</code> property is
     * <code>true</code>; otherwise <code>false</code>.
     */
    public boolean isAllowLaxSSL() {
        return allowLaxSSL;
    }

    /**
     * Sets <code>allow-lax-ssl</code> property which determines if self-signed
     * certificates are allowed; should not be used in production.
     * Default <code>false</code>.
     *
     * @param allowLaxSSL Whether lax SSL should be allowed.
     */
    public void setAllowLaxSSL(boolean allowLaxSSL) {
        this.allowLaxSSL = allowLaxSSL;
    }

    /**
     * Returns the <code>content-chunked</code> property.
     *
     * @return <code>true</code> if <code>content-chunked</code> property is
     * <code>true</code>; otherwise <code>false</code>.
     */
    public boolean isContentChunked() {
        return contentChunked;
    }

    /**
     * Sets the <code>content-chunked</code> property. Default <code>false</code>.
     *
     * @param contentChunked The <code>content-chunked</code> property.
     */
    public void setContentChunked(boolean contentChunked) {
        this.contentChunked = contentChunked;
    }

    /**
     * Returns the <code>cookie-limit</code> property.
     *
     * @return The <code>cookie-limit</code> property.
     */
    public int getCookieLimit() {
        return cookieLimit;
    }

    /**
     * Sets the <code>cookie-limit</code> property. Default 200.
     *
     * @param cookieLimit The cookie limit for the proxy.
     */
    public void setCookieLimit(int cookieLimit) {
        this.cookieLimit = cookieLimit;
    }

    /**
     * Casts the <code>Destination</code> into <code>HTTPProxyDestination</code>
     * and calls super.setDestination.
     *
     * @param destination The HTTP proxy destination.
     */
    public void setDestination(Destination destination) {
        Destination dest = (HTTPProxyDestination) destination;
        super.setDestination(dest);
    }

    /**
     * Returns <code>ExternalProxySettings</code>.
     *
     * @return the <code>ExternalProxySettings</code>
     */
    public ExternalProxySettings getExternalProxySettings() {
        return externalProxy;
    }

    /**
     * Sets <code>ExternalProxySettings</code>.
     *
     * @param externalProxy The external proxy settings.
     */
    public void setExternalProxySettings(ExternalProxySettings externalProxy) {
        this.externalProxy = externalProxy;
        initExternalProxy(externalProxy);
    }

    /**
     * Returns <code>HTTPConnectionManagerSettings</code>.
     *
     * @return the <code>HTTPConnectionManagerSettings</code>
     */
    public HTTPConnectionManagerSettings getConnectionManagerSettings() {
        return connectionManagerSettings;
    }

    /**
     * Sets <code>HTTPConnectionManagerSettings</code>.
     *
     * @param connectionManagerSettings The connection manager settings.
     */
    public void setConnectionManagerSettings(HTTPConnectionManagerSettings connectionManagerSettings) {
        this.connectionManagerSettings = connectionManagerSettings;
        initHttpConnectionManagerParams(connectionManagerSettings);
        connectionManager = new MultiThreadedHttpConnectionManager();
        connectionManager.setParams(connectionParams);
    }

    //--------------------------------------------------------------------------
    //
    // Other public APIs
    //
    //--------------------------------------------------------------------------

    /**
     * {@inheritDoc}
     */
    public Object invoke(Message msg) {
        HTTPMessage message = (HTTPMessage) msg;

        ProxyContext context = new ProxyContext();

        // SOAPMessages should be sent through the SOAPProxyAdapter, but
        // the default destination may be just to the HTTPProxyAdapter.
        // We'll update the context just in case....
        if (message instanceof SOAPMessage)
            context.setSoapRequest(true);
        else
            context.setSoapRequest(false);

        setupContext(context, message);

        try {
            filterChain.invoke(context);

            //TODO: Do we want a return type that encapsulates the response data?

            // OUTPUT
            AcknowledgeMessage ack = new AcknowledgeMessage();
            ack.setBody(context.getResponse());
            ack.setHeader(Message.STATUS_CODE_HEADER, context.getStatusCode());

            if (context.getRecordHeaders()) {
                ack.setHeader(REQUEST_HEADERS, context.getRequestHeaders());
                ack.setHeader(RESPONSE_HEADERS, context.getResponseHeaders());
            }

            return ack;
        } catch (MessageException ex) {
            throw ex;
        } catch (Throwable t) {
            // this should never happen- ErrorFilter should catch everything
            t.printStackTrace();
            throw new MessageException(t.toString());
        }
    }

    //--------------------------------------------------------------------------
    //
    // Protected/private APIs
    //
    //--------------------------------------------------------------------------

    protected void setupContext(ProxyContext context, HTTPMessage message) {
        Target target = new Target();
        context.setTarget(target);

        context.setExternalProxySettings(externalProxy);
        context.setProxyCredentials(proxyCredentials);
        context.setConnectionManager(connectionManager);
        context.setAllowLaxSSL(allowLaxSSL);
        context.setContentChunked(contentChunked);
        context.setRecordHeaders(message.getRecordHeaders());
        context.setCookieLimit(cookieLimit);
        context.setHttpRequest(FlexContext.getHttpRequest() != null);

        //TODO: QUESTION: Pete, Send HTTPHeaders as real headers

        // INPUT
        String url = message.getUrl();
        context.setUrl(url);

        Map httpHeaders = message.getHttpHeaders();
        context.setHeaders(httpHeaders);

        String method = message.getMethod();
        context.setMethod(method);

        String contentType = message.getContentType();
        context.setContentType(contentType);

        Object body = message.getBody();
        context.setBody(body);

        target.setRemoteUsername(message.getRemoteUsername());
        target.setRemotePassword(message.getRemotePassword());

        HTTPProxyDestination destination = (HTTPProxyDestination) getDestination();
        target.setUseCustomAuthentication(destination.isUseCustomAuthentication());

        if (destination.getProtocolFactory() != null) {
            ProtocolFactory protocolFactory = destination.getProtocolFactory();
            context.setProtocol(protocolFactory.getProtocol());
        }
    }

    /**
     * Invoked automatically to allow the <code>HTTPProxyAdapter</code> to setup its corresponding
     * MBean control.
     *
     * @param destination The <code>Destination</code> that manages this <code>HTTPProxyAdapter</code>.
     */
    protected void setupAdapterControl(Destination destination) {
        controller = new HTTPProxyAdapterControl(this, destination.getControl());
        controller.register();
        setControl(controller);
    }

    /**
     * Create default filter chain or return current one if already present.
     */
    private ProxyFilter createFilterChain() {
        if (filterChain == null) {
            // catch-all error filter
            ErrorFilter errorFilter = new ErrorFilter();
            // check proxy access
            AccessFilter accessFilter = new AccessFilter();
            // set up ProxyContext
            ProxyContextFilter contextFilter = new ProxyContextFilter();
            // sends out response after further filters
            ResponseFilter responseFilter = new ResponseFilter();
            // deals with credentials
            SecurityFilter securityFilter = new SecurityFilter();
            // sends out the request
            RequestFilter requestFilter = new RequestFilter();

            errorFilter.setNext(accessFilter);
            accessFilter.setNext(contextFilter);
            contextFilter.setNext(responseFilter);
            responseFilter.setNext(securityFilter);
            securityFilter.setNext(requestFilter);

            filterChain = errorFilter;
        }
        return filterChain;
    }

    private void initExternalProxy(ExternalProxySettings ep) {
        if (externalProxy != null) {

            String proxyServer = externalProxy.getProxyServer();
            String proxyUsername = externalProxy.getUsername();

            if (proxyUsername != null) {
                String proxyPassword = externalProxy.getPassword();
                String proxyDomain = externalProxy.getNTDomain();
                if (proxyDomain != null) {
                    proxyCredentials = new NTCredentials(proxyUsername, proxyPassword, proxyServer, proxyDomain);
                } else {
                    proxyCredentials = new UsernamePasswordCredentials(proxyUsername, proxyPassword);
                }
            }
        }
    }

    private void initHttpConnectionManagerParams(HTTPConnectionManagerSettings settings) {
        connectionParams = new HttpConnectionManagerParams();
        connectionParams.setMaxTotalConnections(settings.getMaxTotalConnections());
        connectionParams.setDefaultMaxConnectionsPerHost(settings.getDefaultMaxConnectionsPerHost());

        if (!settings.getCookiePolicy().equals(CookiePolicy.DEFAULT)) {
            HttpClientParams httpClientParams = (HttpClientParams) connectionParams.getDefaults();
            httpClientParams.setCookiePolicy(settings.getCookiePolicy());
        }

        if (settings.getConnectionTimeout() >= 0)
            connectionParams.setConnectionTimeout(settings.getConnectionTimeout());

        if (settings.getSocketTimeout() >= 0)
            connectionParams.setSoTimeout(settings.getSocketTimeout());

        connectionParams.setStaleCheckingEnabled(settings.isStaleCheckingEnabled());

        if (settings.getSendBufferSize() > 0)
            connectionParams.setSendBufferSize(settings.getSendBufferSize());

        if (settings.getReceiveBufferSize() > 0)
            connectionParams.setReceiveBufferSize(settings.getReceiveBufferSize());

        connectionParams.setTcpNoDelay(settings.isTcpNoDelay());
        connectionParams.setLinger(settings.getLinger());

        if (settings.getMaxConnectionsPerHost() != null) {
            Iterator it = settings.getMaxConnectionsPerHost().iterator();
            while (it.hasNext()) {
                HostConfigurationSettings hcs = (HostConfigurationSettings) it.next();
                HostConfiguration hostConfig = new HostConfiguration();

                if (hcs.getProtocol() != null) {
                    Protocol protocol = Protocol.getProtocol(hcs.getProtocol());
                    hostConfig.setHost(hcs.getHost(), hcs.getPort(), protocol);
                } else if (hcs.getProtocolFactory() != null) {
                    Protocol protocol = hcs.getProtocolFactory().getProtocol();
                    if (hcs.getPort() > 0)
                        hostConfig.setHost(hcs.getHost(), hcs.getPort(), protocol);
                    else
                        hostConfig.setHost(hcs.getHost(), protocol.getDefaultPort(), protocol);
                } else {
                    if (hcs.getPort() > 0)
                        hostConfig.setHost(hcs.getHost(), hcs.getPort());
                    else
                        hostConfig.setHost(hcs.getHost());
                }

                if (hcs.getVirtualHost() != null) {
                    HostParams params = hostConfig.getParams();
                    if (params != null)
                        params.setVirtualHost(hcs.getVirtualHost());
                }

                if (hcs.getProxyHost() != null) {
                    hostConfig.setProxy(hcs.getProxyHost(), hcs.getProxyPort());
                }

                try {
                    InetAddress addr = InetAddress.getByName(hcs.getLocalAddress());
                    hostConfig.setLocalAddress(addr);
                } catch (UnknownHostException ex) {
                }
                connectionParams.setMaxConnectionsPerHost(hostConfig, hcs.getMaximumConnections());
            }
        }
    }
}
