/*
 * 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.catalina.ha.deploy;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.ha.CatalinaCluster;
import org.apache.catalina.ha.ClusterDeployer;
import org.apache.catalina.ha.ClusterListener;
import org.apache.catalina.ha.ClusterMessage;
import org.apache.catalina.tribes.Member;
import org.apache.commons.modeler.Registry;

/**
 * <p>
 * A farm war deployer is a class that is able to deploy/undeploy web
 * applications in WAR form within the cluster.
 * </p>
 * Any host can act as the admin, and will have three directories
 * <ul>
 * <li>deployDir - the directory where we watch for changes</li>
 * <li>applicationDir - the directory where we install applications</li>
 * <li>tempDir - a temporaryDirectory to store binary data when downloading a
 * war from the cluster</li>
 * </ul>
 * Currently we only support deployment of WAR files since they are easier to
 * send across the wire.
 * 
 * @author Filip Hanik
 * @author Peter Rossbach
 * @version $Revision$
 */
public class FarmWarDeployer extends ClusterListener implements ClusterDeployer, FileChangeListener {
    /*--Static Variables----------------------------------------*/
    public static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
            .getLog(FarmWarDeployer.class);
    /**
     * The descriptive information about this implementation.
     */
    private static final String info = "FarmWarDeployer/1.2";

    /*--Instance Variables--------------------------------------*/
    protected CatalinaCluster cluster = null;

    protected boolean started = false; //default 5 seconds

    protected HashMap fileFactories = new HashMap();

    protected String deployDir;

    protected String tempDir;

    protected String watchDir;

    protected boolean watchEnabled = false;

    protected WarWatcher watcher = null;

    /**
     * Iteration count for background processing.
     */
    private int count = 0;

    /**
     * Frequency of the Farm watchDir check. Cluster wide deployment will be
     * done once for the specified amount of backgrondProcess calls (ie, the
     * lower the amount, the most often the checks will occur).
     */
    protected int processDeployFrequency = 2;

    /**
     * Path where context descriptors should be deployed.
     */
    protected File configBase = null;

    /**
     * The associated host.
     */
    protected Host host = null;

    /**
     * The host appBase.
     */
    protected File appBase = null;

    /**
     * MBean server.
     */
    protected MBeanServer mBeanServer = null;

    /**
     * The associated deployer ObjectName.
     */
    protected ObjectName oname = null;

    /*--Constructor---------------------------------------------*/
    public FarmWarDeployer() {
    }

    /**
     * Return descriptive information about this deployer implementation and the
     * corresponding version number, in the format
     * <code>&lt;description&gt;/&lt;version&gt;</code>.
     */
    public String getInfo() {

        return (info);

    }

    /*--Logic---------------------------------------------------*/
    public void start() throws Exception {
        if (started)
            return;
        getCluster().addClusterListener(this);
        if (watchEnabled) {
            watcher = new WarWatcher(this, new File(getWatchDir()));
            if (log.isInfoEnabled())
                log.info("Cluster deployment is watching " + getWatchDir()
                        + " for changes.");
        }

        // Check to correct engine and host setup
        host = (Host) getCluster().getContainer();
        Engine engine = (Engine) host.getParent();
        try {
            oname = new ObjectName(engine.getName() + ":type=Deployer,host="
                    + host.getName());
        } catch (Exception e) {
            log.error("Can't construct MBean object name" + e);
        }
        configBase = new File(System.getProperty("catalina.base"), "conf");
        if (engine != null) {
            configBase = new File(configBase, engine.getName());
        }
        if (host != null) {
            configBase = new File(configBase, host.getName());
        }

        // Retrieve the MBean server
        mBeanServer = Registry.getRegistry(null, null).getMBeanServer();

        started = true;
        count = 0;
        if (log.isInfoEnabled())
            log.info("Cluster FarmWarDeployer started.");
    }

    /*
     * stop cluster wide deployments
     * 
     * @see org.apache.catalina.cluster.ClusterDeployer#stop()
     */
    public void stop() throws LifecycleException {
        started = false;
        getCluster().removeClusterListener(this);
        count = 0;
        if (watcher != null) {
            watcher.clear();
            watcher = null;

        }
        if (log.isInfoEnabled())
            log.info("Cluster FarmWarDeployer stopped.");
    }

    public void cleanDeployDir() {
        throw new java.lang.UnsupportedOperationException(
                "Method cleanDeployDir() not yet implemented.");
    }

    /**
     * Callback from the cluster, when a message is received, The cluster will
     * broadcast it invoking the messageReceived on the receiver.
     * 
     * @param msg
     *            ClusterMessage - the message received from the cluster
     */
    public void messageReceived(ClusterMessage msg) {
        try {
            if (msg instanceof FileMessage && msg != null) {
                FileMessage fmsg = (FileMessage) msg;
                if (log.isDebugEnabled())
                    log.debug("receive cluster deployment [ path: "
                            + fmsg.getContextPath() + " war:  "
                            + fmsg.getFileName() + " ]");
                FileMessageFactory factory = getFactory(fmsg);
                // TODO correct second try after app is in service!
                if (factory.writeMessage(fmsg)) {
                    //last message received war file is completed
                    String name = factory.getFile().getName();
                    if (!name.endsWith(".war"))
                        name = name + ".war";
                    File deployable = new File(getDeployDir(), name);
                    try {
                        String path = fmsg.getContextPath();
                        if (!isServiced(path)) {
                            addServiced(path);
                            try {
                                remove(path);
                                factory.getFile().renameTo(deployable);
                                check(path);
                            } finally {
                                removeServiced(path);
                            }
                            if (log.isDebugEnabled())
                                log.debug("deployment from " + path
                                        + " finished.");
                        } else
                            log.error("Application " + path
                                    + " in used. touch war file " + name
                                    + " again!");
                    } catch (Exception ex) {
                        log.error(ex);
                    } finally {
                        removeFactory(fmsg);
                    }
                }
            } else if (msg instanceof UndeployMessage && msg != null) {
                try {
                    UndeployMessage umsg = (UndeployMessage) msg;
                    String path = umsg.getContextPath();
                    if (log.isDebugEnabled())
                        log.debug("receive cluster undeployment from " + path);
                    if (!isServiced(path)) {
                        addServiced(path);
                        try {
                            remove(path);
                        } finally {
                            removeServiced(path);
                        }
                        if (log.isDebugEnabled())
                            log.debug("undeployment from " + path
                                    + " finished.");
                    } else
                        log.error("Application "
                            + path
                            + " in used. Sorry not remove from backup cluster nodes!");
                } catch (Exception ex) {
                    log.error(ex);
                }
            }
        } catch (java.io.IOException x) {
            log.error("Unable to read farm deploy file message.", x);
        }
    }

    /**
     * create factory for all transported war files
     * 
     * @param msg
     * @return Factory for all app message (war files)
     * @throws java.io.FileNotFoundException
     * @throws java.io.IOException
     */
    public synchronized FileMessageFactory getFactory(FileMessage msg)
            throws java.io.FileNotFoundException, java.io.IOException {
        File tmpFile = new File(msg.getFileName());
        File writeToFile = new File(getTempDir(), tmpFile.getName());
        FileMessageFactory factory = (FileMessageFactory) fileFactories.get(msg
                .getFileName());
        if (factory == null) {
            factory = FileMessageFactory.getInstance(writeToFile, true);
            fileFactories.put(msg.getFileName(), factory);
        }
        return factory;
    }

    /**
     * Remove file (war) from messages)
     * 
     * @param msg
     */
    public void removeFactory(FileMessage msg) {
        fileFactories.remove(msg.getFileName());
    }

    /**
     * Before the cluster invokes messageReceived the cluster will ask the
     * receiver to accept or decline the message, In the future, when messages
     * get big, the accept method will only take a message header
     * 
     * @param msg
     *            ClusterMessage
     * @return boolean - returns true to indicate that messageReceived should be
     *         invoked. If false is returned, the messageReceived method will
     *         not be invoked.
     */
    public boolean accept(ClusterMessage msg) {
        return (msg instanceof FileMessage) || (msg instanceof UndeployMessage);
    }

    /**
     * Install a new web application, whose web application archive is at the
     * specified URL, into this container and all the other members of the
     * cluster with the specified context path. A context path of "" (the empty
     * string) should be used for the root application for this container.
     * Otherwise, the context path must start with a slash.
     * <p>
     * If this application is successfully installed locally, a ContainerEvent
     * of type <code>INSTALL_EVENT</code> will be sent to all registered
     * listeners, with the newly created <code>Context</code> as an argument.
     * 
     * @param contextPath
     *            The context path to which this application should be installed
     *            (must be unique)
     * @param war
     *            A URL of type "jar:" that points to a WAR file, or type
     *            "file:" that points to an unpacked directory structure
     *            containing the web application to be installed
     * 
     * @exception IllegalArgumentException
     *                if the specified context path is malformed (it must be ""
     *                or start with a slash)
     * @exception IllegalStateException
     *                if the specified context path is already attached to an
     *                existing web application
     * @exception IOException
     *                if an input/output error was encountered during
     *                installation
     */
    public void install(String contextPath, URL war) throws IOException {
        Member[] members = getCluster().getMembers();
        Member localMember = getCluster().getLocalMember();
        FileMessageFactory factory = FileMessageFactory.getInstance(new File(
                war.getFile()), false);
        FileMessage msg = new FileMessage(localMember, war.getFile(),
                contextPath);
        if(log.isDebugEnabled())
            log.debug("Send cluster war deployment [ path:"
                    + contextPath + " war: " + war + " ] started.");
        msg = factory.readMessage(msg);
        while (msg != null) {
            for (int i = 0; i < members.length; i++) {
                if (log.isDebugEnabled())
                    log.debug("Send cluster war fragment [ path: "
                            + contextPath + " war: " + war + " to: " +  members[i] + " ]");
                getCluster().send(msg, members[i]);
            }
            msg = factory.readMessage(msg);
        }
        if(log.isDebugEnabled())
            log.debug("Send cluster war deployment [ path: "
                    + contextPath + " war: " + war + " ] finished.");
    }

    /**
     * Remove an existing web application, attached to the specified context
     * path. If this application is successfully removed, a ContainerEvent of
     * type <code>REMOVE_EVENT</code> will be sent to all registered
     * listeners, with the removed <code>Context</code> as an argument.
     * Deletes the web application war file and/or directory if they exist in
     * the Host's appBase.
     * 
     * @param contextPath
     *            The context path of the application to be removed
     * @param undeploy
     *            boolean flag to remove web application from server
     * 
     * @exception IllegalArgumentException
     *                if the specified context path is malformed (it must be ""
     *                or start with a slash)
     * @exception IllegalArgumentException
     *                if the specified context path does not identify a
     *                currently installed web application
     * @exception IOException
     *                if an input/output error occurs during removal
     */
    public void remove(String contextPath, boolean undeploy) throws IOException {
        if (log.isInfoEnabled())
            log.info("Cluster wide remove of web app " + contextPath);
        Member localMember = getCluster().getLocalMember();
        UndeployMessage msg = new UndeployMessage(localMember, System
                .currentTimeMillis(), "Undeploy:" + contextPath + ":"
                + System.currentTimeMillis(), contextPath, undeploy);
        if (log.isDebugEnabled())
            log.debug("Send cluster wide undeployment from "
                    + contextPath );
        cluster.send(msg);
        // remove locally
        if (undeploy) {
            try {
                if (!isServiced(contextPath)) {
                    addServiced(contextPath);
                    try {
                        remove(contextPath);
                    } finally {
                        removeServiced(contextPath);
                    }
                } else
                    log.error("Local remove from " + contextPath
                            + "failed, other manager has app in service!");

            } catch (Exception ex) {
                log.error("local remove from " + contextPath + " failed", ex);
            }
        }

    }

    /*
     * Modifcation from watchDir war detected!
     * 
     * @see org.apache.catalina.cluster.deploy.FileChangeListener#fileModified(java.io.File)
     */
    public void fileModified(File newWar) {
        try {
            File deployWar = new File(getDeployDir(), newWar.getName());
            copy(newWar, deployWar);
            String contextName = getContextName(deployWar);
            if (log.isInfoEnabled())
                log.info("Installing webapp[" + contextName + "] from "
                        + deployWar.getAbsolutePath());
            try {
                remove(contextName, false);
            } catch (Exception x) {
                log.error("No removal", x);
            }
            install(contextName, deployWar.toURL());
        } catch (Exception x) {
            log.error("Unable to install WAR file", x);
        }
    }

    /*
     * War remvoe from watchDir
     * 
     * @see org.apache.catalina.cluster.deploy.FileChangeListener#fileRemoved(java.io.File)
     */
    public void fileRemoved(File removeWar) {
        try {
            String contextName = getContextName(removeWar);
            if (log.isInfoEnabled())
                log.info("Removing webapp[" + contextName + "]");
            remove(contextName, true);
        } catch (Exception x) {
            log.error("Unable to remove WAR file", x);
        }
    }

    /**
     * Create a context path from war
     * @param war War filename
     * @return '/filename' or if war name is ROOT.war context name is empty string '' 
     */
    protected String getContextName(File war) {
        String contextName = "/"
        + war.getName().substring(0,
                war.getName().lastIndexOf(".war"));
        if("/ROOT".equals(contextName))
            contextName= "" ;
        return contextName ;
    }
    
    /**
     * Given a context path, get the config file name.
     */
    protected String getConfigFile(String path) {
        String basename = null;
        if (path.equals("")) {
            basename = "ROOT";
        } else {
            basename = path.substring(1).replace('/', '#');
        }
        return (basename);
    }

    /**
     * Given a context path, get the config file name.
     */
    protected String getDocBase(String path) {
        String basename = null;
        if (path.equals("")) {
            basename = "ROOT";
        } else {
            basename = path.substring(1);
        }
        return (basename);
    }

    /**
     * Return a File object representing the "application root" directory for
     * our associated Host.
     */
    protected File getAppBase() {

        if (appBase != null) {
            return appBase;
        }

        File file = new File(host.getAppBase());
        if (!file.isAbsolute())
            file = new File(System.getProperty("catalina.base"), host
                    .getAppBase());
        try {
            appBase = file.getCanonicalFile();
        } catch (IOException e) {
            appBase = file;
        }
        return (appBase);

    }

    /**
     * Invoke the remove method on the deployer.
     */
    protected void remove(String path) throws Exception {
        // TODO Handle remove also work dir content !
        // Stop the context first to be nicer
        Context context = (Context) host.findChild(path);
        if (context != null) {
            if(log.isDebugEnabled())
                log.debug("Undeploy local context " +path );
            ((Lifecycle) context).stop();
            File war = new File(getAppBase(), getDocBase(path) + ".war");
            File dir = new File(getAppBase(), getDocBase(path));
            File xml = new File(configBase, getConfigFile(path) + ".xml");
            if (war.exists()) {
                war.delete();
            } else if (dir.exists()) {
                undeployDir(dir);
            } else {
                xml.delete();
            }
            // Perform new deployment and remove internal HostConfig state
            check(path);
        }

    }

    /**
     * Delete the specified directory, including all of its contents and
     * subdirectories recursively.
     * 
     * @param dir
     *            File object representing the directory to be deleted
     */
    protected void undeployDir(File dir) {

        String files[] = dir.list();
        if (files == null) {
            files = new String[0];
        }
        for (int i = 0; i < files.length; i++) {
            File file = new File(dir, files[i]);
            if (file.isDirectory()) {
                undeployDir(file);
            } else {
                file.delete();
            }
        }
        dir.delete();

    }

    /*
     * Call watcher to check for deploy changes
     * 
     * @see org.apache.catalina.cluster.ClusterDeployer#backgroundProcess()
     */
    public void backgroundProcess() {
        if (started) {
            count = (count + 1) % processDeployFrequency;
            if (count == 0 && watchEnabled) {
                watcher.check();
            }
        }

    }

    /*--Deployer Operations ------------------------------------*/

    /**
     * Invoke the check method on the deployer.
     */
    protected void check(String name) throws Exception {
        String[] params = { name };
        String[] signature = { "java.lang.String" };
        mBeanServer.invoke(oname, "check", params, signature);
    }

    /**
     * Invoke the check method on the deployer.
     */
    protected boolean isServiced(String name) throws Exception {
        String[] params = { name };
        String[] signature = { "java.lang.String" };
        Boolean result = (Boolean) mBeanServer.invoke(oname, "isServiced",
                params, signature);
        return result.booleanValue();
    }

    /**
     * Invoke the check method on the deployer.
     */
    protected void addServiced(String name) throws Exception {
        String[] params = { name };
        String[] signature = { "java.lang.String" };
        mBeanServer.invoke(oname, "addServiced", params, signature);
    }

    /**
     * Invoke the check method on the deployer.
     */
    protected void removeServiced(String name) throws Exception {
        String[] params = { name };
        String[] signature = { "java.lang.String" };
        mBeanServer.invoke(oname, "removeServiced", params, signature);
    }

    /*--Instance Getters/Setters--------------------------------*/
    public CatalinaCluster getCluster() {
        return cluster;
    }

    public void setCluster(CatalinaCluster cluster) {
        this.cluster = cluster;
    }

    public boolean equals(Object listener) {
        return super.equals(listener);
    }

    public int hashCode() {
        return super.hashCode();
    }

    public String getDeployDir() {
        return deployDir;
    }

    public void setDeployDir(String deployDir) {
        this.deployDir = deployDir;
    }

    public String getTempDir() {
        return tempDir;
    }

    public void setTempDir(String tempDir) {
        this.tempDir = tempDir;
    }

    public String getWatchDir() {
        return watchDir;
    }

    public void setWatchDir(String watchDir) {
        this.watchDir = watchDir;
    }

    public boolean isWatchEnabled() {
        return watchEnabled;
    }

    public boolean getWatchEnabled() {
        return watchEnabled;
    }

    public void setWatchEnabled(boolean watchEnabled) {
        this.watchEnabled = watchEnabled;
    }

    /**
     * Return the frequency of watcher checks.
     */
    public int getProcessDeployFrequency() {

        return (this.processDeployFrequency);

    }

    /**
     * Set the watcher checks frequency.
     * 
     * @param processExpiresFrequency
     *            the new manager checks frequency
     */
    public void setProcessDeployFrequency(int processExpiresFrequency) {

        if (processExpiresFrequency <= 0) {
            return;
        }
        this.processDeployFrequency = processExpiresFrequency;
    }

    /**
     * Copy a file to the specified temp directory.
     * @param from copy from temp
     * @param to   to host appBase directory
     * @return true, copy successful
     */
    protected boolean copy(File from, File to) {
        try {
            if (!to.exists())
                to.createNewFile();
            java.io.FileInputStream is = new java.io.FileInputStream(from);
            java.io.FileOutputStream os = new java.io.FileOutputStream(to,
                    false);
            byte[] buf = new byte[4096];
            while (true) {
                int len = is.read(buf);
                if (len < 0)
                    break;
                os.write(buf, 0, len);
            }
            is.close();
            os.close();
        } catch (IOException e) {
            log.error("Unable to copy file from:" + from + " to:" + to, e);
            return false;
        }
        return true;
    }

}
