package lcm.util;
import java.io.*;
import java.util.*;
import java.util.jar.*;
import java.util.zip.*;
import java.net.*;
import java.lang.reflect.*;
public class ClassDiscoverer
{
public static void findClasses(ClassVisitor visitor)
{
String ps = System.getProperty("path.separator");
// In order to correctly handle types that reference other
// types whose definitions are in another JAR file, create a
// big "master" classpath that contains everything we might
// want to load.
String cp = System.getenv("CLASSPATH")+ ps +System.getProperty("java.class.path");
findClasses(cp, visitor);
}
private static void visitDirectory(ClassVisitor visitor, URLClassLoader cldr,
String classpath_entry, File dir, String visiting_classpath) {
if(!dir.canRead())
return;
for(File f : dir.listFiles()) {
if(!f.canRead())
continue;
String fname = f.getName();
if(f.isDirectory()) {
// found a directory. recursively traverse the directory and
// search for .class files
if(fname.contains("."))
continue;
visitDirectory(visitor, cldr, classpath_entry, f, fname + ".");
} else if(f.isFile() && fname.endsWith(".class")) {
// found a .class file. Construct its full classname and pass
// it to the class visitor
String cn = visiting_classpath + fname.substring(0, fname.length()-6);
try {
Class cls = cldr.loadClass(cn);
if (cls != null)
visitor.classFound(classpath_entry, cls);
} catch (Throwable ex) { }
}
}
}
/** Given a colon-delimited list of jar files, iterate over the
* classes in them.
* @param cp The colon-deliimited classpath to search
**/
public static void findClasses(String cp, ClassVisitor visitor)
{
if (cp == null)
return;
String ps = System.getProperty("path.separator");
String[] items = cp.split(ps);
// Create a class loader that has access to the whole class path.
URLClassLoader cldr;
try {
URL[] urls = new URL[items.length];
for (int i = 0; i < items.length; i++)
urls[i] = new File(items[i]).toURL();
cldr = new URLClassLoader(urls);
} catch (IOException ex) {
System.out.println("ClassDiscoverer ERR: "+ex);
return;
}
for (int i = 0; i < items.length; i++) {
String item = items[i];
if (item.endsWith(".jar")) {
try {
JarFile jf = new JarFile(item);
for (Enumeration<JarEntry> e = jf.entries() ; e.hasMoreElements() ;) {
JarEntry je = e.nextElement();
String n = je.getName();
// skip private classes?
// if (n.contains("$"))
// continue;
if (n.endsWith(".class")) {
// convert the path into a class name
String cn = n.substring(0, n.length()-6);
cn = cn.replace('/', '.');
cn = cn.replace('\\', '.');
// try loading that class
try {
Class cls = cldr.loadClass(cn);
if (cls == null)
continue;
visitor.classFound(item, cls);
} catch (Throwable ex) {
System.out.println("ClassDiscoverer: "+ex);
System.out.println(" jar: "+item);
System.out.println(" class: "+n);
}
}
}
} catch(IOException ioe) {
System.out.println("Error extracting "+items[i]);
}
} else {
File f = new File(item);
if(!f.isDirectory())
continue;
visitDirectory(visitor, cldr, item, f, "");
}
}
}
public interface ClassVisitor
{
public void classFound(String jarfile, Class cls);
}
// Just list every class that we can find!
public static void main(String args[])
{
ClassVisitor cv = new ClassVisitor() {
public void classFound(String jarfile, Class cls) {
System.out.printf("%-30s %s\n", jarfile, cls);
}
};
ClassDiscoverer.findClasses(cv);
}
}