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

com.github.linushp.commons.scan.ClasspathPackageScanner Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
package com.github.linushp.commons.scan;


import com.github.linushp.commons.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

public class ClasspathPackageScanner implements PackageScanner {
    private Logger logger = LoggerFactory.getLogger(ClasspathPackageScanner.class);
    private String basePackage;
    private ClassLoader classLoader;

    /**
     * 初始化
     *
     * @param basePackage
     */
    public ClasspathPackageScanner(String basePackage) {
        this.basePackage = basePackage;
        this.classLoader = getClass().getClassLoader();
    }

    public ClasspathPackageScanner(String basePackage, ClassLoader classLoader) {
        this.basePackage = basePackage;
        this.classLoader = classLoader;
    }

    /**
     * 获取指定包下的所有字节码文件的全类名
     */
    public List getFullyQualifiedClassNameList() throws IOException {
        logger.info("开始扫描包{}下的所有类", basePackage);
        return doScan(basePackage, new ArrayList());
    }

    /**
     * doScan函数
     *
     * @param basePackage
     * @param nameList
     * @return
     * @throws IOException
     */
    private List doScan(String basePackage, List nameList) throws IOException {
        String splashPath = StringUtils.dotToSplash(basePackage);
        URL url = classLoader.getResource(splashPath);   //file:/D:/WorkSpace/java/ScanTest/target/classes/com/scan
        String filePath = StringUtils.getRootPath(url);
        List names = null; // contains the name of the class file. e.g., Apple.class will be stored as "Apple"


        if (isJarFile(filePath)) {// 先判断是否是jar包,如果是jar包,通过JarInputStream产生的JarEntity去递归查询所有类
            if (logger.isDebugEnabled()) {
                logger.debug("{} 是一个JAR包", filePath);
            }

            names = readFromJarFile(filePath, splashPath);
            names = toFullyQualifiedName(names, null);
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("{} 是一个目录", filePath);
            }
            names = readFromDirectory(filePath);
            names = toFullyQualifiedName(names, basePackage);
        }


        nameList.addAll(names);

        if (logger.isDebugEnabled()) {
            for (String n : nameList) {
                logger.debug("找到{}", n);
            }
        }
        return nameList;
    }

    private List toFullyQualifiedName(List shortName, String basePackage) {

        List result = new ArrayList<>();

        for (String s : shortName) {

            String name;
            if (!StringUtils.isEmpty(basePackage)) {
                name = basePackage + "." + s;
            } else {
                name = s;
            }
            name = StringUtils.trimExtension(name);
            name = StringUtils.splashToDot(name);

            result.add(name);
        }

        return result;

    }

    private List readFromJarFile(String jarPath, String splashedPackageName) throws IOException {
        if (logger.isDebugEnabled()) {
            logger.debug("从JAR包中读取类: {}", jarPath);
        }
        JarInputStream jarIn = new JarInputStream(new FileInputStream(jarPath));
        JarEntry entry = jarIn.getNextJarEntry();
        List nameList = new ArrayList();
        while (null != entry) {
            String name = entry.getName();
            if (name.startsWith(splashedPackageName) && isClassFile(name)) {
                nameList.add(name);
            }
            entry = jarIn.getNextJarEntry();
        }

        return nameList;
    }

    private List readFromDirectory(String path) {

        int prefixLength = path.length();

        File file = new File(path);

        List fileList = listFileOfDirectory(file);


        List fileNames = new ArrayList<>();
        for (File file1 : fileList) {
            String path1 = file1.getAbsolutePath();
            String pathShort = path1.substring(prefixLength + 1);
            fileNames.add(pathShort);
        }

        return fileNames;
    }

    private List listFileOfDirectory(File file) {

        if (file.isDirectory()) {
            List result = new ArrayList<>();
            File[] files = file.listFiles();
            for (File file1 : files) {

                if (file1.isDirectory()) {

                    List file1List = listFileOfDirectory(file1);
                    if (file1List != null && !file1List.isEmpty()) {
                        result.addAll(file1List);
                    }

                } else {
                    result.add(file1);
                }

            }

            return result;
        }

        return new ArrayList<>();
    }


    private boolean isClassFile(String name) {
        return name.endsWith(".class");
    }

    private boolean isJarFile(String name) {
        return name.endsWith(".jar");
    }

//    /**
//     * For test purpose.
//     */
//    public static void main(String[] args) throws Exception {
//        PackageScanner scan = new ClasspathPackageScanner("com.scan");
//        scan.getFullyQualifiedClassNameList();
//    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy