package org.fastcatsearch.util; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class ClassScanner<E> { private static final Logger logger = LoggerFactory.getLogger(ClassScanner.class); public List<E> scanClass(String packageName, Object param) throws IOException { List<E> ret = new ArrayList<E>(); if(packageName==null || "".equals(packageName)) { packageName=""; } String pathStr = ""; pathStr = packageName.replace(".", "/"); if (!pathStr.endsWith("/")) { pathStr = pathStr + "/"; } String[] pathArray = pathStr.split(","); for(String path : pathArray) { Enumeration<URL> classEnumeration = null; logger.trace("find class from {}", path); classEnumeration = DynamicClassLoader.getResources(path); while(classEnumeration.hasMoreElements()) { String urlString = classEnumeration.nextElement().toString(); logger.trace("find class url > {}", urlString); if(urlString.startsWith("jar:file:")) { String jpath = urlString.substring(9); int st = jpath.indexOf("!/"); String jarPath = jpath.substring(0, st); String entryPath = jpath.substring(st + 2); logger.trace("jarPath > {}, {}", jarPath, entryPath); JarFile jarFile = new JarFile(jarPath); try { Enumeration<JarEntry>jee = jarFile.entries(); while(jee.hasMoreElements()) { JarEntry jarEntry = jee.nextElement(); String className = jarEntry.getName(); logger.trace("jar entry > {}, {}", className, entryPath); if (className.startsWith(entryPath)) { if(className.endsWith(".class")) { className = className.substring(0,className.length() - 6); className = className.replaceAll("/", "."); //in-a class 는 인정하지 않는다. if(!className.contains("$")) { E args = done(className, packageName, param); if(args!=null && !ret.contains(args)) { ret.add(args); } } } } } } finally{ jarFile.close(); } } else if(urlString.startsWith("file:")) { String rootPath = urlString.substring(5); int prefixLength = rootPath.indexOf(path); File baseFile = new File(rootPath); Set<File> fileSet = new HashSet<File>(); if (baseFile.isDirectory()) { addDirectory(fileSet, baseFile); } else { fileSet.add(baseFile); } for (File file : fileSet) { String classPath = file.toURI().toURL().toString() .substring(5).substring(prefixLength); if(classPath.endsWith(".class")) { classPath = classPath.substring(0,classPath.length() - 6); classPath = classPath.replaceAll("/", "."); //in-a class 는 인정하지 않는다. if(!classPath.contains("$")) { E args = done(classPath, packageName, param); if(args!=null && !ret.contains(args)) { ret.add(args); } } } } } } } return ret; } private void addDirectory(Set<File> set, File d){ File[] files = d.listFiles(); for (int i = 0; i < files.length; i++) { if(files[i].isDirectory()){ addDirectory(set, files[i]); }else{ set.add(files[i]); } } } protected abstract E done(String className, String packageName, Object param); }