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

com.github.yoojia.next.utils.ClassFinder Maven / Gradle / Ivy

package com.github.yoojia.next.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;

/**
 * @author YOOJIA.CHEN ([email protected])
 */
public final class ClassFinder {

    private final Logger mLogger = LoggerFactory.getLogger(ClassFinder.class);

    private final ArrayList mClasses = new ArrayList<>();

    public enum ConsumeResult {
        CONSUMED, SKIP
    }

    public interface Visitor {
        ConsumeResult visit(String className) throws Exception;
    }

    public interface PrepareHandler {
        void prepare(String root, T module, Class hostType, Method method);
    }

    public void start(){
        mClasses.clear();
        final long scanTime = System.nanoTime();
        final URL url = this.getClass().getResource("/");
        // 1. 当前项目下的类文件
        try {
            final Path base = Paths.get(url.toURI());
            mLogger.debug("Searching path: {}", base);
            final FileVisitor visitor = new SimpleFileVisitor() {
                @Override
                public FileVisitResult visitFile(Path path, BasicFileAttributes attr) throws IOException {
                    final Path clazz = base.relativize(path);
                    final String name = clazz.toString();
                    if (name.endsWith(".class")){
                        mClasses.add(resolveName(name));
                    }
                    return FileVisitResult.CONTINUE;
                }
            };
            Files.walkFileTree(base, visitor);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // 2. TODO 扫描 Jar 文件内的 class 文件
        TimeAnalysis.log(scanTime, "Scan classes:" + mClasses.size());
    }

    public void walkClasses(Visitor visitor){
        if(mClasses == null) {
            throw new IllegalStateException("Cannot walk classes after scanner closed!");
        }
        final int max = mClasses.size() - 1;
        final List deleteRef = new ArrayList<>();
        try{
            for (int i = 0;i <= max; ++i){
                final String item = mClasses.get(i);
                if (ConsumeResult.CONSUMED.equals(visitor.visit(item))){
                    deleteRef.add(item);
                }
            }
        }catch (Throwable e){
            throw new RuntimeException(e);
        }
        mClasses.removeAll(deleteRef);
    }

    public void clean(){
        mClasses.clear();
    }

    private static String resolveName(String name){
        // Not String.replace, String.replace/replaceAll use regex objects
        // Here use a simple way: fast and low memory
        final List segments = URIs.fastParse(name, File.separator.charAt(0), false);
        final StringBuilder ret = new StringBuilder();
        for (String seg : segments) {
            if(seg.contains(".class")){
                ret.append(seg.substring(0, seg.length() - 6)/* 6: .class */);
            }else{
                ret.append(seg).append('.');
            }
        }
        return ret.toString();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy