package org.sky.auto.intrumentation; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.net.URLDecoder; 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 java.util.regex.Pattern; import org.apache.log4j.Logger; public class ClassPathScanHandler { private static Logger logger = Logger.getLogger(ClassPathScanHandler.class); /** * 定义扫描器是否扫描带有内部类的class,默认的不扫描 * */ private boolean excludeInner = true; /** *该参数表示过滤规则适用情况,true—>搜索符合规则的 false->排除符合规则的,默认=true */ private boolean checkInOrEx = true; /** * 自定义过滤规则,如果是null或者空,即全部符合不过滤,默认为null。过滤规则可以自定义为:<br> * Xyz或Xyz*或*Xyz或*Xyz*等类似的格式 * */ private List<String> classFilters = null; public ClassPathScanHandler(){ } public ClassPathScanHandler(boolean excludeInner,boolean checkInOrEx,List<String> classFilters){ this.excludeInner=excludeInner; this.checkInOrEx=checkInOrEx; this.classFilters=classFilters; } /** * * @param basePackage 基础包 * @param recursive 是否递归搜索子包 * @return Set */ public Set<Class<?>>getPackageAllClasses(String basePackage,boolean recursive){ Set<Class<?>> classes=new HashSet<Class<?>>(); String baseName=basePackage; if(baseName.endsWith(".")){ baseName=baseName.substring(0, basePackage.lastIndexOf(".")); } String package2path=baseName.replace(".", "/"); Enumeration<URL> dirs; try{ dirs=Thread.currentThread().getContextClassLoader().getResources(package2path); while(dirs.hasMoreElements()){ URL url = dirs.nextElement(); String protocol = url.getProtocol(); if("file".equals(protocol)){ String filePath = URLDecoder.decode(url.getFile(),"UTF-8"); logger.info("扫描file类型的class文件..."); doScanPackageClassesByFile(classes, baseName, filePath,recursive); }else if("jar".equals(protocol)){ logger.info("扫描jar文件中的类..."); doScanPackageClassesByJAR(baseName, url, recursive, classes); } } }catch(IOException e){ logger.error("IOException error:", e); } return classes; } /** * 以jar的方式扫描包下的所有Class文件<br> * @param basePackage eg:org.sky. * @param url * * @param recursive * @param classes */ private void doScanPackageClassesByJAR(String baseName, URL url, boolean recursive, Set<Class<?>> classes) { String packageName=baseName; String package2Path = packageName.replace(".", "/"); JarFile jar; try{ jar=((JarURLConnection)url.openConnection()).getJarFile(); Enumeration<JarEntry> enties = jar.entries(); while(enties.hasMoreElements()){ JarEntry je = enties.nextElement(); String name =je.getName(); if(!name.startsWith(package2Path)||je.isDirectory()){ continue; } if(!recursive&&name.lastIndexOf("/")!=package2Path.length()){ continue; } String classSimpleName = name.substring(name.lastIndexOf('/') + 1); if(this.fiterClassName(classSimpleName)){ String className = name.replace("/", "."); className = className.substring(0, className.length()-6); try{ classes.add(Thread.currentThread().getContextClassLoader().loadClass(className)); logger.info("className:"+className); }catch(ClassNotFoundException e){ logger.error("Class.forName Error:"+e); } } } }catch(IOException e){ logger.error("IOException error:"+e); } } private boolean fiterClassName(String classSimpleName) { // TODO Auto-generated method stub return false; } /** 以文件的方式扫描包下的所有Class文件 * @param classes * @param baseName * @param filePath * @param recursive * */ private void doScanPackageClassesByFile(Set<Class<?>> classes, String baseName, String filePath, boolean recursive) { File dir = new File(filePath); if(!dir.exists()||!dir.isDirectory()){ return; } final boolean fileRecursive=recursive; File[] dirlist = dir.listFiles(new FileFilter() { @Override public boolean accept(File file) { if (file.isDirectory()) { return fileRecursive; } String filename = file.getName(); if (excludeInner && filename.indexOf('$') != -1) { // logger.info("exclude inner class with name:" + filename); return false; } return filterClassName(filename); } }); for(File file:dirlist){ if(file.isDirectory()){ doScanPackageClassesByFile(classes, baseName+"."+file.getName(),file.getAbsolutePath(), recursive); }else{ String className = file.getName().substring(0, file.getName().length()-6); try{ classes.add(Thread.currentThread().getContextClassLoader().loadClass(baseName+"."+className)); }catch(ClassNotFoundException e){ logger.error("Class.forName ERROR:"+e); } } } } /** * 根据过滤规则判断类名 * @param className * @return */ private boolean filterClassName(String className) { if (!className.endsWith(".class")) { return false; } if (null == this.classFilters || this.classFilters.isEmpty()) { return true; } String tmpName = className.substring(0, className.length() - 6); boolean flag = false; for (String str : classFilters) { String tmpreg = "^" + str.replace("*", ".*") + "$"; Pattern p = Pattern.compile(tmpreg); if (p.matcher(tmpName).find()) { flag = true; break; } } return (checkInOrEx && flag) || (!checkInOrEx && !flag); } public boolean isExcludeInner() { return excludeInner; } public void setExcludeInner(boolean excludeInner) { this.excludeInner = excludeInner; } public boolean isCheckInOrEx() { return checkInOrEx; } public void setCheckInOrEx(boolean checkInOrEx) { this.checkInOrEx = checkInOrEx; } public List<String> getClassFilters() { return classFilters; } public void setClassFilters(List<String> classFilters) { this.classFilters = classFilters; } // public static void main(String[] args) { // ClassPathScanHandler cps = new ClassPathScanHandler(true, true, null); // Set<Class<?>>cls = cps.getPackageAllClasses("org.sky.", true); // for(Class<?>clazz:cls){ // System.out.println(clazz.getName()); // } // } }