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

io.vanillabp.springboot.utils.ClasspathScanner Maven / Gradle / Ivy

There is a newer version: 1.1.3
Show newest version
package io.vanillabp.springboot.utils;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.util.ClassUtils;
import org.springframework.util.SystemPropertyUtils;

public class ClasspathScanner {

    private static Logger logger = LoggerFactory.getLogger(ClasspathScanner.class);

    private static final Map cache = new HashMap<>();

    private ClasspathScanner() {
        // static class: hide public constructor
    }
    
    private static ResourcePatternResolver getResourcePatternResolver(
    		final ResourceLoader resourceLoader) {
    	if (resourceLoader == null) {
    		return new PathMatchingResourcePatternResolver();
    	} else {
    		return new PathMatchingResourcePatternResolver(resourceLoader);
    	}
    }
    
    @SafeVarargs
    public static List allResources(
    		final Predicate... filters) throws Exception {
        
        return allResources(null, null, filters);
        
    }

    @SafeVarargs
    public static List allResources(
    		final ResourceLoader resourceLoader,
    		final Predicate... filters) throws Exception {
        
        return allResources(resourceLoader, null, filters);
        
    }

    @SafeVarargs
    public static List allResources(
    		final String basePath,
    		final Predicate... filters) throws Exception {
    	
    	return allResources(null, basePath, filters);
    	
    }
    
    @SafeVarargs
    public static List allResources(
    		final ResourceLoader resourceLoader,
    		final String basePath,
    		final Predicate... filters) throws Exception {
        
        final var searchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                + (basePath == null ? "" : basePath)
                + "/**/*";
        
        final Resource[] resources;
        synchronized (cache) {
            final var cachedResources = cache.get(searchPath);
            if (cachedResources != null) {
                resources = cachedResources;
            } else {
                resources = getResourcePatternResolver(resourceLoader).getResources(searchPath);
            }
        }
        
        final List result = new LinkedList<>();
        
        for (final var resource : resources) {
            if (resource.isReadable()) {
                boolean complies = true;
                for (Predicate filter : filters) {
                    if (!filter.test(resource)) {
                        complies = false;
                        break;
                    }
                }
                if (complies) {
                    result.add(resource);
                }
            }
        }
        
        return result;
        
    }

    @SafeVarargs
    public static List> allClasses(
    		final String basePackage,
    		final Predicate... filters) throws Exception {
    	
    	return allClasses(null, basePackage, filters);
    	
    }

    @SafeVarargs
    public static List> allClasses(
    		final ResourceLoader resourceLoader,
    		final String basePackage,
    		final Predicate... filters) throws Exception {

        final var packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage)
            + "/**/*.class";

		final List> classes = new LinkedList<>();
		
		final var resourcePatternResolver = getResourcePatternResolver(null);
	    final var metadataReaderFactory = new CachingMetadataReaderFactory(resourcePatternResolver);

        final Resource[] resources;
        synchronized (cache) {
            final var cachedResources = cache.get(packageSearchPath);
            if (cachedResources != null) {
                resources = cachedResources;
            } else {
                resources = resourcePatternResolver.getResources(packageSearchPath);
            }
        }

		for (Resource resource : resources) {
			if (resource.isReadable()) {
                final var metadataReader = metadataReaderFactory.getMetadataReader(resource);
                boolean complies = true;
                for (Predicate filter : filters) {
                    if (!filter.test(metadataReader)) {
                        complies = false;
                        break;
                    }
                }
                if (complies) {
                    try {
                        Class c = Class.forName(metadataReader.getClassMetadata().getClassName());
                        classes.add(c);
                    } catch (NoClassDefFoundError e) {
                        logger.debug("NoClassDefFoundError: it might be an optional dependency", e);
                    }
                }
			}
		}

		return classes;
		
	}
	
    private static String resolveBasePackage(final String basePackage) {
    	
        return ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage));
    
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy