/*
* Copyright (c) 1998-2011 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 Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.jca.ra;
import com.caucho.config.ConfigException;
import com.caucho.env.deploy.DeployController;
import com.caucho.env.deploy.DeployMode;
import com.caucho.jca.cfg.ResourceConfig;
import com.caucho.lifecycle.Lifecycle;
import com.caucho.lifecycle.LifecycleState;
import com.caucho.server.util.CauchoSystem;
import com.caucho.util.L10N;
import com.caucho.vfs.Path;
import com.caucho.vfs.Vfs;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
/**
* The generator for the resource-deploy
*/
public class ResourceDeploy {
private static final L10N L = new L10N(ResourceDeploy.class);
private final ResourceDeployAdmin _admin = new ResourceDeployAdmin(this);
private ClassLoader _classLoader;
private Path _containerRootDirectory;
private Path _rarDir;
private Path _rarExpandDir;
private String _expandPrefix = "";
private HashSet<String> _rarNames = new HashSet<String>();
private volatile boolean _isInit;
public ResourceDeploy()
{
_classLoader = Thread.currentThread().getContextClassLoader();
setExpandPrefix("_rar_");
_containerRootDirectory = Vfs.getPwd();
}
Path getContainerRootDirectory()
{
return _containerRootDirectory;
}
/**
* Gets the rar directory.
*/
public Path getPath()
{
return _rarDir;
}
/**
* Sets the rar directory.
*/
public void setPath(Path path)
{
_rarDir = path;
}
public Path getArchiveDirectory()
{
return getPath();
}
public Path getArchivePath(String name)
{
return getArchiveDirectory().lookup(name + getExtension());
}
/**
* Returns the combination of prefix, name, and suffix used for expanded
* archives.
*
* @return
*/
protected String getExpandName(String name)
{
return getExpandPrefix() + name + getExpandSuffix();
}
/**
* Sets the war expand dir to check for new applications.
*/
public void setExpandPath(Path path)
{
_rarExpandDir = path;
}
/**
* @deprecated use {@link @getExpandDirectory}
*/
public Path getExpandPath()
{
return getExpandDirectory();
}
/**
* Gets the rar expand directory.
*/
public Path getExpandDirectory()
{
if (_rarExpandDir != null)
return _rarExpandDir;
else
return _rarDir;
}
/**
* Returns the location of an expanded archive, or null if no archive with
* the passed name is deployed.
*
* @param name a name, without an extension
*/
public Path getExpandPath(String name)
{
if (!isDeployedKey(name))
return null;
return getExpandDirectory().lookup(getExpandName(name));
}
private boolean isDeployedKey(String name)
{
return _rarNames.contains(name);
}
/**
* 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.
*/
@PostConstruct
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"));
deployResources();
_admin.register();
}
private void deployResources()
{
HashSet<String> oldNames = _rarNames;
try {
_rarNames = getRarNames();
for (String oldName : oldNames) {
if (! _rarNames.contains(oldName))
undeployResource(oldName);
}
for (String name : _rarNames) {
if (oldNames.contains(name))
continue;
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 (Exception e) {
throw ConfigException.create(e);
}
}
private void undeployResource(String name)
{
ResourceArchiveManager.removeResourceArchive(name);
}
/**
* 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(Locale.ENGLISH);
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(Locale.ENGLISH);
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;
}
public String getExtension()
{
return ".rar";
}
public String getExpandSuffix()
{
return "";
}
public long getDependencyCheckInterval()
{
return -1;
}
public DeployMode getStartupMode()
{
return DeployMode.AUTOMATIC;
}
public DeployMode getRedeployMode()
{
return DeployMode.MANUAL;
}
public String getState()
{
if (! _isInit)
return LifecycleState.NEW.toString();
else
return LifecycleState.ACTIVE.toString();
}
public void start()
{
// XXX:
}
public Throwable getConfigException()
{
// XXX:
return null;
}
public void stop()
{
// XXX:
}
public void update()
{
// XXX:
}
public String[] getNames()
{
// XXX:
return new String[0];
}
public void stop(String name)
{
// XXX:
}
public void start(String name)
{
Thread thread = Thread.currentThread();
ClassLoader oldLoader = thread.getContextClassLoader();
try {
thread.setContextClassLoader(_classLoader);
deployResources();
} finally {
thread.setContextClassLoader(oldLoader);
}
}
public Throwable getConfigException(String moduleID)
{
// XXX:
return null;
}
public void undeploy(String name)
{
// XXX:
}
}