package org.rzo.yajsw.cache;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.vfs.AllFileSelector;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSelectInfo;
import org.apache.commons.vfs.FileSelector;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.VFS;
import org.apache.commons.vfs.impl.DefaultFileSystemManager;
import org.apache.commons.vfs.provider.local.LocalFile;
import org.rzo.yajsw.Constants;
import org.rzo.yajsw.config.YajswConfigurationImpl;
import org.rzo.yajsw.util.VFSUtils;
public class Cache
{
boolean _loaded = false;
public boolean load(YajswConfigurationImpl config)
{
try
{
// reload if not yet loaded, or wrapper.restart.reload_configuration
// is true
boolean reload = config.getBoolean("wrapper.restart.reload_configuration", Constants.DEFAULT_RELOAD_CONFIGURATION);
if (!reload && _loaded)
return true;
String workingDir = config.getString("wrapper.working.dir", ".");
String base = config.getString("wrapper.base", workingDir);
String cache = config.getCache();
DefaultFileSystemManager fsManager = (DefaultFileSystemManager) VFS.getManager();
FileObject basef = VFSUtils.resolveFile(".", base);
FileObject cachef = VFSUtils.resolveFile(".", cache);
if (!(cachef instanceof LocalFile))
{
System.out.println("cache must be a local folder -> abort");
return false;
}
if (!cachef.exists())
cachef.createFolder();
if (cachef.getType() != FileType.FOLDER)
{
System.out.println("cache must be a folder -> abort");
return false;
}
boolean cacheLocal = config.getBoolean("wrapper.cache.local", Constants.DFAULT_CACHE_LOCAL);
Configuration resources = config.subset("wrapper.resource");
for (Iterator it = resources.getKeys(); it.hasNext();)
{
String key = (String) it.next();
loadFiles("wrapper.resource." + key, config, basef, cachef, cacheLocal, fsManager);
}
Configuration classpath = config.subset("wrapper.java.classpath");
for (Iterator it = classpath.getKeys(); it.hasNext();)
{
String key = (String) it.next();
loadFiles("wrapper.java.classpath." + key, config, basef, cachef, cacheLocal, fsManager);
}
_loaded = true;
return true;
}
catch (Exception ex)
{
ex.printStackTrace();
}
return false;
}
private void loadFiles(String key, YajswConfigurationImpl config, FileObject basef, FileObject cachef, boolean cacheLocal,
DefaultFileSystemManager fsManager)
{
try
{
String value = config.getString(key);
List files = resolveFiles(basef, value, fsManager);
int count = 0;
for (Iterator it = files.iterator(); it.hasNext();)
{
FileObject source = (FileObject) it.next();
FileObject destination = loadFile(value, source, basef, cachef, cacheLocal, fsManager);
if (destination != null)
{
config.getFileConfiguration().setProperty(key + "$" + count++, destination.getURL().getFile().substring(2));
// System.out.println("set configuration "+key+" "+destination.getURL().getFile());
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
private List resolveFiles(FileObject basef, String value, DefaultFileSystemManager fsManager)
{
System.out.println("resolve files " + value);
try
{
ArrayList result = new ArrayList();
// if no wild card, just return the file
if (!(value.contains("?") || value.contains("*")))
{
result.add(VFSUtils.resolveFile(basef, value));
return result;
}
// if we have wild cards
{
// create a java pattern from the file pattern
String pattern = value.replaceAll("\\.", "\\\\.");
pattern = pattern.replaceAll("\\?", ".");
if (pattern.contains("/**/"))
pattern = pattern.replaceAll("/\\*\\*/", "/*/");
pattern = pattern.replaceAll("\\*", ".*");
pattern = basef.getName().getPath() + "/" + pattern;
final Pattern pat = Pattern.compile(pattern);
// find prefix with no pattern
int istar = value.indexOf("*");
if (istar <= 0)
istar = Integer.MAX_VALUE;
int iquest = value.indexOf("?");
if (iquest <= 0)
iquest = Integer.MAX_VALUE;
int i = Math.min(istar, iquest);
String prefix = null;
if (i < Integer.MAX_VALUE)
{
prefix = value.substring(0, i);
}
int depth = 0;
if (value.contains("**/"))
{
depth = Integer.MAX_VALUE;
}
else
while ((i = value.indexOf("*/")) != -1)
{
depth++;
value = value.substring(i + 2);
}
final int fdepth = depth;
FileSelector fs = new FileSelector()
{
public boolean includeFile(FileSelectInfo info) throws Exception
{
// files /x/x causes exceptions -> these are imaginary
// files -> ignore
if (info.getFile().getType() == FileType.IMAGINARY)
return false;
boolean result = pat.matcher(info.getFile().getName().getPath()).matches();
System.out.println(info.getFile().getName().getPath() + " " + result);
return result;
}
public boolean traverseDescendents(FileSelectInfo info) throws Exception
{
return info.getDepth() <= fdepth;
}
};
FileObject nbase;
if (prefix != null)
nbase = basef.resolveFile(prefix);
else
nbase = basef;
FileObject[] files = nbase.findFiles(fs);
if (files != null && files.length > 0)
return Arrays.asList(files);
else
return new ArrayList();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
return null;
}
private FileObject loadFile(String value, FileObject source, FileObject basef, FileObject cachef, boolean cacheLocal,
DefaultFileSystemManager fsManager)
{
try
{
boolean isLocal = source instanceof LocalFile;
if (isLocal && !cacheLocal)
return null;
FileObject destination = null;
boolean absolute = false;
// assume value is absolute
try
{
destination = VFSUtils.resolveFile((String) null, value);
absolute = true;
}
catch (Exception ex)
{
}
if (!absolute)
destination = VFSUtils.resolveFile(cachef, basef.getName().getRelativeName(source.getName()));
else
{
String fileName = destination.getName().getBaseName();
destination = VFSUtils.resolveFile(cachef, fileName);
}
if (fileChanged(source, destination))
{
destination.copyFrom(source, new AllFileSelector());
destination.getContent().setLastModifiedTime(source.getContent().getLastModifiedTime());
System.out.println("file loaded " + source.getName() + " -> " + destination.getName());
}
return destination;
}
catch (Exception ex)
{
ex.printStackTrace();
}
return null;
}
private boolean fileChanged(FileObject source, FileObject destination)
{
try
{
return !destination.exists() || source.getContent().getLastModifiedTime() != destination.getContent().getLastModifiedTime();
}
catch (FileSystemException e)
{
e.printStackTrace();
return true;
}
}
public static void main(String[] args)
{
Cache c = new Cache();
System.setProperty("wrapper.config", "http://localhost:8080/wrapper.helloworld.conf");
YajswConfigurationImpl config = new YajswConfigurationImpl();
c.load(config);
}
}