/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2006-2011 Bull S.A.S.
 * Contact: jonas-team@ow2.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 any 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: Tomcat7Connectors.java 22139 2012-02-22 14:07:30Z cazauxj $
 * --------------------------------------------------------------------------
 */
package org.ow2.jonas.antmodular.jonasbase.web.tomcat7;

import org.apache.tools.ant.Project;
import org.ow2.jonas.antmodular.jonasbase.bootstrap.JReplace;
import org.ow2.jonas.antmodular.jonasbase.web.tomcat.TomcatAjp;
import org.ow2.jonas.antmodular.jonasbase.web.tomcat.TomcatConnectors;
import org.ow2.jonas.antmodular.jonasbase.web.tomcat.TomcatHttp;
import org.ow2.jonas.antmodular.jonasbase.web.tomcat.TomcatHttps;
import org.ow2.jonas.antmodular.web.base.Director;
import org.ow2.jonas.antmodular.web.base.Http;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Configure a Tomcat 7 Connector
 * @author Jeremy Cazaux
 */
public class Tomcat7Connectors extends TomcatConnectors {

    /**
     * The tomcat 7 http connector available in (JONAS_BASE/deploy)
     */
    public static final String TOMCAT_7_HTPP_CONNECTOR = "tomcat7-http-connector.xml";

    /**
     * Tomcat 7 https connector to create
     */
    public static final String TOMCAT_7_HTTPS_CONNECTOR = "tomcat7-https-connector.xml";

    /**
     * Tomcat 7 AJP connector to create
     */
    public static final String TOMCAT_7_AJP_CONNECTOR = "tomcat7-ajp-connector.xml";

    /**
     * EOL
     */
    public static final String EOL = "\n";

    /**
     * The http redirect port configured
     */
    public String httpRedirectPort;

    /**
     * Default constructor
     */
    public Tomcat7Connectors() {
        super();
    }

    /**
     * Configure a HTTP Connector.
     * @param tomcatHttp Tomcat HTTP Configuration.
     */
    @Override
    public void addConfiguredHttp(final TomcatHttp tomcatHttp) {
        this.httpConfigured = true;
        JReplace propertyReplace = new JReplace();
        propertyReplace.setDeployableFile(TOMCAT_7_HTPP_CONNECTOR);
        propertyReplace.setToken("<property name=\"port\">" + Http.DEFAULT_PORT + "</property>"); 
        StringBuilder value = new StringBuilder();
        value.append("<property name=\"port\">" + tomcatHttp.getPort() + "</property>");

        final String maxThreads = tomcatHttp.getMaxThreads();
        if (maxThreads != null) {
            value.append(EOL + "    <property name=\"maxThreads\">" + maxThreads + "</property>");
        }

        final String minSpareThreads = tomcatHttp.getMinSpareThreads();
        if (minSpareThreads != null) {
            value.append(EOL + "    <property name=\"minSpareThreads\">" + minSpareThreads +"</property>");
        }

        final String enableLookups = tomcatHttp.getEnableLookups();
        if (enableLookups != null) {
            value.append(EOL + "    <property name=\"enableLookups\">" + tomcatHttp.getEnableLookups() + "</property>");
        }

        final String connectionTimeout = tomcatHttp.getConnectionTimeout();
        if (connectionTimeout != null) {
            value.append(EOL + "    <property name=\"connectionTimeout\">" + connectionTimeout + "</property>");
        }

        final String acceptCount = tomcatHttp.getAcceptCount();
        if (acceptCount != null) {
            value.append(EOL + "    <property name=\"acceptCount\">" + acceptCount + "</property>");
        }

        final String compression = tomcatHttp.getCompression();
        if (compression != null) {
            value.append(EOL + "    <property name=\"compression\">" + compression + "</property>");
        }

        final String maxKeepAliveRequests = tomcatHttp.getMaxKeepAliveRequest();
        if (maxKeepAliveRequests != null) {
            value.append(EOL + "    <property name=\"maxKeepAliveRequests\">" + maxKeepAliveRequests + "</property>");
        }
        
        propertyReplace.setValue(value.toString());
        addTask(propertyReplace);

        String redirectPort = tomcatHttp.getRedirectPort();
        if (redirectPort != null) {
            //replace redirectPort
            JReplace redirectPortReplace = new JReplace();
            redirectPortReplace.setDeployableFile(TOMCAT_7_HTPP_CONNECTOR);
            if (this.httpRedirectPort != null) {
                redirectPortReplace.setToken("<property name=\"redirectPort\">" + this.httpRedirectPort + "</property>");
            } else {
                redirectPortReplace.setToken("<property name=\"redirectPort\">" + TomcatHttp.DEFAULT_REDIRECT_PORT + "</property>");
            }
            redirectPortReplace.setValue("<property name=\"redirectPort\">" + redirectPort + "</property>");
            addTask(redirectPortReplace);
            this.httpRedirectPort = redirectPort;
        }
    }


    /**
     * Configure a HTTPS Connector.
     * @param tomcatHttps Tomcat HTTPS Configuration.
     */
    @Override
    public void addConfiguredHttps(final TomcatHttps tomcatHttps) {
        super.addConfiguredHttps(tomcatHttps, Tomcat7.TOMCAT_SERVER_CONF_FILE);
        final File httpsConnectorFile = new File(getJOnASBase(), "deploy" + File.separator + TOMCAT_7_HTTPS_CONNECTOR);
        FileOutputStream fileOutputStream = null;
        try {
            try {
                fileOutputStream = new FileOutputStream(httpsConnectorFile);
            } catch (FileNotFoundException e) {
                log("Cannot create file " + httpsConnectorFile.getAbsolutePath() + ": " + e,Project.MSG_ERR);
            }

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            stringBuilder.append(EOL + "<configadmin xmlns=\"http://jonas.ow2.org/ns/configadmin/1.0\">");
            stringBuilder.append(EOL + "  <factory-configuration pid=\"Tomcat7HttpsConnector\">");
            stringBuilder.append(EOL + "    <property name=\"address\">localhost</property>");
            stringBuilder.append(EOL + "    <property name=\"port\">" + tomcatHttps.getPort() + "</property>");

            final String redirectPort = tomcatHttps.getRedirectPort();
            if (redirectPort != null) {
                stringBuilder.append(EOL + "    <property name=\"redirectPort\">" + redirectPort + "</property>");
            }

            final String maxThreads = tomcatHttps.getMaxThreads();
            if (maxThreads != null) {
                stringBuilder.append(EOL + "    <property name=\"maxThreads\">" + maxThreads + "</property>");
            }

            final String minSpareThreads = tomcatHttps.getMinSpareThreads();
            if (minSpareThreads != null) {
                stringBuilder.append(EOL + "    <property name=\"minSpareThreads\">" + minSpareThreads +"</property>");
            }

            final String enableLookups = tomcatHttps.getEnableLookups();
            if (enableLookups != null) {
                stringBuilder.append(EOL + "    <property name=\"enableLookups\">" + enableLookups + "</property>");
            }

            final String connectionTimeout = tomcatHttps.getConnectionTimeout();
            if (connectionTimeout != null) {
                stringBuilder.append(EOL + "    <property name=\"connectionTimeout\">" + connectionTimeout + "</property>");
            }

            final String acceptCount = tomcatHttps.getAcceptCount();
            if (acceptCount != null) {
                stringBuilder.append(EOL + "    <property name=\"acceptCount\">" + acceptCount + "</property>");
            }

            final String compression = tomcatHttps.getCompression();
            if (compression != null) {
                stringBuilder.append(EOL + "    <property name=\"compression\">" + compression + "</property>");
            }

            final String maxKeepAliveRequests = tomcatHttps.getMaxKeepAliveRequest();
            if (maxKeepAliveRequests != null) {
                stringBuilder.append(EOL + "    <property name=\"maxKeepAliveRequests\">" + maxKeepAliveRequests + "</property>");
            }

            final String keystore = tomcatHttps.getKeystoreFile();
            if (keystore != null) {
                stringBuilder.append(EOL + "    <property name=\"keystore\">" + keystore + "</property>");
            }

            final String keystorePass = tomcatHttps.getKeystorePass();
            if (keystorePass != null) {
                stringBuilder.append(EOL + "    <property name=\"keystorePass\">" + keystorePass + "</property>");
            }

            stringBuilder.append(EOL + "  </factory-configuration>");
            stringBuilder.append(EOL + "</configadmin>");

            try {
                fileOutputStream.write(stringBuilder.toString().getBytes());
            } catch (IOException e) {
                log("Cannot write " + stringBuilder.toString() + " into the output file " + httpsConnectorFile.getAbsolutePath()
                        + " :" + e, Project.MSG_ERR);
            }
            
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                log("Cannot close the FileOutputStream resource " + e, Project.MSG_ERR);
            }
        }

        //replace http redirect port with the https port value
        JReplace propertyReplace = new JReplace();
        propertyReplace.setDeployableFile(TOMCAT_7_HTPP_CONNECTOR);
        if (this.httpRedirectPort != null) {
            propertyReplace.setToken("<property name=\"redirectPort\">" + this.httpRedirectPort + "</property>");
        } else {
            propertyReplace.setToken("<property name=\"redirectPort\">" + TomcatHttp.DEFAULT_REDIRECT_PORT  + "</property>");
        }
        String httpsPort = tomcatHttps.getPort();
        propertyReplace.setValue("<property name=\"redirectPort\">" + httpsPort + "</property>");
        addTask(propertyReplace);
        this.httpRedirectPort = httpsPort;
    }

    /**
     * Configure a Director Connector.
     * @param dir Director Configuration.
     */
    @Override
    public void addConfiguredDirector(final Director dir) {
        super.addConfiguredDirector(dir, Tomcat7.TOMCAT_SERVER_CONF_FILE);
    }

    /**
     * Configure an AJP Connector.
     * @param tomcatAjp AJP Configuration.
     */
    @Override
    public void addConfiguredAjp(TomcatAjp tomcatAjp) {
        File ajpConnectorFile = new File(getJOnASBase(), "deploy" + File.separator + TOMCAT_7_AJP_CONNECTOR);
        FileOutputStream fileOutputStream = null;
        try {
            try {
                fileOutputStream = new FileOutputStream(ajpConnectorFile);
            } catch (FileNotFoundException e) {
                log("Cannot create file " + ajpConnectorFile.getAbsolutePath() + ": " + e,Project.MSG_ERR);
            }

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            stringBuilder.append(EOL + "<configadmin xmlns=\"http://jonas.ow2.org/ns/configadmin/1.0\">");
            stringBuilder.append(EOL + "  <factory-configuration pid=\"Tomcat7AjpConnector\">");
            stringBuilder.append(EOL + "    <property name=\"address\">localhost</property>");
            stringBuilder.append(EOL + "    <property name=\"port\">" + tomcatAjp.getPort() + "</property>");
            
            String redirectPort = tomcatAjp.getRedirectPort();
            if (redirectPort == null) {
                redirectPort = TomcatAjp.DEFAULT_REDIRECT_PORT;
            }
            stringBuilder.append(EOL + "    <property name=\"redirectPort\">" + redirectPort + "</property>");

            final String maxThreads = tomcatAjp.getMaxThreads();
            if (maxThreads != null) {
                stringBuilder.append(EOL + "    <property name=\"maxThreads\">" + maxThreads + "</property>");
            }

            final String minSpareThreads = tomcatAjp.getMinSpareThreads();
            if (minSpareThreads != null) {
                stringBuilder.append(EOL + "    <property name=\"minSpareThreads\">" + minSpareThreads +"</property>");
            }

            final String enableLookups = tomcatAjp.getEnableLookups();
            if (enableLookups != null) {
                stringBuilder.append(EOL + "    <property name=\"enableLookups\">" + enableLookups + "</property>");
            }

            final String connectionTimeout = tomcatAjp.getConnectionTimeout();
            if (connectionTimeout != null) {
                stringBuilder.append(EOL + "    <property name=\"connectionTimeout\">" + connectionTimeout + "</property>");
            }

            final String acceptCount = tomcatAjp.getAcceptCount();
            if (acceptCount != null) {
                stringBuilder.append(EOL + "    <property name=\"acceptCount\">" + acceptCount + "</property>");
            }

            stringBuilder.append(EOL + "  </factory-configuration>");
            stringBuilder.append(EOL + "</configadmin>");


            try {
                fileOutputStream.write(stringBuilder.toString().getBytes());
            } catch (IOException e) {
                log("Cannot write " + stringBuilder.toString() + " into the output file " + ajpConnectorFile.getAbsolutePath()
                        + " :" + e, Project.MSG_ERR);
            }

        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                log("Cannot close the FileOutputStream resource " + e, Project.MSG_ERR);
            }
        }
    }

    @Override
    public void execute() {
        super.execute();
        super.executeAllTask();
    }
}
