/*
 * 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 org.apache.axis2.transport.http.impl.httpclient3;

import java.net.URL;
import java.util.StringTokenizer;

import javax.xml.namespace.QName;

import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.transport.http.HTTPTransportConstants;
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @deprecated  use {@link HTTPProxyConfigurator}
 */
@Deprecated
public class HTTPProxcyConfigurator {

    private static Log log = LogFactory.getLog(HTTPProxcyConfigurator.class);

    /**
     * Configure HTTP Proxy settings of commons-httpclient HostConfiguration.
     * Proxy settings can be get from axis2.xml, Java proxy settings or can be
     * override through property in message context.
     * <p/>
     * HTTP Proxy setting element format: <parameter name="Proxy">
     * <Configuration> <ProxyHost>example.org</ProxyHost>
     * <ProxyPort>3128</ProxyPort> <ProxyUser>EXAMPLE/John</ProxyUser>
     * <ProxyPassword>password</ProxyPassword> <Configuration> <parameter>
     * 
     * @param messageContext
     *            in message context for
     * @param httpClient
     *            commons-httpclient instance
     * @param config
     *            commons-httpclient HostConfiguration
     * @throws AxisFault
     *             if Proxy settings are invalid
     */
    public static void configure(MessageContext messageContext, HttpClient httpClient,
            HostConfiguration config) throws AxisFault {

        Credentials proxyCredentials = null;
        String proxyHost = null;
        String nonProxyHosts = null;
        Integer proxyPort = -1;
        String proxyUser = null;
        String proxyPassword = null;

        // Getting configuration values from Axis2.xml
        Parameter proxySettingsFromAxisConfig = messageContext.getConfigurationContext()
                .getAxisConfiguration().getParameter(HTTPTransportConstants.ATTR_PROXY);
        if (proxySettingsFromAxisConfig != null) {
            OMElement proxyConfiguration = getProxyConfigurationElement(proxySettingsFromAxisConfig);
            proxyHost = getProxyHost(proxyConfiguration);
            proxyPort = getProxyPort(proxyConfiguration);
            proxyUser = getProxyUser(proxyConfiguration);
            proxyPassword = getProxyPassword(proxyConfiguration);
            if (proxyUser != null) {
                if (proxyPassword == null) {
                    proxyPassword = "";
                }
                int proxyUserDomainIndex = proxyUser.indexOf("\\");
                if (proxyUserDomainIndex > 0) {
                    String domain = proxyUser.substring(0, proxyUserDomainIndex);
                    if (proxyUser.length() > proxyUserDomainIndex + 1) {
                        String user = proxyUser.substring(proxyUserDomainIndex + 1);
                        proxyCredentials = new NTCredentials(user, proxyPassword, proxyHost, domain);
                    }
                }
                proxyCredentials = new UsernamePasswordCredentials(proxyUser, proxyPassword);
            }

        }

        // If there is runtime proxy settings, these settings will override
        // settings from axis2.xml
        HttpTransportProperties.ProxyProperties proxyProperties = (HttpTransportProperties.ProxyProperties) messageContext
                .getProperty(HTTPConstants.PROXY);
        if (proxyProperties != null) {
            String proxyHostProp = proxyProperties.getProxyHostName();
            if (proxyHostProp == null || proxyHostProp.length() <= 0) {
                throw new AxisFault("HTTP Proxy host is not available. Host is a MUST parameter");
            } else {
                proxyHost = proxyHostProp;
            }
            proxyPort = proxyProperties.getProxyPort();

            // Overriding credentials
            String userName = proxyProperties.getUserName();
            String password = proxyProperties.getPassWord();
            String domain = proxyProperties.getDomain();

            if (userName != null && password != null && domain != null) {
                proxyCredentials = new NTCredentials(userName, password, proxyHost, domain);
            } else if (userName != null && domain == null) {
                proxyCredentials = new UsernamePasswordCredentials(userName, password);
            }

        }

        // Overriding proxy settings if proxy is available from JVM settings
        String host = System.getProperty(HTTPTransportConstants.HTTP_PROXY_HOST);
        if (host != null) {
            proxyHost = host;
        }

        String port = System.getProperty(HTTPTransportConstants.HTTP_PROXY_PORT);
        if (port != null) {
            proxyPort = Integer.parseInt(port);
        }

        if (proxyCredentials != null) {
            httpClient.getParams().setAuthenticationPreemptive(true);
            HttpState cachedHttpState = (HttpState) messageContext
                    .getProperty(HTTPConstants.CACHED_HTTP_STATE);
            if (cachedHttpState != null) {
                httpClient.setState(cachedHttpState);
            }
            httpClient.getState().setProxyCredentials(AuthScope.ANY, proxyCredentials);
        }
        config.setProxy(proxyHost, proxyPort);
    }

    private static OMElement getProxyConfigurationElement(Parameter proxySettingsFromAxisConfig)
            throws AxisFault {
        OMElement proxyConfigurationElement = proxySettingsFromAxisConfig.getParameterElement()
                .getFirstElement();
        if (proxyConfigurationElement == null) {
            log.error(HTTPTransportConstants.PROXY_CONFIGURATION_NOT_FOUND);
            throw new AxisFault(HTTPTransportConstants.PROXY_CONFIGURATION_NOT_FOUND);
        }
        return proxyConfigurationElement;
    }

    private static String getProxyHost(OMElement proxyConfiguration) throws AxisFault {
        OMElement proxyHostElement = proxyConfiguration.getFirstChildWithName(new QName(
                HTTPTransportConstants.PROXY_HOST_ELEMENT));
        if (proxyHostElement == null) {
            log.error(HTTPTransportConstants.PROXY_HOST_ELEMENT_NOT_FOUND);
            throw new AxisFault(HTTPTransportConstants.PROXY_HOST_ELEMENT_NOT_FOUND);
        }
        String proxyHost = proxyHostElement.getText();
        if (proxyHost == null) {
            log.error(HTTPTransportConstants.PROXY_HOST_ELEMENT_WITH_EMPTY_VALUE);
            throw new AxisFault(HTTPTransportConstants.PROXY_HOST_ELEMENT_WITH_EMPTY_VALUE);
        }
        return proxyHost;
    }

    private static Integer getProxyPort(OMElement proxyConfiguration) throws AxisFault {
        OMElement proxyPortElement = proxyConfiguration.getFirstChildWithName(new QName(
                HTTPTransportConstants.PROXY_PORT_ELEMENT));
        if (proxyPortElement == null) {
            log.error(HTTPTransportConstants.PROXY_PORT_ELEMENT_NOT_FOUND);
            throw new AxisFault(HTTPTransportConstants.PROXY_PORT_ELEMENT_NOT_FOUND);
        }
        String proxyPort = proxyPortElement.getText();
        if (proxyPort == null) {
            log.error(HTTPTransportConstants.PROXY_PORT_ELEMENT_WITH_EMPTY_VALUE);
            throw new AxisFault(HTTPTransportConstants.PROXY_PORT_ELEMENT_WITH_EMPTY_VALUE);
        }
        return Integer.parseInt(proxyPort);
    }

    private static String getProxyUser(OMElement proxyConfiguration) {
        OMElement proxyUserElement = proxyConfiguration.getFirstChildWithName(new QName(
                HTTPTransportConstants.PROXY_USER_ELEMENT));
        if (proxyUserElement == null) {
            return null;
        }
        String proxyUser = proxyUserElement.getText();
        if (proxyUser == null) {
            log.warn("Empty user name element in HTTP Proxy settings.");
            return null;
        }

        return proxyUser;
    }

    private static String getProxyPassword(OMElement proxyConfiguration) {
        OMElement proxyPasswordElement = proxyConfiguration.getFirstChildWithName(new QName(
                HTTPTransportConstants.PROXY_PASSWORD_ELEMENT));
        if (proxyPasswordElement == null) {
            return null;
        }
        String proxyUser = proxyPasswordElement.getText();
        if (proxyUser == null) {
            log.warn("Empty user name element in HTTP Proxy settings.");
            return null;
        }

        return proxyUser;
    }

    /**
     * Check whether http proxy is configured or active. This is not a deep
     * check.
     * 
     * @param messageContext
     *            in message context
     * @param targetURL
     *            URL of the edpoint which we are sending the request
     * @return true if proxy is enabled, false otherwise
     */
    public static boolean isProxyEnabled(MessageContext messageContext, URL targetURL) {
        boolean proxyEnabled = false;

        Parameter param = messageContext.getConfigurationContext().getAxisConfiguration()
                .getParameter(HTTPTransportConstants.ATTR_PROXY);

        // If configuration is over ridden
        Object obj = messageContext.getProperty(HTTPConstants.PROXY);

        // From Java Networking Properties
        String sp = System.getProperty(HTTPTransportConstants.HTTP_PROXY_HOST);

        if (param != null || obj != null || sp != null) {
            proxyEnabled = true;
        }

        boolean isNonProxyHost = validateNonProxyHosts(targetURL.getHost());

        return proxyEnabled && !isNonProxyHost;
    }

    /**
     * Validates for names that shouldn't be listered as proxies. The
     * http.nonProxyHosts can be set to specify the hosts which should be
     * connected to directly (not through the proxy server). The value of the
     * http.nonProxyHosts property can be a list of hosts, each separated by a
     * |; it can also take a regular expression for matches; for example:
     * *.sfbay.sun.com would match any fully qualified hostname in the sfbay
     * domain.
     * <p/>
     * For more information refer to :
     * http://java.sun.com/features/2002/11/hilevel_network.html
     * <p/>
     * false : validation fail : User can use the proxy true : validation pass ;
     * User can't use the proxy
     * 
     * @return boolean
     */
    private static boolean validateNonProxyHosts(String host) {
        // From system property http.nonProxyHosts
        String nonProxyHosts = System.getProperty(HTTPTransportConstants.HTTP_NON_PROXY_HOSTS);
        return isHostInNonProxyList(host, nonProxyHosts);
    }

    /**
     * Check if the specified host is in the list of non proxy hosts.
     * 
     * @param host
     *            host name
     * @param nonProxyHosts
     *            string containing the list of non proxy hosts
     * @return true/false
     */
    public static boolean isHostInNonProxyList(String host, String nonProxyHosts) {
        if ((nonProxyHosts == null) || (host == null)) {
            return false;
        }

        /*
         * The http.nonProxyHosts system property is a list enclosed in double
         * quotes with items separated by a vertical bar.
         */
        StringTokenizer tokenizer = new StringTokenizer(nonProxyHosts, "|\"");

        while (tokenizer.hasMoreTokens()) {
            String pattern = tokenizer.nextToken();
            if (match(pattern, host, false)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Matches a string against a pattern. The pattern contains two special
     * characters: '*' which means zero or more characters,
     * 
     * @param pattern
     *            the (non-null) pattern to match against
     * @param str
     *            the (non-null) string that must be matched against the pattern
     * @param isCaseSensitive
     * @return <code>true</code> when the string matches against the pattern,
     *         <code>false</code> otherwise.
     */
    private static boolean match(String pattern, String str, boolean isCaseSensitive) {

        char[] patArr = pattern.toCharArray();
        char[] strArr = str.toCharArray();
        int patIdxStart = 0;
        int patIdxEnd = patArr.length - 1;
        int strIdxStart = 0;
        int strIdxEnd = strArr.length - 1;
        char ch;
        boolean containsStar = false;

        for (int i = 0; i < patArr.length; i++) {
            if (patArr[i] == '*') {
                containsStar = true;
                break;
            }
        }
        if (!containsStar) {

            // No '*'s, so we make a shortcut
            if (patIdxEnd != strIdxEnd) {
                return false; // Pattern and string do not have the same size
            }
            for (int i = 0; i <= patIdxEnd; i++) {
                ch = patArr[i];
                if (isCaseSensitive && (ch != strArr[i])) {
                    return false; // Character mismatch
                }
                if (!isCaseSensitive
                        && (Character.toUpperCase(ch) != Character.toUpperCase(strArr[i]))) {
                    return false; // Character mismatch
                }
            }
            return true; // String matches against pattern
        }
        if (patIdxEnd == 0) {
            return true; // Pattern contains only '*', which matches anything
        }

        // Process characters before first star
        while ((ch = patArr[patIdxStart]) != '*' && (strIdxStart <= strIdxEnd)) {
            if (isCaseSensitive && (ch != strArr[strIdxStart])) {
                return false; // Character mismatch
            }
            if (!isCaseSensitive
                    && (Character.toUpperCase(ch) != Character.toUpperCase(strArr[strIdxStart]))) {
                return false; // Character mismatch
            }
            patIdxStart++;
            strIdxStart++;
        }
        if (strIdxStart > strIdxEnd) {

            // All characters in the string are used. Check if only '*'s are
            // left in the pattern. If so, we succeeded. Otherwise failure.
            for (int i = patIdxStart; i <= patIdxEnd; i++) {
                if (patArr[i] != '*') {
                    return false;
                }
            }
            return true;
        }

        // Process characters after last star
        while ((ch = patArr[patIdxEnd]) != '*' && (strIdxStart <= strIdxEnd)) {
            if (isCaseSensitive && (ch != strArr[strIdxEnd])) {
                return false; // Character mismatch
            }
            if (!isCaseSensitive
                    && (Character.toUpperCase(ch) != Character.toUpperCase(strArr[strIdxEnd]))) {
                return false; // Character mismatch
            }
            patIdxEnd--;
            strIdxEnd--;
        }
        if (strIdxStart > strIdxEnd) {

            // All characters in the string are used. Check if only '*'s are
            // left in the pattern. If so, we succeeded. Otherwise failure.
            for (int i = patIdxStart; i <= patIdxEnd; i++) {
                if (patArr[i] != '*') {
                    return false;
                }
            }
            return true;
        }

        // process pattern between stars. padIdxStart and patIdxEnd point
        // always to a '*'.
        while ((patIdxStart != patIdxEnd) && (strIdxStart <= strIdxEnd)) {
            int patIdxTmp = -1;

            for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
                if (patArr[i] == '*') {
                    patIdxTmp = i;
                    break;
                }
            }
            if (patIdxTmp == patIdxStart + 1) {

                // Two stars next to each other, skip the first one.
                patIdxStart++;
                continue;
            }

            // Find the pattern between padIdxStart & padIdxTmp in str between
            // strIdxStart & strIdxEnd
            int patLength = (patIdxTmp - patIdxStart - 1);
            int strLength = (strIdxEnd - strIdxStart + 1);
            int foundIdx = -1;

            strLoop: for (int i = 0; i <= strLength - patLength; i++) {
                for (int j = 0; j < patLength; j++) {
                    ch = patArr[patIdxStart + j + 1];
                    if (isCaseSensitive && (ch != strArr[strIdxStart + i + j])) {
                        continue strLoop;
                    }
                    if (!isCaseSensitive
                            && (Character.toUpperCase(ch) != Character
                                    .toUpperCase(strArr[strIdxStart + i + j]))) {
                        continue strLoop;
                    }
                }
                foundIdx = strIdxStart + i;
                break;
            }
            if (foundIdx == -1) {
                return false;
            }
            patIdxStart = patIdxTmp;
            strIdxStart = foundIdx + patLength;
        }

        // All characters in the string are used. Check if only '*'s are left
        // in the pattern. If so, we succeeded. Otherwise failure.
        for (int i = patIdxStart; i <= patIdxEnd; i++) {
            if (patArr[i] != '*') {
                return false;
            }
        }
        return true;
    }

}
