Hi, I need help :)
I'm trying to make a Java application that scans all the .class files it can find, looking for my custom annotations, and then parses them into an XML file. I have a class that scans the classpath, finds all .class files, and passes them on to the parser. Now, when I run this project in Eclipse, it works fine - finds all the .class files, filters them and parses them. However, when I convert the app into a runnable JAR, or an EXE file for Windows, it doesn't find anything. Even if the class files are in the directory where the app is, it still doesn't see them. And when I explicitly select a .class file and give it to my classFinder class, I get a ClassNotFound Exception. Here's the code that I use to scan for all .class files and filter them, I suspect that's where the problem is:
public class ClassFinder {
private final FilenameFilter classFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".class");
}
};
/**
* Finds all classes that are in the directories on the classpath. It will
* find all classes in subdirectories as well. Note that this method will
* not search for classes that are in jars on the classpath.
*
* @return a list of found classes
*/
public List<Class<?>> findAllClassesOnClasspath() {
List<Class<?>> classes = new LinkedList<Class<?>>();
List<String> classNames = listClassNames();
for (String className : classNames) {
className = className.replace(File.separatorChar, '.');
className = className.substring(0, className.length() - ".class".length());
if (!className.contains("$")) {
try {
Class<?> clazz = Class.forName(className);
if (clazz.getAnnotation(SuiteAnnotation.class) != null) {
classes.add(clazz);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
return classes;
}
private List<String> listClassNames() {
String classpath = System.getProperty("java.class.path", "");
StringTokenizer filesTokenizer = new StringTokenizer(classpath, File.pathSeparator);
List<String> classes = new LinkedList<String>();
while (filesTokenizer.hasMoreTokens()) {
String token = filesTokenizer.nextToken();
File classpathElement = new File(token);
if (classpathElement.isDirectory()) {
String elementPath = classpathElement.getAbsolutePath();
List<File> dirs = new LinkedList<File>();
dirs.add(classpathElement);
dirs.addAll(findSubdirectories(classpathElement));
for (File dir : dirs) {
String packageName = dir.getAbsolutePath().substring(elementPath.length());
if (packageName.startsWith("" + File.separatorChar)) {
packageName = packageName.substring(1);
}
List<String> classesInDir = Arrays.asList(dir.list(classFilter));
if (classesInDir == null) {
System.out.println("Root je: " + dir.getName());
}
List<String> fullClassNames = new LinkedList<String>();
for (String classInDir : classesInDir) {
fullClassNames.add(packageName + File.separatorChar + classInDir);
}
classes.addAll(fullClassNames);
}
}
}
return classes;
}
private List<File> findSubdirectories(File dir) {
assert dir.isDirectory();
List<File> results = new LinkedList<File>();
List<File> rootFiles = Arrays.asList(dir.listFiles());
for (File file : rootFiles) {
if (file.isDirectory()) {
results.add(file);
results.addAll(findSubdirectories(file));
}
}
return results;
}
public static void main(String[] args) {
List<Class<?>> classes = new ClassFinder().findAllClassesOnClasspath();
for (Class<?> clazz : classes) {
System.out.println(clazz);
}
}
}
Can anyone help? Why does this work if I run it as a project in Eclipse (or in Netbeans, works in both), but not when I run it as a standalone JAR or EXE file in Windows? When run as a project, it returns a list of classes it found, but when run as a runnable JAR, or EXE in Windows, it doesn't find anything. Why?