com.googlecode.gwt.test.internal.ClassesScanner Maven / Gradle / Ivy
package com.googlecode.gwt.test.internal;
import com.googlecode.gwt.test.exceptions.GwtTestPatchException;
import javassist.CtClass;
import javassist.NotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* The class used to scan and filter classes. For internal use only.
*
* @author Gael Lazzari
*/
final class ClassesScanner {
static interface ClassVisitor {
void visit(CtClass ctClass);
}
private static final ClassesScanner INSTANCE = new ClassesScanner();
private static Logger logger = LoggerFactory.getLogger(ClassesScanner.class);
public static ClassesScanner getInstance() {
return INSTANCE;
}
private ClassesScanner() {
}
public void scanPackages(ClassVisitor classVisitor, Set rootPackages) {
for (String rootPackage : rootPackages) {
String path = rootPackage.replaceAll("\\.", "/");
logger.debug("Scan package " + rootPackage);
if (rootPackage.endsWith(".")) {
rootPackage = rootPackage.substring(0, rootPackage.length() - 1);
}
try {
Enumeration l = Thread.currentThread().getContextClassLoader().getResources(path);
while (l.hasMoreElements()) {
URL url = l.nextElement();
String u = url.toExternalForm();
if (u.startsWith("file:")) {
String directoryName = u.substring("file:".length());
directoryName = URLDecoder.decode(directoryName, "UTF-8");
scanClassesFromDirectory(new File(directoryName), rootPackage, classVisitor);
} else if (u.startsWith("jar:file:")) {
scanClassesFromJarFile(u.substring("jar:file:".length()), path, classVisitor);
} else {
throw new IllegalArgumentException("Not managed class container " + u);
}
}
} catch (Exception e) {
throw new GwtTestPatchException("Error while scanning package '" + rootPackage + "'", e);
}
}
}
private void scanClassesFromDirectory(File directoryToScan, String scanPackage,
ClassVisitor classVisitor) {
logger.debug("Scan directory " + directoryToScan);
for (File f : directoryToScan.listFiles()) {
if (f.isDirectory()) {
if (!".".equals(f.getName()) && !"..".equals(f.getName())) {
scanClassesFromDirectory(f, scanPackage + "." + f.getName(), classVisitor);
}
} else if (f.getName().endsWith(".class")) {
visitClass(scanPackage + "." + f.getName(), classVisitor);
}
}
logger.debug("Directory scanned " + directoryToScan);
}
private void scanClassesFromJarFile(String path, String scanPackage, ClassVisitor classVisitor)
throws Exception {
String prefix = path.substring(path.indexOf("!") + 2);
String jarName = path.substring(0, path.indexOf("!"));
jarName = URLDecoder.decode(jarName, "UTF-8");
logger.debug("Load classes from jar " + jarName);
JarFile jar = new JarFile(jarName);
Enumeration entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.getName().startsWith(prefix) && entry.getName().endsWith(".class")) {
visitClass(entry.getName().replaceAll("\\/", "."), classVisitor);
}
}
logger.debug("Classes loaded from jar " + jarName);
}
private void visitClass(String classFileName, ClassVisitor classVisitor) {
try {
CtClass current = GwtClassPool.getClass(classFileName.substring(0, classFileName.length()
- ".class".length()));
classVisitor.visit(current);
for (CtClass innerClass : current.getNestedClasses()) {
classVisitor.visit(innerClass);
}
} catch (NotFoundException e) {
// do nothing
}
}
}