/* JFox, the OpenSource J2EE Application Server
 *
 * Copyright (C) 2002 huihoo.com
 * Distributable under GNU LGPL license
 * See the GNU Lesser General Public License for more details.
 */

package org.jfox.ejb.deploy;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.io.File;
import java.io.FilenameFilter;
import java.net.MalformedURLException;
import java.net.URL;

import org.huihoo.jfox.system.ServiceSupport;

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

public class EJBDeployService extends ServiceSupport implements DeployService {

  private EJBDeployer deployer = null;
  // 所有要监视的 deploy 目录
  private volatile List directories = new ArrayList();
  // 所有的已发布的jar, url => lastModify
  private Map jars = new HashMap();
  private long sleepTime = 10000L; // 10s

  private static FilenameFilter filter = new FilenameFilter() {
                                              public boolean accept(File dir, String name) {
                                                if(name.endsWith(".jar")) {
                                                  return true;
                                                }
                                                else {
                                                  return false;
                                                }
                                              }
                                            };

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

  public long getSleepTime() {
    return sleepTime;
  }

  /**
   *
   * @param url
   */
  public void addDeployDirectory(String url) {
    File file = new File(url);
    try {
      String dirUrl = file.toURL().toString();
      if(!file.exists()){
        logger.warn(dirUrl + " is not exists.");
      }
      else if(!file.isDirectory()){
        logger.warn("add deploy directory " + dirUrl + " faild, it must be a directory.");
      }
      else {
        logger.info("add deploy directory " + dirUrl + " successfully");
        synchronized(directories) {
          directories.add(file);
        }
      }
    }
    catch(MalformedURLException e){
      e.printStackTrace();
      logger.warn(e.getMessage(),e);
    }

  }

  /**
   * 得到当前监视的 deploy 目录
   * @return
   */
  public File[] getDeployDirectories() {
    return (File[])directories.toArray(new File[0]);
  }

  protected void doInit() throws Exception {
    deployer = new EJBDeployer();
    deployer.init();
  }

  public URL[] getDeployedJars(){
    return (URL[])jars.keySet().toArray(new URL[0]);
  }

  protected void doStart() throws Exception {
    Thread deployThread =  new Thread(this,name);
    deployThread.setPriority(Thread.MIN_PRIORITY);
    deployThread.start();
  }

  protected void doStop() throws Exception {

  }

  protected void doDestroy() throws Exception {
    deployer = null;
    directories.clear();
    jars.clear();
  }

  public void run() {
//    int count = 0;
    while(isRunning()){
//      if(count%20==0) { // 不要打印太多的日志
//        logger.debug("scanning deploy directories...");
//      }
      Map newJars = new HashMap();
      File[] directoriesNames = this.getDeployDirectories();
      for( int i=0; i<directoriesNames.length; i++){
//        if(count%20==0) {
//          logger.debug("scaning " + directoriesNames[i].getAbsoluteFile().toString());
//        }
        File dir = directoriesNames[i];
        if(dir.exists() && dir.isDirectory()){
          // 取得目录下所有的 .jar 文件
          File[] jarFiles = dir.listFiles(filter);
          for(int j=0; j< jarFiles.length; j++){
            File jar = jarFiles[j];
            try {
              newJars.put(jar.toURL(),new Long(jar.lastModified()));
              if(mustBeDeploy(jar)){ // 要发布
                deployer.deploy(jar.toURL());
              }
              jars.remove(jar.toURL());
            }
            catch(Exception e){
              logger.warn(e.getMessage(),e);
            }
          }
        }
      }

      // jars 里面剩下的是已经删除的jar, undeploy 它们
      for(Iterator it = jars.keySet().iterator(); it.hasNext();){
        URL url = (URL)it.next();
        try {
          deployer.undeploy(url);
        }
        catch(Exception e){
          logger.warn("undeploy " + url + " failed", e);
        }
      }
      jars = newJars;

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

  private boolean mustBeDeploy(File jar){
    try {
      URL jarUrl = jar.toURL();
      if(!jars.containsKey(jarUrl)){ // 新增的 jar
        return true;
      }
      else {
        long lastModify = ((Long)jars.get(jarUrl)).longValue();
        if(jar.lastModified() > lastModify) { // 修改的 jar
          return true;
        }
        else {
          return false;
        }
      }
    }
    catch(MalformedURLException e){
      e.printStackTrace();
      logger.warn(e.getMessage(), e);
      return false;
    }
  }

  public static void main(String[] args) {

  }
}