/* JFox, the OpenSource J2EE Application Server
 *
 * Distributable under GNU LGPL license by gun.org
 * more details please visit http://www.huihoo.org/jfox
 */
package org.jfox.deployment;

import java.io.File;
import java.io.FileFilter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.jfox.deployment.application.EARDeployer;
import org.jfox.deployment.application.EARModule;
import org.jfox.deployment.ejb.EJBDeployer;
import org.jfox.deployment.ejb.EJBModule;
import org.jfox.deployment.web.WebDeployer;
import org.jfox.deployment.web.WebModule;
import org.jfox.framework.deploy.DeployException;
import org.jfox.framework.deploy.Deployable;
import org.jfox.framework.deploy.Deployer;
import org.jfox.framework.extra.ActiveComponent;
import org.jfox.framework.util.FileFilters;
import org.jfox.system.AbstractService;

/**
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class J2EEDeployMonitor extends AbstractService implements ActiveComponent {
    private long sleepTime = 1000L;

    private EARDeployer earDeployer;
    private EJBDeployer ejbDeployer;
    private WebDeployer webDeployer;

    private String moniteDirectory = "../deploy";

    // file => last modify
    private Map deployed = new HashMap();
    // file => modules
    private Map deployedModules = new HashMap();

    private static FileFilter filter = FileFilters.suffixFileFilter(new String[]{".jar", ".war", ".ear"});


    public J2EEDeployMonitor(EARDeployer earDeployer) {
        this.earDeployer = earDeployer;
        this.ejbDeployer = earDeployer.getEjbDeployer();
        this.webDeployer = earDeployer.getWebDeployer();
    }

    public void setSleepTime(long time) {
        this.sleepTime = time;
    }

    public long getSleepTime() {
        return sleepTime;
    }

    public File[] getDeployedJars() {
        return (File[]) deployed.values().toArray(new File[deployed.size()]);
    }

    public void run() {
        File monitorDir = new File(moniteDirectory);
        while(isStarted()) {
            Map newJars = new HashMap();
            // 取得目录下所有的 .jar 文件
            File[] jarFiles = monitorDir.listFiles(filter);
            for(int j = 0; j < jarFiles.length; j++) {
                File jar = jarFiles[j];
                try {
                    newJars.put(jar, new Long(jar.lastModified()));
                    if(isToBeDeploy(jar)) { // 要发布
                        logger.info("deploy module " + jar.getName() + " ...");
                        Deployer deployer = getDeployer(jar);
                        Deployable module = buildModule(jar);
                        deployer.deploy(module);
                        deployedModules.put(jar, module);
                        logger.info("deploy module " + jar.getName() + " over.");
                    }
                    deployed.remove(jar);

                }
                catch(Exception e) {
                    logger.warn(e.getMessage(), e);
                }
            }

            // jars 里面剩下的是已经删除的jar, undeploy 它们
            for(Iterator it = deployed.keySet().iterator(); it.hasNext();) {
                File file = (File) it.next();
                Deployable module = (Deployable) deployedModules.get(file);
                Deployer deployer = getDeployer(file);
                try {
                    deployer.undeploy(module);
                    deployedModules.remove(file);
                }
                catch(DeployException e) {
                    logger.warn("undeploy module " + module + " error", e);
                }
            }
            deployed = newJars;

            try {
                Thread.sleep(sleepTime);
            }
            catch(InterruptedException e) {
//        e.printStackTrace();
                logger.warn(e.getMessage(), e);
            }
        }

    }

    protected void doStart() throws Exception {
        Thread deployMonitor = new Thread(this, this.getClass().getName());
        deployMonitor.setPriority(Thread.MIN_PRIORITY);
        deployMonitor.start();
    }

    protected void doStop() throws Exception {

    }

    private boolean isToBeDeploy(File jar) {
        if(!deployed.containsKey(jar)) { // 新增的 jar
            return true;
        }
        else {
            long lastModify = ((Long) deployed.get(jar)).longValue();
            if(jar.lastModified() > lastModify) { // 修改的 jar
                return true;
            }
            else {
                return false;
            }
        }
    }

    protected void doInit() throws Exception {

    }

    protected void doDestroy() throws Exception {

    }

    private Deployer getDeployer(File jar) {
        if(jar.getName().endsWith(".ear")) {
            return earDeployer;
        }
        else if(jar.getName().endsWith(".war")) {
            return webDeployer;
        }
        else if(jar.getName().endsWith(".jar")) {
            return ejbDeployer;
        }
        return null;
    }

    private Deployable buildModule(File jar) throws DeployException {
        if(jar.getName().endsWith(".ear")) {
            return new EARModule(jar);
        }
        else if(jar.getName().endsWith(".war")) {
            return new WebModule(jar);
        }
        else if(jar.getName().endsWith(".jar")) {
            return new EJBModule(jar);
        }
        return null;

    }

    public static void main(String[] args) {

    }
}