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

com.neko233.config233.utils.PackageScannerForConfig233 Maven / Gradle / Ivy

There is a newer version: 0.1.8
Show newest version
package com.neko233.config233.utils;


import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;

public final class PackageScannerForConfig233 {
    private PackageScannerForConfig233() {
    }

    public static Set> scanClass(String packageName, boolean recursive, Class parentClass) {
        if (parentClass == null) {
            return Collections.emptySet();
        } else {
            parentClass.getClass();
            return scanClass(packageName, recursive, parentClass::isAssignableFrom);
        }
    }

    public static Set> scanClassRecursive(String packageName, Class parentClass) {
        return scanClass(packageName, true, parentClass);
    }

    public static Set> scanClass(String packageName, boolean recursive) {
        return scanClass(packageName, recursive, (clazz) -> {
            return true;
        });
    }

    public static Set> scanClass(Class appClass) {
        return scanClass(appClass.getPackage().getName(), true, (clazz) -> {
            return true;
        });
    }

    public static Set> scanClass(Class appClass, boolean recursive, ClassFilterApi filter) {
        return scanClass(appClass.getPackage().getName(), recursive, filter);
    }

    /**
     * 扫描包中的类
     *
     * @param packageName 包名
     * @param recursive   是否递归扫描子目录
     * @param filter      过滤器
     * @return 类集合
     */
    public static Set> scanClass(String packageName, boolean recursive, ClassFilterApi filter) {
        Set> resultSet = new HashSet<>();

        if (packageName == null || packageName.isEmpty()) {
            return resultSet;
        }
        String packagePath = packageName.replace('.', '/');
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        try {
            Enumeration urls = classLoader.getResources(packagePath);
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                String protocol = url.getProtocol();
                if ("file".equalsIgnoreCase(protocol)) {
                    // 扫描文件目录中的类
                    String filePath = URLDecoder.decode(url.getFile(), StandardCharsets.UTF_8.toString());
                    scanClassFromDir(resultSet, filePath, packageName, recursive, filter);
                } else if ("jar".equalsIgnoreCase(protocol)) {
                    // 扫描 JAR 文件中的类
                    scanClassFromJar(resultSet, url, packageName, recursive, filter);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return resultSet;
    }

    /**
     * 从文件目录中扫描类
     *
     * @param resultSet   结果集
     * @param filePath    文件路径
     * @param packageName 包名
     * @param recursive   是否递归扫描子目录
     * @param filter      过滤器
     */
    private static void scanClassFromDir(Set> resultSet, String filePath, String packageName, boolean recursive, ClassFilterApi filter) {
        File dir = new File(filePath);
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }

        File[] files = dir.listFiles(file -> file.isDirectory() || file.getName().endsWith(".class"));
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory() && recursive) {
                    // 递归扫描子目录
                    scanClassFromDir(resultSet, file.getAbsolutePath(), packageName + "." + file.getName(), recursive, filter);
                } else if (file.getName().endsWith(".class")) {
                    // 加载类
                    String className = packageName + '.' + file.getName().substring(0, file.getName().length() - 6);
                    addClass(resultSet, className, filter);
                }
            }
        }
    }

    /**
     * 从 JAR 文件中扫描类
     *
     * @param resultSet   结果集
     * @param url         JAR 文件 URL
     * @param packageName 包名
     * @param recursive   是否递归扫描子目录
     * @param filter      过滤器
     */
    private static void scanClassFromJar(Set> resultSet, URL url, String packageName, boolean recursive, ClassFilterApi filter) {
        try {
            // 打开 Jar 文件连接
            JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
            JarFile jarFile = jarURLConnection.getJarFile();
            Enumeration entries = jarFile.entries();

            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                String name = entry.getName();
                if (name.startsWith(packageName.replace('.', '/'))) {
                    // 匹配包名
                    int idx = name.lastIndexOf('/');
                    if ((idx != -1 || recursive) && name.endsWith(".class") && !entry.isDirectory()) {
                        // 匹配类名-去掉 .class 后缀
                        String className = name.substring(0, name.length() - 6).replace('/', '.');
                        addClass(resultSet, className, filter);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加类
     *
     * @param resultSet 结果集
     * @param className 类名称
     * @param filter    过滤器
     */
    private static void addClass(Set> resultSet, String className, ClassFilterApi filter) {
        try {
            Class clazz = Class.forName(className);
            if (filter == null || filter.isNeed(clazz)) {
                resultSet.add(clazz);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    public static Set> scanClassWithJar(String packageName, boolean recursive, ClassFilterApi filter) {
        if (packageName != null && !packageName.isEmpty()) {
            String packagePath = packageName.replace('.', '/');
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            Set> resultSet = new HashSet();

            try {
                Enumeration urlEnum = cl.getResources(packagePath);

                while (urlEnum.hasMoreElements()) {
                    URL currUrl = (URL) urlEnum.nextElement();
                    String protocol = currUrl.getProtocol();
                    Set> tmpSet = null;
                    if ("FILE".equalsIgnoreCase(protocol)) {
                        tmpSet = scanClassFromDir(new File(currUrl.getFile()), packageName, recursive, filter);
                    } else if ("JAR".equalsIgnoreCase(protocol)) {
                        String fileStr = currUrl.getFile();
                        if (fileStr.startsWith("file:")) {
                            fileStr = fileStr.substring(5);
                        }

                        if (fileStr.lastIndexOf(33) > 0) {
                            fileStr = fileStr.substring(0, fileStr.lastIndexOf(33));
                        }

                        tmpSet = scanClassFromJar(new File(fileStr), packageName, recursive, filter);
                    }

                    if (tmpSet != null) {
                        resultSet.addAll(tmpSet);
                    }
                }

                return resultSet;
            } catch (Exception var11) {
                throw new RuntimeException(var11);
            }
        } else {
            return null;
        }
    }

    public static Set> scanClassFromDir(File dirFile, String packageName, boolean recursive, ClassFilterApi filter) {
        if (dirFile.exists() && dirFile.isDirectory()) {
            File[] subFileArr = dirFile.listFiles();
            if (subFileArr != null && subFileArr.length > 0) {
                Queue fileQ = new LinkedList(Arrays.asList(subFileArr));
                Set> resultSet = new HashSet();

                while (true) {
                    while (!fileQ.isEmpty()) {
                        File currFile = (File) fileQ.poll();
                        if (currFile.isDirectory() && recursive) {
                            subFileArr = currFile.listFiles();
                            if (subFileArr != null && subFileArr.length > 0) {
                                fileQ.addAll(Arrays.asList(subFileArr));
                            }
                        } else if (currFile.isFile() && currFile.getName().endsWith(".class")) {
                            String clazzName = currFile.getAbsolutePath();
                            clazzName = clazzName.substring(dirFile.getAbsolutePath().length(), clazzName.lastIndexOf(46));
                            clazzName = clazzName.replace('\\', '/');
                            clazzName = trimLeft(clazzName, "/");
                            clazzName = join(clazzName.split("/"), ".");
                            clazzName = packageName + "." + clazzName;

                            try {
                                Class clazzObj = Class.forName(clazzName);
                                if (null == filter || !filter.isNotNeed(clazzObj)) {
                                    resultSet.add(clazzObj);
                                }
                            } catch (Exception var10) {
                                throw new RuntimeException(var10);
                            }
                        }
                    }

                    return resultSet;
                }
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    private static Set> scanClassFromJar(File jarFilePath, String packageName, boolean recursive, ClassFilterApi filter) {
        if (jarFilePath != null && !jarFilePath.isDirectory()) {
            Set> resultSet = new HashSet();

            try {
                JarInputStream jarIn = new JarInputStream(Files.newInputStream(jarFilePath.toPath()));

                while (true) {
                    Class clazzObj;
                    do {
                        String entryName;
                        String tmpStr;
                        do {
                            do {
                                JarEntry entry;
                                do {
                                    if ((entry = jarIn.getNextJarEntry()) == null) {
                                        jarIn.close();
                                        return resultSet;
                                    }
                                } while (entry.isDirectory());

                                entryName = entry.getName();
                            } while (!entryName.endsWith(".class"));

                            if (recursive) {
                                break;
                            }

                            tmpStr = entryName.substring(0, entryName.lastIndexOf(47));
                            tmpStr = join(tmpStr.split("/"), ".");
                        } while (!packageName.equals(tmpStr));

                        tmpStr = entryName.substring(0, entryName.lastIndexOf(46));
                        tmpStr = join(tmpStr.split("/"), ".");
                        clazzObj = Class.forName(tmpStr);
                    } while (null != filter && !filter.isNeed(clazzObj));

                    resultSet.add(clazzObj);
                }
            } catch (Exception var10) {
                throw new RuntimeException(var10);
            }
        } else {
            return null;
        }
    }

    private static String join(String[] strArr, String joiner) {
        if (null != strArr && strArr.length > 0) {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < strArr.length; ++i) {
                if (i > 0) {
                    sb.append(joiner);
                }

                sb.append(strArr[i]);
            }

            return sb.toString();
        } else {
            return "";
        }
    }

    private static String trimLeft(String src, String trimStr) {
        if (null != src && !src.isEmpty()) {
            if (null != trimStr && !trimStr.isEmpty()) {
                if (src.equals(trimStr)) {
                    return "";
                } else {
                    while (src.startsWith(trimStr)) {
                        src = src.substring(trimStr.length());
                    }

                    return src;
                }
            } else {
                return src;
            }
        } else {
            return "";
        }
    }

    @FunctionalInterface
    public interface ClassFilterApi {
        boolean isNeed(Class var1);

        default boolean isNotNeed(Class clazz) {
            return !this.isNeed(clazz);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy