How to load Classes at runtime from a folder or JAR?
To do this, I need to be able to scan all of the .class files from the project location (JAR/WAR or just a folder)
Scanning all of the files in a folder is simple. One option is to call File.listFiles()
on the File
that denotes the folder, then iterate the resulting array. To traverse trees of nested folders, use recursion.
Scanning the files of a JAR file can be done using the JarFile
API ... and you don't need to recurse to traverse nested "folders".
Neither of these is particularly complicated. Just read the javadoc and start coding.
The following code loads all classes from a JAR file. It does not need to know anything about the classes. The names of the classes are extracted from the JarEntry.
JarFile jarFile = new JarFile(pathToJar);
Enumeration<JarEntry> e = jarFile.entries();
URL[] urls = { new URL("jar:file:" + pathToJar+"!/") };
URLClassLoader cl = URLClassLoader.newInstance(urls);
while (e.hasMoreElements()) {
JarEntry je = e.nextElement();
if(je.isDirectory() || !je.getName().endsWith(".class")){
continue;
}
// -6 because of .class
String className = je.getName().substring(0,je.getName().length()-6);
className = className.replace('/', '.');
Class c = cl.loadClass(className);
}
edit:
As suggested in the comments above, javassist would also be a possibility. Initialize a ClassPool somewhere before the while loop form the code above, and instead of loading the class with the class loader, you could create a CtClass object:
ClassPool cp = ClassPool.getDefault();
...
CtClass ctClass = cp.get(className);
From the ctClass, you can get all methods, fields, nested classes, .... Take a look at the javassist api: https://jboss-javassist.github.io/javassist/html/index.html
List All the classes inside jar file.
public static List getClasseNames(String jarName) {
ArrayList classes = new ArrayList();
if (debug)
System.out.println("Jar " + jarName );
try {
JarInputStream jarFile = new JarInputStream(new FileInputStream(
jarName));
JarEntry jarEntry;
while (true) {
jarEntry = jarFile.getNextJarEntry();
if (jarEntry == null) {
break;
}
if (jarEntry.getName().endsWith(".class")) {
if (debug)
System.out.println("Found "
+ jarEntry.getName().replaceAll("/", "\\."));
classes.add(jarEntry.getName().replaceAll("/", "\\."));
}
}
} catch (Exception e) {
e.printStackTrace();
}
return classes;
}