/*
* Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com>
* Licensed under the Apache License, Version 2.0 (the "License")
* $Id: ClasspathUtils.java 3918 2008-04-14 17:35:35Z gbevin $
*/
package com.uwyn.rife.tools;
import com.uwyn.rife.config.RifeConfig;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
public abstract class ClasspathUtils
{
public static ArrayList<String> getResourcesInDirectory(String directory)
{
return getResourcesInDirectory(directory, true, null);
}
public static ArrayList<String> getResourcesInDirectory(String directory, FileFilter filter)
{
return getResourcesInDirectory(directory, true, filter);
}
public static ArrayList<String> getResourcesInDirectory(String directory, boolean excludeJavaHomePaths)
{
return getResourcesInDirectory(directory, excludeJavaHomePaths, null);
}
public static ArrayList<String> getResourcesInDirectory(String directory, boolean excludeJavaHomePaths, FileFilter filter)
{
ArrayList<String> resources = new ArrayList<String>();
ArrayList<URL> classpath_components = ClasspathComponentsSingleton.INSTANCE.getClasspathComponents();
String classpath_component_filename = null;
File classpath_component_file = null;
String java_home = System.getProperty("java.home");
for (URL classpath_component : classpath_components)
{
try
{
classpath_component_filename = URLDecoder.decode(classpath_component.getFile(), "ISO-8859-1");
}
catch (UnsupportedEncodingException e)
{
// should never fail, it's a standard encoding
}
if (null != classpath_component_filename &&
(excludeJavaHomePaths && !classpath_component_filename.startsWith(java_home)))
{
classpath_component_file = new File(classpath_component_filename);
Pattern[] included = new Pattern[1];
if (directory != null)
{
if (File.separatorChar != '/')
{
directory = directory.replace('/', File.separatorChar);
}
included[0] = Pattern.compile("^"+StringUtils.encodeRegexp(directory)+".*");
}
Pattern[] excluded = new Pattern[1];
if (directory != null)
{
excluded[0] = Pattern.compile(".*\\.svn.*");
}
if ((null == filter || filter.accept(classpath_component_file)) &&
classpath_component_file.canRead())
{
ArrayList<String> filelist = null;
if (classpath_component_file.isFile() &&
classpath_component_filename.endsWith(".jar"))
{
try
{
JarFile jar_file = new JarFile(classpath_component_file);
Enumeration<JarEntry> jar_entries = jar_file.entries();
JarEntry jar_entry = null;
String entry_name = null;
filelist = new ArrayList<String>(jar_file.size());
while (jar_entries.hasMoreElements())
{
jar_entry = jar_entries.nextElement();
if (!jar_entry.isDirectory())
{
entry_name = jar_entry.getName();
if (StringUtils.filter(entry_name, included, excluded))
{
filelist.add(entry_name);
}
}
}
}
catch (IOException e)
{
// don't propagate this since this classpath entry will just be ignored when an error occurs
}
}
else if (classpath_component_file.isDirectory())
{
filelist = FileUtils.getFileList(classpath_component_file, included, excluded);
}
if (null != filelist)
{
for (String filelist_entry : filelist)
{
filelist_entry = filelist_entry.replace(File.separatorChar, '/');
if (!resources.contains(filelist_entry))
{
resources.add(filelist_entry);
}
}
}
}
}
}
return resources;
}
private static ArrayList<String> getClassPathCandidates(ClassLoader classloader)
{
// try to obtain the base resin classloader class
Class resin_classloader = null;
try
{
resin_classloader = classloader.loadClass("com.caucho.util.DynamicClassLoader");
}
catch (ClassNotFoundException e)
{
resin_classloader = null;
}
ArrayList<String> classpath_candidates = new ArrayList<String>();
URL[] classloader_urls = null;
do
{
// handle regular URLClassLoader classes
if (classloader instanceof URLClassLoader)
{
classloader_urls = ((URLClassLoader)classloader).getURLs();
for (URL classloader_url : classloader_urls)
{
if (classloader_url.getProtocol().equals("file"))
{
try
{
classpath_candidates.add(URLDecoder.decode(classloader_url.getPath(), "ISO-8859-1"));
}
catch (UnsupportedEncodingException e)
{
// should never fail, it's a standard encoding
}
}
}
}
// handle resin classloaders
else if (resin_classloader != null &&
resin_classloader.isAssignableFrom(classloader.getClass()))
{
try
{
Method method = resin_classloader.getDeclaredMethod("getClassPath", (Class[])null);
String resin_classpath = (String)method.invoke(classloader, (Object[])null);
classpath_candidates.addAll(StringUtils.split(resin_classpath, File.pathSeparator));
}
catch (SecurityException e)
{
// do nothing
}
catch (NoSuchMethodException e)
{
// do nothing
}
catch (IllegalArgumentException e)
{
// do nothing
}
catch (InvocationTargetException e)
{
// do nothing
}
catch (IllegalAccessException e)
{
// do nothing
}
}
classloader = classloader.getParent();
}
while (classloader != null);
return classpath_candidates;
}
public static String getClassPath(Class reference)
{
// construct the classpath string from the list
return StringUtils.join(getClassPathAsList(reference), File.pathSeparator);
}
public static List<String> getClassPathAsList(Class reference)
{
ArrayList<String> classpath = new ArrayList<String>();
// try to obtain the classpath element through the hierachy
// of classloaders
ArrayList<String> classpath_candidates = new ArrayList<String>();
classpath_candidates.addAll(getClassPathCandidates(Thread.currentThread().getContextClassLoader()));
classpath_candidates.addAll(getClassPathCandidates(reference.getClassLoader()));
// try to detect the location of the RIFE classes
String current_class_file = ClasspathUtils.class.getName().replace('.','/')+".class";
URL rife_classpath_resource = reference.getClassLoader().getResource(current_class_file);
if (rife_classpath_resource != null)
{
String rife_classpath_entry = rife_classpath_resource.toExternalForm();
if (rife_classpath_entry.startsWith("jar:file:"))
{
rife_classpath_entry = rife_classpath_entry.substring("jar:file:".length());
rife_classpath_entry = rife_classpath_entry.substring(0, rife_classpath_entry.indexOf("!"));
}
else if (rife_classpath_entry.startsWith("file:"))
{
rife_classpath_entry = rife_classpath_entry.substring("file:".length());
rife_classpath_entry = rife_classpath_entry.substring(0, rife_classpath_entry.indexOf(current_class_file));
}
else
{
rife_classpath_entry = null;
}
if (rife_classpath_entry != null)
{
classpath_candidates.add(rife_classpath_entry);
}
}
// include the system-wide classpath properties for completeness
classpath_candidates.addAll(StringUtils.split(RifeConfig.Global.getApplicationClassPath(), File.pathSeparator));
classpath_candidates.addAll(StringUtils.split(System.getProperty("sun.boot.class.path"), File.pathSeparator));
classpath_candidates.addAll(StringUtils.split(System.getProperty("java.class.path"), File.pathSeparator));
// iterate over the classpath candidate entries, validate them
// and add them to the classpath if they're no already present
File path_file = null;
for (String path : classpath_candidates)
{
if (!classpath.contains(path))
{
path_file = new File(path);
if (path_file.exists() &&
path_file.canRead() &&
(path_file.isDirectory() ||
(path_file.isFile() && path.endsWith(".jar"))))
{
classpath.add(path);
}
}
}
return classpath;
}
}