flex.messaging.services.http.HTTPProxyAdapter.java Source code

Java tutorial

Introduction

Here is the source code for flex.messaging.services.http.HTTPProxyAdapter.java

Source

/*
 * 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());
            }
        }
    }
}