/**
 * 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$
 * --------------------------------------------------------------------------
 */
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";

    /**
     * Package of optional deployables
     */
    public static final String OPTIONAL_DEPLOYABLE_PACKAGE = "templates/web/tomcat7/deploy/optional/";

    /**
     * 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;

        String port = tomcatHttp.getPort();
        String redirectPort = tomcatHttp.getRedirectPort();
        String maxThreads = tomcatHttp.getMaxThreads();
        String minSpareThreads = tomcatHttp.getMinSpareThreads();
        String enableLookups = tomcatHttp.getEnableLookups();
        String connectionTimeout = tomcatHttp.getConnectionTimeout();
        String acceptCount = tomcatHttp.getAcceptCount();
        String compression = tomcatHttp.getCompression();
        String maxKeepAliveRequests = tomcatHttp.getMaxKeepAliveRequest();

        if (!this.skipOptionalDeployablesCopy)  {
            //if the http connector already exist (copied from the template dir), update it
            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\">" + port + "</property>");

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

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

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

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

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

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

            propertyReplace.setValue(value.toString());
            addTask(propertyReplace);

            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;
            }
        } else {
            //create a new http connector file
            File httpConnectorFile = new File(getJOnASBase(), "deploy" + File.separator + TOMCAT_7_HTPP_CONNECTOR);
            FileOutputStream outputStream = null;
            
            try {
                try {
                    outputStream = new FileOutputStream(httpConnectorFile);
                } catch (FileNotFoundException e) {
                    log("Cannot create file " + httpConnectorFile.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=\"Tomcat7HttpConnector\">");
                stringBuilder.append(EOL + "    <property name=\"address\"/>");
                stringBuilder.append(EOL + "    <property name=\"port\">" + port + "</property>");

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

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

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

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

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

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

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

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

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

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

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

    }


    /**
     * 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() {
        if (!this.skipOptionalDeployablesCopy) {
            //copy optional template deployables
            copyTemplateDeployables(OPTIONAL_DEPLOYABLE_PACKAGE);
        }

        super.execute();
        super.executeAllTask();
    }
}
