package com.sf.ddao.chain;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
/**
* derived from Morphia's ReflectionUtils @see http://code.google.com/p/morphia/source/browse/trunk/morphia/src/main/java/com/google/code/morphia/utils/ReflectionUtils.java
*/
public class PackageScanner {
private static String stripFilenameExtension(final String filename) {
if (filename.indexOf('.') != -1) {
return filename.substring(0, filename.lastIndexOf('.'));
} else {
return filename;
}
}
public static void getFromDirectory(final File directory, final String packageName, final Set<Class<?>> classes)
throws ClassNotFoundException {
if (directory.exists()) {
for (String file : directory.list()) {
if (file.endsWith(".class")) {
String name = packageName + '.' + stripFilenameExtension(file);
Class<?> clazz = Class.forName(name);
classes.add(clazz);
}
}
}
}
public static void getFromJARFile(final String jar, final String packageName, final Set<Class<?>> classes) throws IOException,
ClassNotFoundException {
JarInputStream jarFile = new JarInputStream(new FileInputStream(jar));
JarEntry jarEntry;
do {
jarEntry = jarFile.getNextJarEntry();
if (jarEntry != null) {
String className = jarEntry.getName();
if (className.endsWith(".class")) {
className = stripFilenameExtension(className);
if (className.startsWith(packageName)) {
classes.add(Class.forName(className.replace('/', '.')));
}
}
}
} while (jarEntry != null);
}
public static void getClasses(final ClassLoader loader, final String packageName, final Set<Class<?>> classes) throws IOException,
ClassNotFoundException {
String path = packageName.replace('.', '/');
Enumeration<URL> resources = loader.getResources(path);
if (resources != null) {
while (resources.hasMoreElements()) {
String filePath = resources.nextElement().getFile();
// WINDOWS HACK
if (filePath.indexOf("%20") > 0)
filePath = filePath.replaceAll("%20", " ");
// # in the jar name
if (filePath.indexOf("%23") > 0)
filePath = filePath.replaceAll("%23", "#");
if (filePath != null) {
if ((filePath.indexOf("!") > 0) & (filePath.indexOf(".jar") > 0)) {
String jarPath = filePath.substring(0, filePath.indexOf("!")).substring(
filePath.indexOf(":") + 1);
// WINDOWS HACK
if (jarPath.contains(":")) {
jarPath = jarPath.substring(1);
}
getFromJARFile(jarPath, path, classes);
} else {
getFromDirectory(new File(filePath), packageName, classes);
}
}
}
}
}
public static Set<Class<?>> getClasses(final Class<?>[] sampleClassList) throws ClassNotFoundException, IOException {
Map<String, ClassLoader> packageClassLoaders = new HashMap<String, ClassLoader>();
for (Class<?> aClass : sampleClassList) {
final String name = aClass.getPackage().getName();
packageClassLoaders.put(name, aClass.getClassLoader());
}
Set<Class<?>> classes = new HashSet<Class<?>>();
for (Map.Entry<String, ClassLoader> entry : packageClassLoaders.entrySet()) {
getClasses(entry.getValue(),entry.getKey(),classes);
}
return classes;
}
}