package nbtool.util;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.LinkedList;
import java.util.List;
import nbtool.gui.logviews.misc.ViewParent;
public class ClassFinder {
private static final Debug.DebugSettings debug =
Debug.createSettings(true, true, true, Debug.INFO, null);
interface ClassCallback {
public boolean callback(Class<?> arg) throws Exception;
}
private static void nbitesClassCaller(final ClassCallback impl) {
final Path baseLoadDir = FileSystems.getDefault().getPath(ToolSettings.NBITES_DIR,
"/build/nbtool/");
final Path baseDir = baseLoadDir.resolve("nbtool/");
final int baseCount = baseDir.getNameCount() - 1;
try {
final URLClassLoader loader = new URLClassLoader(new URL[]{baseLoadDir.toUri().toURL()});
Files.walkFileTree(baseDir, new SimpleFileVisitor<Path>(){
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path subPath = file.subpath(baseCount, file.getNameCount());
String className = subPath.toString().replace('/', '.');
if (className.endsWith(".class")) {
className = className.substring(0, className.length() - ".class".length());
try {
Class<?> fileClass = loader.loadClass(className);
boolean ok = impl.callback(fileClass);
if (!ok) return FileVisitResult.TERMINATE;
} catch (Exception e) {
debug.error("nbitesClassCaller ending because %s: %s",
e.getClass().getName(), e.getMessage());
e.printStackTrace();
return FileVisitResult.TERMINATE;
}
}
return FileVisitResult.CONTINUE;
}
});
loader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void callAllInstancesOfStaticMethod(final String methodName) {
ClassFinder.nbitesClassCaller(new ClassCallback(){
@Override
public boolean callback(Class<?> arg) throws Exception {
for (Method m : arg.getDeclaredMethods()) {
if (Modifier.isStatic(m.getModifiers()) &&
m.getName().equals(methodName)) {
Debug.print("ClassFinder: invoking %s on class %s",
methodName, arg.getName());
m.invoke(null);
}
}
return true;
}
});
}
public static List<Class<?>> findAllSubclasses(final Class<?> parent) {
final LinkedList<Class<?>> found = new LinkedList<>();
nbitesClassCaller(new ClassCallback(){
@Override
public boolean callback(Class<?> arg) throws Exception {
if (parent.isAssignableFrom(arg) &&
!parent.equals(arg) &&
!Modifier.isAbstract(arg.getModifiers())) {
found.add(arg);
}
return true;
}
});
return found;
}
public static void main(String[] args) {
Debug.print("searching...");
ClassFinder.findAllSubclasses(ViewParent.class);
}
}