package ren.yale.java.tools; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; public abstract class PackageScanner { private static final String FILE_PROTOCL = "file"; private static final String JAR_PROTOCL = "jar"; private static final String CLASS_SUFFIX = ".class"; public List<Class<?>> scan(String packagename) throws IOException, ClassNotFoundException { if (!StringUtils.isEmpty(packagename)) { Enumeration<URL> urls = Thread.currentThread().getContextClassLoader() .getResources(packagename.replaceAll("\\.", "/")); List<Class<?>> classList = new ArrayList<Class<?>>(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); String protocl = url.getProtocol(); if (FILE_PROTOCL.equals(protocl)) { String packagePath = url.getPath().replaceAll("%20", " "); addClass(classList, packagePath, packagename); } else if (JAR_PROTOCL.equals(protocl)) { JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection(); JarFile jarFile = jarURLConnection.getJarFile(); Enumeration<JarEntry> jarEntrys = jarFile.entries(); while (jarEntrys.hasMoreElements()) { JarEntry jarEntry = jarEntrys.nextElement(); String jarEntryName = jarEntry.getName(); if (jarEntryName.equals(CLASS_SUFFIX)) { String className = jarEntryName.substring(0, jarEntryName.indexOf(".")).replaceAll("/", "."); Class<?> cls = Class.forName(className, true, Thread.currentThread().getContextClassLoader()); if (checkAdd(cls)) { classList.add(cls); } } } } } return classList; } return null; } private void addClass(List<Class<?>> classList, String packagePath, String packageName) throws ClassNotFoundException { File[] files = new File(packagePath).listFiles(new FileFilter() { public boolean accept(File file) { return (file.isFile() && file.getName().endsWith(CLASS_SUFFIX)) || file.isDirectory(); } }); for (File file : files) { String fileName = file.getName(); if (file.isFile()) { //get class name String className = fileName.substring(0, fileName.lastIndexOf(".")); if (!StringUtils.isEmpty(packageName)) { className = packageName + "." + className; } Class<?> cls = Class.forName(className, true, Thread.currentThread().getContextClassLoader()); //judge whether class to loader if (checkAdd(cls)) { classList.add(cls); } } else { String currentPackagePath = fileName; if (!StringUtils.isEmpty(packagePath)) { currentPackagePath = packagePath + "/" + currentPackagePath; } String currentPackageName = fileName; if (!StringUtils.isEmpty(packageName)) { currentPackageName = packageName + "." + currentPackageName; } addClass(classList, currentPackagePath, currentPackageName); } } } public abstract boolean checkAdd(Class<?> clzz); }