ClassPathUtil.java
package cern.accsoft.steering.jmad.util;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* utility to collect the effective classpath. This is not that trivial since the classpath is combine of the entries
* from the system property and also from classpath entries in jar file.
*
* @author Kajetan Fuchsberger (kajetan.fuchsberger at cern.ch)
*/
public class ClassPathUtil {
/** the logger for the class */
private final static Logger LOGGER = LoggerFactory.getLogger(ClassPathUtil.class);
/**
* collects all the classpath-entries from the different resources:
* <ul>
* <li>entries of the system classpath
* <li>the loaded jars
* <li>entries from classpath-attribute in any jars as detected before
* </ul>
*
* @return all the entries
*/
public static final Set<String> getAllClassPathEntries() {
Set<String> entries = new HashSet<String>();
processEntries(entries, getSystemPropertyClassPathEntries(), true);
processEntries(entries, getLoadedJarNames(), false);
return entries;
}
/**
* adds all the newEntries to the entries, if they are not already there. And if a new entry is added and the new
* entry represents a jar then it checks also if there are entries in the manifes of the classpath and adds them
* also by calling itself recursively.
*
* @param entries the set of entries to which the new ones shall be added
* @param newEntries the entries to add.
*/
private static void processEntries(Set<String> entries, List<String> newEntries, boolean assumeFile) {
for (String entry : newEntries) {
if (entry == null || entry.isEmpty()) {
continue;
}
String unifiedEntry = unifyName(entry, assumeFile);
if (!entries.contains(unifiedEntry)) {
entries.add(unifiedEntry);
LOGGER.debug("Added classpath-entry: '" + unifiedEntry + "'");
if (JarUtil.isJarName(unifiedEntry)) {
processEntries(entries, getClassPathEntriesFromJarFile(unifiedEntry), true);
}
}
}
}
/**
* extracts the class path entries from the system classpath.
*
* @return all the entries from the system classpath
*/
private static List<String> getSystemPropertyClassPathEntries() {
String classPath = System.getProperty("java.class.path", ".");
String[] classPathEntries = classPath.split(File.pathSeparator);
return Arrays.asList(classPathEntries);
}
/**
* extracts the class path entries from the jar-manifest
*
* @param fileName the filename from which to extract the entries
* @return the entries
*/
private static List<String> getClassPathEntriesFromJarFile(String fileName) {
String manifestClassPath = JarUtil.getManifestClassPathFromJarFile(fileName);
String[] classPathEntries = manifestClassPath.split(" ");
return Arrays.asList(classPathEntries);
}
/**
* crawls through all classloaders and gets the names of all loaded jars
*
* @return a list of jar names
*/
private static List<String> getLoadedJarNames() {
List<String> retval = new ArrayList<String>();
ClassLoader classLoader = ClassPathUtil.class.getClassLoader();
while (classLoader != null) {
if (classLoader instanceof URLClassLoader) {
URL[] urls = ((URLClassLoader) classLoader).getURLs();
for (URL url : urls) {
if (url != null) {
String name = url.toExternalForm();
if (JarUtil.isJarName(name)) {
retval.add(name);
}
}
}
}
classLoader = classLoader.getParent();
}
return retval;
}
private static final String unifyName(final String name, boolean file) {
String newName = name.replaceAll("\\\\", "\\/");
if (file) {
if (!newName.startsWith("file:")) {
newName = "file:" + newName;
}
}
if (OsUtil.isWindows()) {
/*
* remove trailing slashes
*/
newName = newName.replace("file:/", "file:");
}
return newName;
}
}