/*
 * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
 *
 * This file is part of Resin(R) Open Source
 *
 * Each copy or derived work must preserve the copyright notice and this
 * notice unmodified.
 *
 * Resin Open Source is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Resin Open Source 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, or any warranty
 * of NON-INFRINGEMENT.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Resin Open Source; if not, write to the
 *   Free SoftwareFoundation, Inc.
 *   59 Temple Place, Suite 330
 *   Boston, MA 02111-1307  USA
 *
 * @author Scott Ferguson
 */

package com.caucho.jca;

import java.io.IOException;

import java.util.HashSet;
import java.util.ArrayList;
import java.util.Iterator;

import com.caucho.util.L10N;
import com.caucho.util.CauchoSystem;

import com.caucho.vfs.Path;
import com.caucho.vfs.Vfs;

import com.caucho.config.ConfigException;

import com.caucho.log.Log;

/**
 * The generator for the resource-deploy
 */
public class ResourceDeploy {
  private static final L10N L = new L10N(ResourceDeploy.class);
  
  private Path _rarDir;
  private Path _rarExpandDir;

  private String _expandPrefix = "";

  private HashSet<String> _rarNames = new HashSet<String>();

  private volatile boolean _isInit;

  public ResourceDeploy()
  {
    setExpandPrefix("_rar_");
  }

  /**
   * Gets the rar directory.
   */
  public Path getPath()
  {
    return _rarDir;
  }

  /**
   * Sets the rar directory.
   */
  public void setPath(Path path)
  {
    _rarDir = path;
  }

  /**
   * Sets the war expand dir to check for new applications.
   */
  public void setExpandPath(Path path)
  {
    _rarExpandDir = path;
  }

  /**
   * Gets the war expand directory.
   */
  public Path getExpandPath()
  {
    if (_rarExpandDir != null)
      return _rarExpandDir;
    else
      return _rarDir;
  }

  /**
   * Returns the expand prefix.
   */
  public String getExpandPrefix()
  {
    return _expandPrefix;
  }

  /**
   * Sets the expand prefix.
   */
  public void setExpandPrefix(String prefix)
  {
    _expandPrefix = prefix;
  }

  public boolean isModified()
  {
    try {
      return ! _rarNames.equals(getRarNames());
    } catch (Exception e) {
      return false;
    }
  }

  /**
   * Initialize the resource-deploy.
   */
  public void init()
    throws ConfigException
  {
    synchronized (this) {
      if (_isInit)
	return;
      _isInit = true;
    }
    
    if (getPath() == null)
      throw new ConfigException(L.l("resource-deploy requires a path attribute"));

    try {
      _rarNames = getRarNames();
      
      Iterator<String> iter = _rarNames.iterator();
      while (iter.hasNext()) {
	String name = iter.next();

	ResourceArchive rar;

	rar = new ResourceArchive();
	rar.setRarPath(getPath().lookup(name + ".rar"));
	rar.setRootDirectory(getExpandPath().lookup(getExpandPrefix() + name));

	Path oldPwd = Vfs.getPwd();

	try {
	  Vfs.setPwd(rar.getRootDirectory());

	  for (ResourceConfig config : ResourceDefault.getDefaultList()) {
	    config.getBuilderProgram().configure(rar);
	  }
	} finally {
	  Vfs.setPwd(oldPwd);
	}

	rar.init();

	ResourceArchiveManager.addResourceArchive(rar);
      }
    } catch (ConfigException e) {
      throw e;
    } catch (Throwable e) {
      throw new ConfigException(e);
    }
  }

  /**
   * Return the war-expansion directories which were added.
   */
  private HashSet<String> getRarNames()
    throws IOException
  {
    HashSet<String> rarNames = new HashSet<String>();

    Path rarDir = getPath();
    Path rarExpandDir = getExpandPath();

    if (rarDir == null || rarExpandDir == null)
      return rarNames;

    String []rarDirList = rarDir.list();

    // collect all the new wars
    loop:
    for (int i = 0; i < rarDirList.length; i++) {
      String rarName = rarDirList[i];
      String appName;

      if (! rarName.endsWith(".rar"))
        continue;

      Path path = rarDir.lookup(rarName);

      if (! path.canRead())
        continue;

      appName = rarName.substring(0, rarName.length() - 4);

      if (CauchoSystem.isCaseInsensitive())
        appName = appName.toLowerCase();

      rarNames.add(appName);
    }
    
    String []rarExpandList = rarExpandDir.list();
    ArrayList<String> newNames = new ArrayList<String>();

    // collect all the new rar expand directories
    loop:
    for (int i = 0; i < rarExpandList.length; i++) {
      String rarDirName = rarExpandList[i];

      if (! rarDirName.startsWith(getExpandPrefix()))
	continue;

      if (CauchoSystem.isCaseInsensitive())
        rarDirName = rarDirName.toLowerCase();

      Path path = rarExpandDir.lookup(rarDirName);

      if (! path.isDirectory() || ! rarDirName.startsWith(getExpandPrefix()))
        continue;
      
      String appName = rarDirName.substring(getExpandPrefix().length());

      if (! newNames.contains(appName))
        newNames.add(appName);

      rarNames.add(appName);
    }

    return rarNames;
  }
}
