/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2005 Bull S.A.
 * Contact: jonas-team@objectweb.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or 1any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.objectweb.jonas.jonasadmin.test.catalina;

import java.io.IOException;
import java.net.ServerSocket;

import org.xml.sax.SAXException;

import com.meterware.httpunit.SubmitButton;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebForm;
import com.meterware.httpunit.WebLink;
import com.meterware.httpunit.WebResponse;

/**
 * Class for using connectors from jonasAdmin, for example create a new connector.
 * @author Paul Kemler
 *
 */
public class ConnectorUtils {

    /**
     * NAME of FRAME content
     */
    protected static final String FRAME_CONTENT = "content";

    /**
     * NAME of FRAME tree
     */
    protected static final String FRAME_TREE = "tree";

    /**
     * URL of the Catalina connectors
     */
    private static final String URL_JONASADMIN_CATALINA_CONNECTOR = "ListCatalinaConnectors.do";

    /**
     * URL for creating a catalina connector
     */
    private static final String URL_JONASADMIN_CREATE_CATALINA_CONNECTOR = "CreateCatalinaConnector.do";

    /**
     * Create a new connector
     * @param wc logged to jonasAdmin
     * @return port of the new connector
     * @throws Exception if an error occurs
     */
    public static String createNewConnector(WebConversation wc) throws Exception {
        // Call method createNewConnector(WebConversation wc, String protocol)
        return createNewConnector(wc, "http");
    }

    /**
     * Create a new connector
     * @param wc logged to jonasAdmin
     * @param protocol protocol to create ("http", "https" or "ajp")
     * @return port of the new connector
     * @throws Exception if an error occurs
     */
    public static String createNewConnector(WebConversation wc, String protocol) throws Exception {
        WebResponse wr = null;
        WebLink link = null;
        WebForm form = null;
        String portText = null;

        // Go to connector page
        wr = getConnectorPage(wc);

        // Go to CreateCatalinaConnector.do?type= <protocol>
        link = wr.getFirstMatchingLink(WebLink.MATCH_URL_STRING, URL_JONASADMIN_CREATE_CATALINA_CONNECTOR + "?type="
                + protocol);
        link.click();
        wr = wc.getFrameContents(FRAME_CONTENT);

        portText = "" + findPort();

        if (protocol.equals("http")) {

            form = wr.getForms()[0];
            String maxSpareThreadsText = form.getParameterValue("maxSpareThreadsText");
            String URIEncoding = form.getParameterValue("URIEncoding");
            String minSpareThreadsText = form.getParameterValue("minSpareThreadsText");
            String address = form.getParameterValue("address");
            String tcpNoDelay = form.getParameterValue("tcpNoDelay");
            String maxThreadsText = form.getParameterValue("maxThreadsText");
            String xpoweredBy = form.getParameterValue("xpoweredBy");
            String connectorType = form.getParameterValue("connectorType");
            String objectName = form.getParameterValue("objectName");
            String secure = form.getParameterValue("secure");
            String action = form.getParameterValue("action");
            String save = form.getParameterValue("save");
            String emptySessionPath = form.getParameterValue("emptySessionPath");
            String acceptCountText = form.getParameterValue("acceptCountText");
            String bufferSizeText = form.getParameterValue("bufferSizeText");
            String proxyName = form.getParameterValue("proxyName");
            String useBodyEncodingForURI = form.getParameterValue("useBodyEncodingForURI");
            String connTimeOutText = form.getParameterValue("connTimeOutText");
            String redirectPortText = form.getParameterValue("redirectPortText");
            String enableLookups = form.getParameterValue("enableLookups");
            String allowTrace = form.getParameterValue("allowTrace");
            String proxyPortText = form.getParameterValue("proxyPortText");
            String maxPostSizeText = form.getParameterValue("maxPostSizeText");

            createNewHttpConnector(form, maxSpareThreadsText, URIEncoding, portText, minSpareThreadsText, address,
                    tcpNoDelay, maxThreadsText, xpoweredBy, connectorType, objectName, secure, action, save,
                    emptySessionPath, acceptCountText, bufferSizeText, proxyName, useBodyEncodingForURI,
                    connTimeOutText, redirectPortText, enableLookups, allowTrace, proxyPortText, maxPostSizeText);
        } else if (protocol.equals("https")) {
            form = wr.getForms()[0];
            String maxSpareThreadsText = form.getParameterValue("maxSpareThreadsText");
            String keystorePass = form.getParameterValue("keystorePass");
            String URIEncoding = form.getParameterValue("URIEncoding");
            String minSpareThreadsText = form.getParameterValue("minSpareThreadsText");
            String address = form.getParameterValue("address");
            String keystoreType = form.getParameterValue("keystoreType");
            String algorithm = form.getParameterValue("algorithm");
            String tcpNoDelay = form.getParameterValue("tcpNoDelay");
            String maxThreadsText = form.getParameterValue("maxThreadsText");
            String xpoweredBy = form.getParameterValue("xpoweredBy");
            String connectorType = form.getParameterValue("connectorType");
            String sslProtocol = form.getParameterValue("sslProtocol");
            String objectName = form.getParameterValue("objectName");
            String secure = form.getParameterValue("secure");
            String action = form.getParameterValue("action");
            String save = form.getParameterValue("save");
            String emptySessionPath = form.getParameterValue("emptySessionPath");
            String keystoreFile = form.getParameterValue("keystoreFile");
            String acceptCountText = form.getParameterValue("acceptCountText");
            String bufferSizeText = form.getParameterValue("bufferSizeText");
            String proxyName = form.getParameterValue("proxyName");
            String useBodyEncodingForURI = form.getParameterValue("useBodyEncodingForURI");
            String connTimeOutText = form.getParameterValue("connTimeOutText");
            String redirectPortText = form.getParameterValue("redirectPortText");
            String enableLookups = form.getParameterValue("enableLookups");
            String clientAuth = form.getParameterValue("clientAuth");
            String allowTrace = form.getParameterValue("allowTrace");
            String ciphers = form.getParameterValue("ciphers");
            String proxyPortText = form.getParameterValue("proxyPortText");
            String maxPostSizeText = form.getParameterValue("maxPostSizeText");

            createNewHttpsConnector(form, maxSpareThreadsText, keystorePass, URIEncoding, portText,
                    minSpareThreadsText, address, keystoreType, algorithm, tcpNoDelay, maxThreadsText, xpoweredBy,
                    connectorType, sslProtocol, objectName, secure, action, save, emptySessionPath, keystoreFile,
                    acceptCountText, bufferSizeText, proxyName, useBodyEncodingForURI, connTimeOutText,
                    redirectPortText, enableLookups, clientAuth, allowTrace,
                    ciphers, proxyPortText, maxPostSizeText);
        } else if (protocol.equals("ajp")) {
            form = wr.getForms()[0];
            String maxSpareThreadsText = form.getParameterValue("maxSpareThreadsText");
            String URIEncoding = form.getParameterValue("URIEncoding");
            String minSpareThreadsText = form.getParameterValue("minSpareThreadsText");
            String address = form.getParameterValue("address");
            String tcpNoDelay = form.getParameterValue("tcpNoDelay");
            String maxThreadsText = form.getParameterValue("maxThreadsText");
            String xpoweredBy = form.getParameterValue("xpoweredBy");
            String connectorType = form.getParameterValue("connectorType");
            String objectName = form.getParameterValue("objectName");
            String secure = form.getParameterValue("secure");
            String action = form.getParameterValue("action");
            String save = form.getParameterValue("save");
            String emptySessionPath = form.getParameterValue("emptySessionPath");
            String acceptCountText = form.getParameterValue("acceptCountText");
            String bufferSizeText = form.getParameterValue("bufferSizeText");
            String useBodyEncodingForURI = form.getParameterValue("useBodyEncodingForURI");
            String connTimeOutText = form.getParameterValue("connTimeOutText");
            String redirectPortText = form.getParameterValue("redirectPortText");
            String enableLookups = form.getParameterValue("enableLookups");
            String allowTrace = form.getParameterValue("allowTrace");
            String maxPostSizeText = form.getParameterValue("maxPostSizeText");

            createNewAjpConnector(form, maxSpareThreadsText, URIEncoding, portText, minSpareThreadsText, address,
                    tcpNoDelay, maxThreadsText, xpoweredBy, connectorType, objectName, secure, action, save,
                    emptySessionPath, acceptCountText, bufferSizeText, useBodyEncodingForURI, connTimeOutText,
                    redirectPortText, enableLookups, allowTrace, maxPostSizeText);
        }
        return portText;
    }

    /**
     * Get connector page when it is catalina
     * @param wc logged to jonasAdmin with catalina
     * @return WebResponse: content frame with list of connectors
     * @throws SAXException if an error occurs when link is matched or clicked
     * @throws IOException if an error occurs when link is clicked
     */
    public static WebResponse getConnectorPage(WebConversation wc) throws SAXException, IOException {
        // Go to connector page (ListCatalinaConnectors.do)
        WebResponse wr;
        WebLink link;

        wr = wc.getFrameContents(FRAME_TREE);
        link = wr.getFirstMatchingLink(WebLink.MATCH_URL_STRING, URL_JONASADMIN_CATALINA_CONNECTOR);
        if (link == null) {
            throw new IllegalStateException("No link found for link : '" + URL_JONASADMIN_CATALINA_CONNECTOR + "'.");
        }
        link.click();

        wr = wc.getFrameContents(FRAME_CONTENT);
        return wr;
    }

    /**
     * Get a free port
     * @return number of a free port
     * @throws Exception if an error occurs to find a port
     */
    private static int findPort() throws Exception {
        int port = 0;

        ServerSocket ss;
        ss = new ServerSocket(port); // free port if port == 0
        port = ss.getLocalPort();
        ss.close();
        return port;
    }

    /**
     * Create New Http Connector
     * @param form Web Form to create http connector
     * @param maxSpareThreadsText a string
     * @param URIEncoding a string
     * @param portText a string
     * @param minSpareThreadsText a string
     * @param address a string
     * @param tcpNoDelay a string
     * @param maxThreadsText a string
     * @param xpoweredBy a string
     * @param connectorType a string
     * @param objectName a string
     * @param secure a string
     * @param action a string
     * @param save a string
     * @param emptySessionPath a string
     * @param acceptCountText a string
     * @param bufferSizeText a string
     * @param proxyName a string
     * @param useBodyEncodingForURI a string
     * @param connTimeOutText a string
     * @param redirectPortText a string
     * @param enableLookups a string
     * @param allowTrace a string
     * @param proxyPortText a string
     * @param maxPostSizeText a string
     * @throws Exception if an error occurs when button is clicked.
     */
    public static void createNewHttpConnector(WebForm form, String maxSpareThreadsText, String URIEncoding,
            String portText, String minSpareThreadsText, String address, String tcpNoDelay, String maxThreadsText,
            String xpoweredBy, String connectorType, String objectName, String secure, String action, String save,
            String emptySessionPath, String acceptCountText, String bufferSizeText, String proxyName,
            String useBodyEncodingForURI, String connTimeOutText, String redirectPortText,
            String enableLookups, String allowTrace,
            String proxyPortText, String maxPostSizeText) throws Exception {

        SubmitButton button = null;

        form.setParameter("maxSpareThreadsText", maxSpareThreadsText);
        form.setParameter("URIEncoding", URIEncoding);
        form.setParameter("portText", portText);
        form.setParameter("minSpareThreadsText", minSpareThreadsText);
        form.setParameter("address", address);
        form.setParameter("tcpNoDelay", tcpNoDelay);
        form.setParameter("maxThreadsText", maxThreadsText);
        form.setParameter("xpoweredBy", xpoweredBy);
        form.setParameter("connectorType", connectorType);
        form.setParameter("objectName", objectName);
        form.setParameter("secure", secure);
        form.setParameter("action", action);
        form.setParameter("save", save);
        form.setParameter("emptySessionPath", emptySessionPath);
        form.setParameter("acceptCountText", acceptCountText);
        form.setParameter("bufferSizeText", bufferSizeText);
        form.setParameter("proxyName", proxyName);
        form.setParameter("useBodyEncodingForURI", useBodyEncodingForURI);
        form.setParameter("connTimeOutText", connTimeOutText);
        form.setParameter("redirectPortText", redirectPortText);
        form.setParameter("enableLookups", enableLookups);
        form.setParameter("allowTrace", allowTrace);
        form.setParameter("proxyPortText", proxyPortText);
        form.setParameter("maxPostSizeText", maxPostSizeText);

        button = form.getSubmitButton("btn_apply");
        button.click();
    }

    /**
     * Create New Https Connector
     * @param form Web Form to create https connector
     * @param maxSpareThreadsText a string
     * @param keystorePass a string
     * @param URIEncoding a string
     * @param portText a string
     * @param minSpareThreadsText a string
     * @param address a string
     * @param keystoreType a string
     * @param algorithm a string
     * @param tcpNoDelay a string
     * @param maxThreadsText a string
     * @param xpoweredBy a string
     * @param connectorType a string
     * @param sslProtocol a string
     * @param objectName a string
     * @param secure a string
     * @param action a string
     * @param save a string
     * @param emptySessionPath a string
     * @param keystoreFile a string
     * @param acceptCountText a string
     * @param bufferSizeText a string
     * @param proxyName a string
     * @param useBodyEncodingForURI a string
     * @param connTimeOutText a string
     * @param redirectPortText a string
     * @param enableLookups a string
     * @param clientAuth a string
     * @param allowTrace a string
     * @param ciphers a string
     * @param proxyPortText a string
     * @param maxPostSizeText a string
     * @throws Exception if an error occurs when button is clicked.
     */
    public static void createNewHttpsConnector(WebForm form, String maxSpareThreadsText, String keystorePass,
            String URIEncoding, String portText, String minSpareThreadsText, String address, String keystoreType,
            String algorithm, String tcpNoDelay, String maxThreadsText, String xpoweredBy, String connectorType,
            String sslProtocol, String objectName, String secure, String action, String save, String emptySessionPath,
            String keystoreFile, String acceptCountText, String bufferSizeText, String proxyName,
            String useBodyEncodingForURI, String connTimeOutText, String redirectPortText,
            String enableLookups, String clientAuth, String allowTrace,
            String ciphers, String proxyPortText, String maxPostSizeText) throws Exception {

        SubmitButton button = null;

        form.setParameter("maxSpareThreadsText", maxSpareThreadsText);
        form.setParameter("keystorePass", keystorePass);
        form.setParameter("URIEncoding", URIEncoding);
        form.setParameter("portText", portText);
        form.setParameter("minSpareThreadsText", minSpareThreadsText);
        form.setParameter("address", address);
        form.setParameter("keystoreType", keystoreType);
        form.setParameter("algorithm", algorithm);
        form.setParameter("tcpNoDelay", tcpNoDelay);
        form.setParameter("maxThreadsText", maxThreadsText);
        form.setParameter("xpoweredBy", xpoweredBy);
        form.setParameter("connectorType", connectorType);
        form.setParameter("sslProtocol", sslProtocol);
        form.setParameter("objectName", objectName);
        form.setParameter("secure", secure);
        form.setParameter("action", action);
        form.setParameter("save", save);
        form.setParameter("emptySessionPath", emptySessionPath);
        form.setParameter("keystoreFile", keystoreFile);
        form.setParameter("acceptCountText", acceptCountText);
        form.setParameter("bufferSizeText", bufferSizeText);
        form.setParameter("proxyName", proxyName);
        form.setParameter("useBodyEncodingForURI", useBodyEncodingForURI);
        form.setParameter("connTimeOutText", connTimeOutText);
        form.setParameter("redirectPortText", redirectPortText);
        form.setParameter("enableLookups", enableLookups);
        form.setParameter("clientAuth", clientAuth);
        form.setParameter("allowTrace", allowTrace);
        form.setParameter("ciphers", ciphers);
        form.setParameter("proxyPortText", proxyPortText);
        form.setParameter("maxPostSizeText", maxPostSizeText);

        button = form.getSubmitButton("btn_apply");
        button.click();
    }

    /**
     * Create New Ajp Connector
     * @param form Web Form to create ajp connector
     * @param maxSpareThreadsText a string
     * @param URIEncoding a string
     * @param portText a string
     * @param minSpareThreadsText a string
     * @param address a string
     * @param tcpNoDelay a string
     * @param maxThreadsText a string
     * @param xpoweredBy a string
     * @param connectorType a string
     * @param objectName a string
     * @param secure a string
     * @param action a string
     * @param save a string
     * @param emptySessionPath a string
     * @param acceptCountText a string
     * @param bufferSizeText a string
     * @param useBodyEncodingForURI a string
     * @param connTimeOutText a string
     * @param redirectPortText a string
     * @param enableLookups a string
     * @param allowTrace a string
     * @param maxPostSizeText a string
     * @throws Exception if an error occurs when button is clicked.
     */
    public static void createNewAjpConnector(WebForm form, String maxSpareThreadsText, String URIEncoding,
            String portText, String minSpareThreadsText, String address, String tcpNoDelay, String maxThreadsText,
            String xpoweredBy, String connectorType, String objectName, String secure, String action, String save,
            String emptySessionPath, String acceptCountText, String bufferSizeText, String useBodyEncodingForURI,
            String connTimeOutText, String redirectPortText, String enableLookups, String allowTrace, String maxPostSizeText) throws Exception {

        SubmitButton button = null;

        form.setParameter("maxSpareThreadsText", maxSpareThreadsText);
        form.setParameter("URIEncoding", URIEncoding);
        form.setParameter("portText", portText);
        form.setParameter("minSpareThreadsText", minSpareThreadsText);
        form.setParameter("address", address);
        form.setParameter("tcpNoDelay", tcpNoDelay);
        form.setParameter("maxThreadsText", maxThreadsText);
        form.setParameter("xpoweredBy", xpoweredBy);
        form.setParameter("connectorType", connectorType);
        form.setParameter("objectName", objectName);
        form.setParameter("secure", secure);
        form.setParameter("action", action);
        form.setParameter("save", save);
        form.setParameter("emptySessionPath", emptySessionPath);
        form.setParameter("acceptCountText", acceptCountText);
        form.setParameter("bufferSizeText", bufferSizeText);
        form.setParameter("useBodyEncodingForURI", useBodyEncodingForURI);
        form.setParameter("connTimeOutText", connTimeOutText);
        form.setParameter("redirectPortText", redirectPortText);
        form.setParameter("enableLookups", enableLookups);
        form.setParameter("allowTrace", allowTrace);
        form.setParameter("maxPostSizeText", maxPostSizeText);

        button = form.getSubmitButton("btn_apply");
        button.click();
    }

    /**
     * Remove a connector
     * @param wc logged to jonasAdmin
     * @param port port number of the connector to remove
     * @throws Exception if an error occurs when connector is deleted
     */
    public static void deleteConnector(WebConversation wc, String port) throws Exception {
        String[] tabPort = {port};
        deleteConnectors(wc, tabPort);
    }

    /**
     * Remove connectors
     * @param wc logged to jonasAdmin
     * @param port port number of the connector to remove
     * @throws Exception if an error occurs
     */
    public static void deleteConnectors(WebConversation wc, String[] tabPort) throws Exception {
        WebResponse wr = null;
        WebForm form = null;
        WebLink link = null;
        SubmitButton button = null;

        String action = "";

        wr = getConnectorPage(wc);

        // Select connectors to remove
        form = wr.getForms()[0];
        action = form.getParameterValue("action");
        for (int i = 0; i < tabPort.length; i++) {
            form.setCheckbox("selectedItems", "jonas:type=Connector,port=" + tabPort[i], true);
        }

        // Choose remove action
        link = wr.getFirstMatchingLink(WebLink.MATCH_URL_STRING, "remove");
        link.click();
        wr = wc.getFrameContents(FRAME_CONTENT);

        // Confirm
        form = wr.getForms()[0];
        button = form.getSubmitButton("btnSubmit");
        button.click();
    }

    /**
     * Modify a connector
     * @param wc logged to jonasAdmin
     * @param port number of the port of the connector to modify
     * @param acceptCountText a string
     * @param maxPostSizeText a string
     * @param connTimeOutText a string
     * @param URIEncoding a string
     * @param bufferSizeText a string
     * @param address a string
     * @param redirectPortText a string
     * @param maxThreadsText a string
     * @param minSpareThreadsText a string
     * @param maxSpareThreadsText a string
     * @param proxyName a string
     * @param proxyPortText a string
     * @throws Exception if an error occurs
     */
    public static void modifyHttpConnector(WebForm form, String acceptCountText, String maxPostSizeText,
            String connTimeOutText, String URIEncoding, String bufferSizeText, String address, String redirectPortText,
            String maxThreadsText, String minSpareThreadsText, String maxSpareThreadsText, String proxyName,
            String proxyPortText, String allowTrace, String emptySessionPath, String enableLookups,
            String useBodyEncodingForURI, String xpoweredBy, String tcpNoDelay) throws Exception {

        SubmitButton button = null;

        String objectName = null;
        String action = null;
        String save = null;
        String connectorType = null;
        String portText = null;

        // get hidden params
        objectName = form.getParameterValue("objectName");
        action = form.getParameterValue("action");
        save = form.getParameterValue("save");
        connectorType = form.getParameterValue("connectorType");
        portText = form.getParameterValue("portText");

        form.setParameter("objectName", objectName);
        form.setParameter("action", action);
        form.setParameter("save", save);
        form.setParameter("connectorType", connectorType);
        form.setParameter("portText", portText);
        form.setParameter("acceptCountText", acceptCountText);
        form.setParameter("maxPostSizeText", maxPostSizeText);
        form.setParameter("connTimeOutText", connTimeOutText);
        form.setParameter("URIEncoding", URIEncoding);
        form.setParameter("bufferSizeText", bufferSizeText);
        form.setParameter("address", address);
        form.setParameter("redirectPortText", redirectPortText);
        form.setParameter("maxThreadsText", maxThreadsText);
        form.setParameter("minSpareThreadsText", minSpareThreadsText);
        form.setParameter("maxSpareThreadsText", maxSpareThreadsText);
        form.setParameter("proxyName", proxyName);
        form.setParameter("proxyPortText", proxyPortText);
        form.setParameter("allowTrace", allowTrace);
        form.setParameter("emptySessionPath", emptySessionPath);
        form.setParameter("enableLookups", enableLookups);
        form.setParameter("useBodyEncodingForURI", useBodyEncodingForURI);
        form.setParameter("xpoweredBy", xpoweredBy);
        form.setParameter("tcpNoDelay", tcpNoDelay);

        button = form.getSubmitButton("btn_apply");
        button.click();
    }
}
