All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.appdapter.gui.util.ClassFinder Maven / Gradle / Ivy

Go to download

Appdapter Maven project including Java and Scala, produces jar, not bundle. Excludes concrete SLF4J binding.

The newest version!
package org.appdapter.gui.util;

import static org.appdapter.gui.util.PromiscuousClassUtilsA.classesSeen;
import static org.appdapter.gui.util.PromiscuousClassUtilsA.coerceClassloader;
import static org.appdapter.gui.util.PromiscuousClassUtilsA.forName;
import static org.appdapter.gui.util.PromiscuousClassUtilsA.getImplementingClasses;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.Callable;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.appdapter.core.convert.ReflectUtils;

/**
 * This is a stateless utility class that contains code for looking up
 * classes in the CLASSPATH and EXTDIRS in the current JVM. 
* * @todo - replace Set with List and use forName(className, false, null) that doesn't * initialize the class * * Changes: *
    *
  • 15.01.2001/Bartlomiej Niechwiej - checking for existance of a file/directory being searched added, underisableClassModifiers added
  • *
  • 08.02.2001/Marcin Slowik - replaced forName(classname) with forName(classname, false, loader) *
  • 20.01.2001/Bartlomiej Niechwiej - a classLoader parameter added to getClasses methods, additional API provided
  • *
* * */ public class ClassFinder { public static boolean DISABLE_CLASS_FINDER = true; /** * Class with these modifiers are skipped while searching the JVM classes. */ private static final int defaultUndesirableClassModifiers = 0;//Modifier.ABSTRACT | Modifier.INTERFACE | Modifier.PRIVATE | Modifier.PROTECTED; /** * Returns a set of all classes that implement or extend * the given class, directly or indirectly. */ public static Set> getClasses(Class ancestor) throws IOException { if (DISABLE_CLASS_FINDER) return new HashSet(); ///.trace("Scaning for subclasses of " + ancestor); if (class_Cache != null && class_Cache.size() > 10) { return (Set>) getImplementingClasses(ancestor); } Set> set = getClasses("", ancestor); //theLogger.trace("returning " + set.size() + " subclasses of " + ancestor); return set; } public static Set class_Cache = null; public static Set getAllClasses() throws IOException { if (class_Cache == null) { class_Cache = classesSeen; synchronized (class_Cache) { class_Cache.addAll(getClasses("", null)); } } return class_Cache; } /** * Returns a set of all classes within the given package (recursively) * that implement or extend the given class, directly or indirectly. */ public static Set> getClasses(String packageName, Class ancestor) throws IOException { return getClasses(packageName, ancestor, null, null, defaultUndesirableClassModifiers); } /** * Returns a set of all classes within the given package (recursively) * that implement or extend the given class, directly or indirectly. */ public static Set> getClasses(String packageName, Class ancestor, ClassLoader classLoader, String dirsString) throws IOException { return getClasses(packageName, ancestor, classLoader, dirsString, defaultUndesirableClassModifiers); } /** * Returns a set of all classes within the given package (recursively) * that implement or extend the given class, directly or indirectly. * All classes that have at least one modifier from undesirableClassModifiers * set are skipped. */ public static Set> getClasses(final String packageName, final Class ancestor, final ClassLoader classLoader, final String dirsString, final int undesirableClassModifiers) throws IOException { return ReflectUtils.cachedResult(new Callable() { @Override public Object call() throws Exception { return getClassesImpl(packageName, ancestor, classLoader, dirsString, undesirableClassModifiers); } }, packageName, ancestor, classLoader, dirsString, undesirableClassModifiers); } public static Set> getClassesImpl(String packageName, Class ancestor, ClassLoader classLoader0, String dirsString, int undesirableClassModifiers) throws IOException { Set> classes = new HashSet(); if (DISABLE_CLASS_FINDER) return classes; if (packageName == null) { packageName = ""; } ClassLoader classLoader; if (classLoader0 == null) //use the default class loader for this class classLoader = ClassFinder.class.getClassLoader(); else classLoader = coerceClassloader(classLoader0, true, false, false); //Get all class names Set allClassNames = getAllClassNames(dirsString); //Loop through the class names Iterator it = allClassNames.iterator(); while (it.hasNext()) { String className = (String) it.next(); //Check if the class is in the right package if (className.startsWith(packageName)) { //check if it should be included try { Class cls = null; try { cls = forName(className, false, classLoader); } catch (NoClassDefFoundError ncdfe) { //ignore the exception because nothing can be do in this case continue; } if (cls == null) { logError("Cant find class called " + className, null); continue; } if ((ancestor == null || ancestor.isAssignableFrom(cls)) && (cls.getModifiers() & undesirableClassModifiers) == 0) { classes.add(cls); } } catch (Throwable err) { //Something went wrong. Skip it and move on. if (err.getCause() != null) err = err.getCause(); if (err instanceof ClassNotFoundException) { continue; } if (err instanceof VirtualMachineError) { throw (VirtualMachineError) err; } logError("Class '" + className + "' could not be loaded - I will ignore it", err); } } } return classes; } /** * Returns a set of all class names within the given package, * recursively */ public static Set getClassNames(final String packageName) { return ReflectUtils.cachedResult(new Callable() { @Override public Object call() throws Exception { Set classNames = new HashSet(); Set allClassNames = getAllClassNames(); Iterator it = allClassNames.iterator(); while (it.hasNext()) { String className = (String) it.next(); if (className.startsWith(packageName)) { classNames.add(className); } } return classNames; } }, packageName); } /** * Returns a set of all class names currently available in this JVM */ static Set classNames_Cache = new HashSet(); private static Set getAllClassNames() throws IOException { if (classNames_Cache == null || classPathFiles_Cache.size() == 0) { classNames_Cache = getAllClassNames0(); } return classNames_Cache; } public static Set getAllClassNames0() throws IOException { return getAllClassNames(null); } /** * Returns a set of all class names currently available in this JVM * * @param dirsString additional directiories to search, it can be null */ static Map cachedClassNames = new HashMap(); public synchronized static Set getAllClassNames(String dirsString) throws IOException { String key = dirsString; if (key == null || key.length() == 0 || key.equals("$CLASSPATH")) key = ""; synchronized (cachedClassNames) { Set fnd = cachedClassNames.get(key); if (fnd != null) return fnd; if (cachedClassNames.containsKey(key)) { return null; } cachedClassNames.put(key, null); fnd = getAllClassNames0(dirsString); cachedClassNames.put(key, fnd); return fnd; } } public synchronized static Set getAllClassNames0(String dirsString) throws IOException { Set classNames = new HashSet(); if (DISABLE_CLASS_FINDER) return classNames; Set classPathFiles = getClassPathFiles(); if (dirsString != null) classPathFiles.addAll(getFilesFromExtDirs(dirsString)); Iterator it = classPathFiles.iterator(); while (it.hasNext()) { File classPathFile = (File) it.next(); if (classPathFile.exists()) { if (classPathFile.isDirectory()) { classNames.addAll(getClassNamesFromDirectory(classPathFile)); } else { classNames.addAll(getClassNamesFromJar(classPathFile)); } } } return classNames; } //====== Private utility methods ============================ /** * Returns a set of files containing all the * class path JARs, ZIPs, and directories */ static Set classPathFiles_Cache = new HashSet(); private static Set getClassPathFiles() { if (classPathFiles_Cache == null || classPathFiles_Cache.size() == 0) { classPathFiles_Cache = getClassPathFiles0(); } return classPathFiles_Cache; } private static Set getClassPathFiles0() { Set classPathFiles = new HashSet(); //Get the global class path and ext dirs String classPathString = System.getProperty("java.class.path", "."); String extDirsString = System.getProperty("java.ext.dirs", ""); //For classpath, each element is either a JAR/ZIP file or a class file root StringTokenizer st = new StringTokenizer(classPathString, ";"); while (st.hasMoreTokens()) { classPathFiles.add(new File(st.nextToken())); } //For ext dirs, each element is a directory who's JAR/ZIP files and //subdirectories should be included in the classpath classPathFiles.addAll(getFilesFromExtDirs(extDirsString)); return classPathFiles; } /** * Returns a set of files in all directories in the given * extDirsString. * * @param extDirsString a string in the same format as java.ext.dirs * propertu * @return a set of files */ private static Set getFilesFromExtDirs(String extDirsString) { Set classPathFiles = new HashSet(); StringTokenizer st = new StringTokenizer(extDirsString, ";"); while (st.hasMoreTokens()) { File dir = new File(st.nextToken()); if (dir.exists() && dir.isDirectory()) { File[] files = dir.listFiles(); for (int i = 0; i < files.length; ++i) { File file = files[i]; if (file.isDirectory()) { classPathFiles.add(file); } else { String name = file.getName().toLowerCase(); if (name.endsWith(".jar") || name.endsWith(".zip")) { classPathFiles.add(file); } } } } } return classPathFiles; } /** * Returns a set of the names of all classes under the given root directory. * * @param rootDir the directory under which the classes are stored */ private static Set getClassNamesFromDirectory(File rootDir) throws IOException { return getClassNamesFromDirectory(null, rootDir); } /** * Returns a set of the names of all classes under the given root directory. * The given package name will be put in front of the class name. * * @param packageName for example "com" or "java.lang" * @param rootDir the directory under which the classes are stored */ private static Set getClassNamesFromDirectory(final String packageName, final File rootDir) throws IOException { return ReflectUtils.cachedResult(new Callable() { @Override public Object call() throws Exception { return getClassNamesFromDirectoryImpl(packageName, rootDir); } }, packageName, rootDir); } private static Set getClassNamesFromDirectoryImpl(String packageName, File rootDir) throws IOException { Set classNames = new HashSet(); File[] files = rootDir.listFiles(); for (int i = 0; i < files.length; i++) { File file = files[i]; if (file.isDirectory()) { //for example "lang" String dirName = file.getName(); //for example "java.lang" if the packageName was "java" was dirName was "lang" String nextPackageName; if (packageName == null || packageName.equals("")) { nextPackageName = dirName; } else { nextPackageName = packageName + "." + dirName; } classNames.addAll(getClassNamesFromDirectoryImpl(nextPackageName, file)); } else { String fileName = file.getName(); if (fileName.toLowerCase().endsWith(".class")) { //The short name is the class name without the package name prefix String shortClassName = fileName.substring(0, fileName.length() - 6); String fullClassName = packageName + "." + shortClassName; classNames.add(fullClassName); } } } return classNames; } /** * Returns a set of the names of all classes stored * in the given JAR or ZIP file */ private static Set getClassNamesFromJar(final File jarFile) throws IOException { return ReflectUtils.cachedResult(new Callable() { @Override public Object call() throws Exception { Set classNames = new HashSet(); //Open the JAR file ZipFile file = new ZipFile(jarFile); //Loop through the contents of the JAR Enumeration enum0 = file.entries(); while (enum0.hasMoreElements()) { ZipEntry entry = (ZipEntry) enum0.nextElement(); if (!entry.isDirectory()) { String fileName = entry.getName(); if (fileName.endsWith(".class")) { String className = getClassNameFromFileName(fileName); classNames.add(className); } } } return classNames; } }, jarFile); } /** * Given a string of type "java/lang/String.class" it will return * the corresponding class name "java.lang.String" */ private static String getClassNameFromFileName(String fileName) { String temp; //Get rid of .class at the end if (fileName.endsWith(".class")) { fileName = fileName.substring(0, fileName.length() - 6); } //Change slashes to dots temp = replace(fileName, "\\", "."); temp = replace(temp, "/", "."); // temp = replace(temp, "$", "."); return temp; } public static String replace(String s, String b, String a) { return s.replace(b, a); } private static void logError(String msg, Throwable err) { //theLogger.error(msg, err); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy