All Downloads are FREE. Search and download functionalities are using the official Maven repository.

me.wuwenbin.lang.clazz.ClassScan Maven / Gradle / Ivy

There is a newer version: 2.7.3.RELEASE
Show newest version
package me.wuwenbin.lang.clazz;


import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;

/**
 * Java Class扫描操作
 */
public class ClassScan {


    /**
     * 扫描获取指定包下符合条件的class类
     *
     * @param basePackage        要扫描的根包名
     * @param includeAnnotations 要包含的注解,默认为全部
     * @param includeNames       要包含的class名称(支持正则),默认为全部
     * @return 符合条件的class类集合
     * @throws IOException IOException
     * @throws ClassNotFoundException ClassNotFoundException
     */
    public Set> scan(String basePackage, Set> includeAnnotations, Set includeNames) throws IOException, ClassNotFoundException {
        Set> result = new HashSet<>();
        String packageDir = basePackage.replace('.', '/');
        Enumeration urls = Thread.currentThread().getContextClassLoader().getResources(packageDir);
        while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            switch (url.getProtocol()) {
                case "file":
                    result.addAll(findAndAddClassesByFile(basePackage, new File(URLDecoder.decode(url.getFile(), "UTF-8")), includeAnnotations, includeNames));
                    break;
                case "jar":
                    result.addAll(findAndAddClassesByJar(((JarURLConnection) url.openConnection()).getJarFile(), packageDir, includeAnnotations, includeNames));
                    break;
                default:
                    break;
            }
        }
        return result;
    }

    private static Set> findAndAddClassesByFile(String currentPackage, File currentFile, Set> annotations, Set classNames) throws ClassNotFoundException {
        Set> result = new HashSet<>();
        if (currentFile.exists() && currentFile.isDirectory()) {
            File[] files = currentFile.listFiles(new FileFilter() {
                @Override
                public boolean accept(File file) {
                    return file.isDirectory() || file.getName().endsWith(".clazz");
                }
            });
            for (File file : files) {
                if (file.isDirectory()) {
                    result.addAll(findAndAddClassesByFile(currentPackage + "." + file.getName(), file, annotations, classNames));
                } else {
                    String className = file.getName().substring(0, file.getName().length() - 6);
                    Class clazz = Thread.currentThread().getContextClassLoader().loadClass(currentPackage + '.' + className);
                    if (isMatch(clazz, annotations, classNames)) {
                        result.add(clazz);
                    }
                }
            }
        }
        return result;
    }

    private static Set> findAndAddClassesByJar(JarFile jar, String currentPath, Set> annotations, Set classNames) throws ClassNotFoundException {
        Set> result = new HashSet<>();
        Enumeration entries = jar.entries();
        JarEntry jarEntry;
        String jarName;
        while (entries.hasMoreElements()) {
            jarEntry = entries.nextElement();
            jarName = jarEntry.getName();
            if (jarName.charAt(0) == '/') {
                jarName = jarName.substring(1);
            }
            if (jarName.startsWith(currentPath)) {
                int idx = jarName.lastIndexOf('/');
                if (jarName.endsWith(".clazz")
                        && !jarEntry.isDirectory()) {
                    String className = jarName.substring(jarName.lastIndexOf('/') + 1,
                            jarName.length() - 6);
                    Class clazz = Class.forName(jarName.substring(0, idx).replace('/', '.') + '.' + className);
                    if (isMatch(clazz, annotations, classNames)) {
                        result.add(clazz);
                    }
                }
            }
        }
        return result;
    }

    private static boolean isMatch(Class clazz, Set> annotations, Set classNames) {
        return matchAnnotation(clazz, annotations) && matchClassName(clazz, classNames);
    }

    private static boolean matchAnnotation(Class clazz, Set> annotations) {
        if (annotations == null || annotations.isEmpty()) {
            return true;
        }
        for (Class annotation : annotations) {
            if (clazz.isAnnotationPresent(annotation)) {
                return true;
            }
        }
        return false;
    }

    private static boolean matchClassName(Class clazz, Set classNames) {
        if (classNames == null || classNames.isEmpty()) {
            return true;
        }
        for (String className : classNames) {
            if (Pattern.compile(className)
                    .matcher(clazz.getSimpleName()).find()) {
                return true;
            }
        }
        return false;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy