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

org.reflections8.Reflections Maven / Gradle / Ivy

There is a newer version: 0.11.7
Show newest version
package org.reflections8;

import static java.lang.String.format;
import static org.reflections8.ReflectionUtils.filter;
import static org.reflections8.ReflectionUtils.forName;
import static org.reflections8.ReflectionUtils.forNames;
import static org.reflections8.ReflectionUtils.withAnnotation;
import static org.reflections8.ReflectionUtils.withAnyParameterAnnotation;
import static org.reflections8.util.Utils.findLogger;
import static org.reflections8.util.Utils.getConstructorsFromDescriptors;
import static org.reflections8.util.Utils.getFieldFromString;
import static org.reflections8.util.Utils.getMembersFromDescriptors;
import static org.reflections8.util.Utils.getMethodsFromDescriptors;
import static org.reflections8.util.Utils.index;
import static org.reflections8.util.Utils.name;
import static org.reflections8.util.Utils.names;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.reflections8.scanners.FieldAnnotationsScanner;
import org.reflections8.scanners.MemberUsageScanner;
import org.reflections8.scanners.MethodAnnotationsScanner;
import org.reflections8.scanners.MethodParameterNamesScanner;
import org.reflections8.scanners.MethodParameterScanner;
import org.reflections8.scanners.ResourcesScanner;
import org.reflections8.scanners.Scanner;
import org.reflections8.scanners.SubTypesScanner;
import org.reflections8.scanners.TypeAnnotationsScanner;
import org.reflections8.serializers.Serializer;
import org.reflections8.serializers.XmlSerializer;
import org.reflections8.util.ClasspathHelper;
import org.reflections8.util.ConfigurationBuilder;
import org.reflections8.util.FilterBuilder;
import org.reflections8.util.HashSetMultimap;
import org.reflections8.util.Joiner;
import org.reflections8.util.ReflectionsIterables;
import org.reflections8.util.SetMultimap;
import org.reflections8.util.Utils;
import org.reflections8.vfs.Vfs;
import org.slf4j.Logger;

/**
 * Reflections one-stop-shop object
 * 

Reflections scans your classpath, indexes the metadata, allows you to query it on runtime and may save and collect that information for many modules within your project. *

Using Reflections you can query your metadata such as: *

    *
  • get all subtypes of some type *
  • get all types/constructors/methods/fields annotated with some annotation, optionally with annotation parameters matching *
  • get all resources matching matching a regular expression *
  • get all methods with specific signature including parameters, parameter annotations and return type *
  • get all methods parameter names *
  • get all fields/methods/constructors usages in code *
*

A typical use of Reflections would be: *

 *      Reflections reflections = new Reflections("my.project.prefix");
 *
 *      Set<Class<? extends SomeType>> subTypes = reflections8.getSubTypesOf(SomeType.class);
 *
 *      Set<Class<?>> annotated = reflections8.getTypesAnnotatedWith(SomeAnnotation.class);
 * 
*

Basically, to use Reflections first instantiate it with one of the constructors, then depending on the scanners, use the convenient query methods: *

 *      Reflections reflections = new Reflections("my.package.prefix");
 *      //or
 *      Reflections reflections = new Reflections(ClasspathHelper.forPackage("my.package.prefix"),
 *            new SubTypesScanner(), new TypesAnnotationScanner(), new FilterBuilder().include(...), ...);
 *
 *       //or using the ConfigurationBuilder
 *       new Reflections(new ConfigurationBuilder()
 *            .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("my.project.prefix")))
 *            .setUrls(ClasspathHelper.forPackage("my.project.prefix"))
 *            .setScanners(new SubTypesScanner(), new TypeAnnotationsScanner().filterResultsBy(optionalFilter), ...));
 * 
* And then query, for example: *
 *       Set<Class<? extends Module>> modules = reflections8.getSubTypesOf(com.google.inject.Module.class);
 *       Set<Class<?>> singletons =             reflections8.getTypesAnnotatedWith(javax.inject.Singleton.class);
 *
 *       Set<String> properties =       reflections8.getResources(Pattern.compile(".*\\.properties"));
 *       Set<Constructor> injectables = reflections8.getConstructorsAnnotatedWith(javax.inject.Inject.class);
 *       Set<Method> deprecateds =      reflections8.getMethodsAnnotatedWith(javax.ws.rs.Path.class);
 *       Set<Field> ids =               reflections8.getFieldsAnnotatedWith(javax.persistence.Id.class);
 *
 *       Set<Method> someMethods =      reflections8.getMethodsMatchParams(long.class, int.class);
 *       Set<Method> voidMethods =      reflections8.getMethodsReturn(void.class);
 *       Set<Method> pathParamMethods = reflections8.getMethodsWithAnyParamAnnotated(PathParam.class);
 *       Set<Method> floatToString =    reflections8.getConverters(Float.class, String.class);
 *       List<String> parameterNames =  reflections8.getMethodsParamNames(Method.class);
 *
 *       Set<Member> fieldUsage =       reflections8.getFieldUsage(Field.class);
 *       Set<Member> methodUsage =      reflections8.getMethodUsage(Method.class);
 *       Set<Member> constructorUsage = reflections8.getConstructorUsage(Constructor.class);
 * 
*

You can use other scanners defined in Reflections as well, such as: SubTypesScanner, TypeAnnotationsScanner (both default), * ResourcesScanner, MethodAnnotationsScanner, ConstructorAnnotationsScanner, FieldAnnotationsScanner, * MethodParameterScanner, MethodParameterNamesScanner, MemberUsageScanner or any custom scanner. *

Use {@link #getStore()} to access and query the store directly *

In order to save the store metadata, use {@link #save(String)} or {@link #save(String, org.reflections8.serializers.Serializer)} * for example with {@link org.reflections8.serializers.XmlSerializer} or {@link org.reflections8.serializers.JavaCodeSerializer} *

In order to collect pre saved metadata and avoid re-scanning, use {@link #collect(String, Predicate, org.reflections8.serializers.Serializer...)}} *

Make sure to scan all the transitively relevant packages. *
for instance, given your class C extends B extends A, and both B and A are located in another package than C, * when only the package of C is scanned - then querying for sub types of A returns nothing (transitive), but querying for sub types of B returns C (direct). * In that case make sure to scan all relevant packages a priori.
*

For Javadoc, source code, and more information about Reflections Library, see http://github.com/ronmamo/reflections/ */ public class Reflections { public static final Optional log = findLogger(Reflections.class); protected final transient Configuration configuration; protected Store store; /** * constructs a Reflections instance and scan according to given {@link org.reflections8.Configuration} *

it is preferred to use {@link org.reflections8.util.ConfigurationBuilder} */ public Reflections(final Configuration configuration) { this.configuration = configuration; store = new Store(configuration); if (configuration.getScanners() != null && !configuration.getScanners().isEmpty()) { //inject to scanners for (Scanner scanner : configuration.getScanners()) { scanner.setConfiguration(configuration); scanner.setStore(store.getOrCreate(index(scanner.getClass()))); } scan(); if (configuration.shouldExpandSuperTypes()) { expandSuperTypes(); } } } /** * a convenient constructor for scanning within a package prefix. *

this actually create a {@link org.reflections8.Configuration} with: *
- urls that contain resources with name {@code prefix} *
- filterInputsBy where name starts with the given {@code prefix} *
- scanners set to the given {@code scanners}, otherwise defaults to {@link org.reflections8.scanners.TypeAnnotationsScanner} and {@link org.reflections8.scanners.SubTypesScanner}. * @param prefix package prefix, to be used with {@link org.reflections8.util.ClasspathHelper#forPackage(String, ClassLoader...)} )} * @param scanners optionally supply scanners, otherwise defaults to {@link org.reflections8.scanners.TypeAnnotationsScanner} and {@link org.reflections8.scanners.SubTypesScanner} */ public Reflections(final String prefix, final Scanner... scanners) { this((Object) prefix, scanners); } /** * a convenient constructor for Reflections, where given {@code Object...} parameter types can be either: *

    *
  • {@link String} - would add urls using {@link org.reflections8.util.ClasspathHelper#forPackage(String, ClassLoader...)} ()}
  • *
  • {@link Class} - would add urls using {@link org.reflections8.util.ClasspathHelper#forClass(Class, ClassLoader...)}
  • *
  • {@link ClassLoader} - would use this classloaders in order to find urls in {@link org.reflections8.util.ClasspathHelper#forPackage(String, ClassLoader...)} and {@link org.reflections8.util.ClasspathHelper#forClass(Class, ClassLoader...)}
  • *
  • {@link org.reflections8.scanners.Scanner} - would use given scanner, overriding the default scanners
  • *
  • {@link java.net.URL} - would add the given url for scanning
  • *
  • {@link Object[]} - would use each element as above
  • *
* * use any parameter type in any order. this constructor uses instanceof on each param and instantiate a {@link org.reflections8.util.ConfigurationBuilder} appropriately. * if you prefer the usual statically typed constructor, don't use this, although it can be very useful. * *

for example: *
     *     new Reflections("my.package", classLoader);
     *     //or
     *     new Reflections("my.package", someScanner, anotherScanner, classLoader);
     *     //or
     *     new Reflections(myUrl, myOtherUrl);
     * 
*/ public Reflections(final Object... params) { this(ConfigurationBuilder.build(params)); } protected Reflections() { configuration = new ConfigurationBuilder(); store = new Store(configuration); } // protected void scan() { if (configuration.getUrls() == null || configuration.getUrls().isEmpty()) { if (log.isPresent()) log.get().warn("given scan urls are empty. set urls in the configuration"); return; } if (log.isPresent() && log.get().isDebugEnabled()) { log.get().debug("going to scan these urls:\n{}", Joiner.on("\n").join(configuration.getUrls())); } long time = System.currentTimeMillis(); int scannedUrls = 0; Optional executorService = configuration.getExecutorService(); List> futures = new ArrayList(); for (final URL url : configuration.getUrls()) { try { if (executorService.isPresent()) { futures.add(executorService.get().submit(new Runnable() { public void run() { if (log.isPresent()) { log.get().debug("[{}] scanning {}", Thread.currentThread().toString(), url); } scan(url); } })); } else { scan(url); } scannedUrls++; } catch (ReflectionsException e) { if (log.isPresent()) { log.get().warn("could not create Vfs.Dir from url. ignoring the exception and continuing", e); } } } //todo use CompletionService if (executorService.isPresent()) { for (Future future : futures) { try { future.get(); } catch (Exception e) { throw new RuntimeException(e); } } } time = System.currentTimeMillis() - time; //gracefully shutdown the parallel scanner executor service. if (executorService.isPresent()) { executorService.get().shutdown(); } if (log.isPresent()) { int keys = 0; int values = 0; for (String index : store.keySet()) { keys += store.get(index).keySet().size(); for (Collection c: store.get(index).values()) { values += c.size(); } } log.get().trace(format("Reflections took %d ms to scan %d urls, producing %d keys and %d values %s", time, scannedUrls, keys, values, executorService.isPresent() && executorService.get() instanceof ThreadPoolExecutor ? format("[using %d cores]", ((ThreadPoolExecutor) executorService.get()).getMaximumPoolSize()) : "")); } } protected void scan(URL url) { Vfs.Dir dir = Vfs.fromURL(url); try { for (final Vfs.File file : dir.getFiles()) { // scan if inputs filter accepts file relative path or fqn Optional> inputsFilter = configuration.getInputsFilter(); String path = file.getRelativePath(); String fqn = path.replace('/', '.'); if (!inputsFilter.isPresent() || inputsFilter.get().test(path) || inputsFilter.get().test(fqn)) { Optional classObject = Optional.empty(); for (Scanner scanner : configuration.getScanners()) { try { if (scanner.acceptsInput(path) || scanner.acceptsInput(fqn)) { classObject = Optional.of(scanner.scan(file, classObject)); } } catch (Exception e) { if (log.isPresent()) { // SLF4J will filter out Throwables from the format string arguments. log.get().debug("could not scan file {} in url {} with scanner {}", file.getRelativePath(), url.toExternalForm(), scanner.getClass().getSimpleName(), e); } } } } } } finally { dir.close(); } } /** collect saved Reflection xml resources and merge it into a Reflections instance *

by default, resources are collected from all urls that contains the package META-INF/reflections * and includes files matching the pattern .*-reflections.xml * */ public static Reflections collect() { return collect("META-INF/reflections/", new FilterBuilder().include(".*-reflections.xml")); } /** * collect saved Reflections resources from all urls that contains the given packagePrefix and matches the given resourceNameFilter * and de-serializes them using the default serializer {@link org.reflections8.serializers.XmlSerializer} or using the optionally supplied optionalSerializer *

* it is preferred to use a designated resource prefix (for example META-INF/reflections but not just META-INF), * so that relevant urls could be found much faster * @param optionalSerializer - optionally supply one serializer instance. if not specified or null, {@link org.reflections8.serializers.XmlSerializer} will be used */ public static Reflections collect(final String packagePrefix, final Predicate resourceNameFilter, Serializer... optionalSerializer) { Serializer serializer = optionalSerializer != null && optionalSerializer.length == 1 ? optionalSerializer[0] : new XmlSerializer(); Collection urls = ClasspathHelper.forPackage(packagePrefix); if (urls.isEmpty()) return null; long start = System.currentTimeMillis(); final Reflections reflections8 = new Reflections(); Iterable files = Vfs.findFiles(urls, packagePrefix, resourceNameFilter); for (final Vfs.File file : files) { try { try(InputStream inputStream = file.openInputStream()) { reflections8.merge(serializer.read(inputStream)); } } catch (IOException e) { throw new ReflectionsException("could not merge " + file, e); } } if (log.isPresent()) { Store store = reflections8.getStore(); int keys = 0; int values = 0; for (String index : store.keySet()) { keys += store.get(index).keySet().size(); values += store.get(index).size(); } log.get().info(format("Reflections took %d ms to collect %d url%s, producing %d keys and %d values [%s]", System.currentTimeMillis() - start, urls.size(), urls.size() > 1 ? "s" : "", keys, values, Joiner.on(", ").join(urls))); } return reflections8; } /** merges saved Reflections resources from the given input stream, using the serializer configured in this instance's Configuration *
useful if you know the serialized resource location and prefer not to look it up the classpath * */ public Reflections collect(final InputStream inputStream) { try { merge(configuration.getSerializer().read(inputStream)); if (log.isPresent()) log.get().info("Reflections collected metadata from input stream using serializer " + configuration.getSerializer().getClass().getName()); } catch (Exception ex) { throw new ReflectionsException("could not merge input stream", ex); } return this; } /** merges saved Reflections resources from the given file, using the serializer configured in this instance's Configuration *

useful if you know the serialized resource location and prefer not to look it up the classpath * */ public Reflections collect(final File file) { FileInputStream inputStream = null; try { inputStream = new FileInputStream(file); return collect(inputStream); } catch (FileNotFoundException e) { throw new ReflectionsException("could not obtain input stream from file " + file, e); } finally { Utils.close(inputStream); } } /** * merges a Reflections instance metadata into this instance */ public Reflections merge(final Reflections reflections8) { if (reflections8.store != null) { for (String indexName : reflections8.store.keySet()) { SetMultimap index = reflections8.store.get(indexName); for (String key : index.keySet()) { for (String string : index.get(key)) { store.getOrCreate(indexName).putSingle(key, string); } } } } return this; } /** * expand super types after scanning, for super types that were not scanned. * this is helpful in finding the transitive closure without scanning all 3rd party dependencies. * it uses {@link ReflectionUtils#getSuperTypes(Class)}. *

* for example, for classes A,B,C where A supertype of B, B supertype of C: *

    *
  • if scanning C resulted in B (B->C in store), but A was not scanned (although A supertype of B) - then getSubTypes(A) will not return C
  • *
  • if expanding supertypes, B will be expanded with A (A->B in store) - then getSubTypes(A) will return C
  • *
*/ public void expandSuperTypes() { if (store.keySet().contains(index(SubTypesScanner.class))) { SetMultimap mmap = store.get(index(SubTypesScanner.class)); Set difference = new HashSet<>(); difference.addAll(mmap.keySet()); difference.removeAll(mmap.flatValuesAsSet()); SetMultimap expand = new HashSetMultimap<>(); for (String key : difference) { final Class type = forName(key, loaders()); if (type != null) { expandSupertypes(expand, key, type); } } mmap.putAllSingles(expand); } } private void expandSupertypes(SetMultimap mmap, String key, Class type) { for (Class supertype : ReflectionUtils.getSuperTypes(type)) { if (mmap.putSingle(supertype.getName(), key)) { if (log.isPresent()) log.get().debug("expanded subtype {} -> {}", supertype.getName(), key); expandSupertypes(mmap, supertype.getName(), supertype); } } } //query /** * gets all sub types in hierarchy of a given type *

depends on SubTypesScanner configured */ public Set> getSubTypesOf(final Class type) { return new HashSet(ReflectionUtils.forNames( store.getAll(index(SubTypesScanner.class), Arrays.asList(type.getName())), loaders())); } /** * get types annotated with a given annotation, both classes and annotations *

{@link java.lang.annotation.Inherited} is not honored by default. *

when honoring @Inherited, meta-annotation should only effect annotated super classes and its sub types *

Note that this (@Inherited) meta-annotation type has no effect if the annotated type is used for anything other then a class. * Also, this meta-annotation causes annotations to be inherited only from superclasses; annotations on implemented interfaces have no effect. *

depends on TypeAnnotationsScanner and SubTypesScanner configured */ public Set> getTypesAnnotatedWith(final Class annotation) { return getTypesAnnotatedWith(annotation, false); } /** * get types annotated with a given annotation, both classes and annotations *

{@link java.lang.annotation.Inherited} is honored according to given honorInherited. *

when honoring @Inherited, meta-annotation should only effect annotated super classes and it's sub types *

when not honoring @Inherited, meta annotation effects all subtypes, including annotations interfaces and classes *

Note that this (@Inherited) meta-annotation type has no effect if the annotated type is used for anything other then a class. * Also, this meta-annotation causes annotations to be inherited only from superclasses; annotations on implemented interfaces have no effect. *

depends on TypeAnnotationsScanner and SubTypesScanner configured */ public Set> getTypesAnnotatedWith(final Class annotation, boolean honorInherited) { Iterable annotated = store.get(index(TypeAnnotationsScanner.class), annotation.getName()); Iterable classes = getAllAnnotated(annotated, annotation.isAnnotationPresent(Inherited.class), honorInherited); return Stream.concat(forNames(annotated, loaders()).stream(), forNames(classes, loaders()).stream()).collect(Collectors.toSet()); } /** * get types annotated with a given annotation, both classes and annotations, including annotation member values matching *

{@link java.lang.annotation.Inherited} is not honored by default *

depends on TypeAnnotationsScanner configured */ public Set> getTypesAnnotatedWith(final Annotation annotation) { return getTypesAnnotatedWith(annotation, false); } /** * get types annotated with a given annotation, both classes and annotations, including annotation member values matching *

{@link java.lang.annotation.Inherited} is honored according to given honorInherited *

depends on TypeAnnotationsScanner configured */ public Set> getTypesAnnotatedWith(final Annotation annotation, boolean honorInherited) { Iterable annotated = store.get(index(TypeAnnotationsScanner.class), annotation.annotationType().getName()); Iterable> filter = filter(forNames(annotated, loaders()), withAnnotation(annotation)); Iterable classes = getAllAnnotated(names(filter), annotation.annotationType().isAnnotationPresent(Inherited.class), honorInherited); Stream classesStream = StreamSupport.stream(classes.spliterator(), false); Stream> filterStream = StreamSupport.stream(filter.spliterator(), false); HashSet annotatedSet = new HashSet(); for(String clazz: annotated) annotatedSet.add(clazz); return Stream.concat(filterStream, forNames(classesStream.filter(new Predicate() { @Override public boolean test(String s) { return !annotatedSet.contains(s); } }).collect(Collectors.toList()), loaders()).stream()).collect(Collectors.toSet()); } protected Iterable getAllAnnotated(Iterable annotated, boolean inherited, boolean honorInherited) { if (honorInherited) { if (inherited) { Iterable subTypes = store.get(index(SubTypesScanner.class), filter(annotated, new Predicate() { public boolean test(String input) { final Class type = forName(input, loaders()); return type != null && !type.isInterface(); } })); return ReflectionsIterables.concat(subTypes, store.getAll(index(SubTypesScanner.class), subTypes)); } else { return annotated; } } else { Iterable subTypes = ReflectionsIterables.concat(annotated, store.getAll(index(TypeAnnotationsScanner.class), annotated)); return ReflectionsIterables.concat(subTypes, store.getAll(index(SubTypesScanner.class), subTypes)); } } /** * get all methods annotated with a given annotation *

depends on MethodAnnotationsScanner configured */ public Set getMethodsAnnotatedWith(final Class annotation) { Iterable methods = store.get(index(MethodAnnotationsScanner.class), annotation.getName()); return getMethodsFromDescriptors(methods, loaders()); } /** * get all methods annotated with a given annotation, including annotation member values matching *

depends on MethodAnnotationsScanner configured */ public Set getMethodsAnnotatedWith(final Annotation annotation) { return filter(getMethodsAnnotatedWith(annotation.annotationType()), withAnnotation(annotation)); } /** get methods with parameter types matching given {@code types}*/ public Set getMethodsMatchParams(Class... types) { return getMethodsFromDescriptors(store.get(index(MethodParameterScanner.class), names(types).toString()), loaders()); } /** get methods with return type match given type */ public Set getMethodsReturn(Class returnType) { return getMethodsFromDescriptors(store.get(index(MethodParameterScanner.class), names(returnType)), loaders()); } /** get methods with any parameter annotated with given annotation */ public Set getMethodsWithAnyParamAnnotated(Class annotation) { return getMethodsFromDescriptors(store.get(index(MethodParameterScanner.class), annotation.getName()), loaders()); } /** get methods with any parameter annotated with given annotation, including annotation member values matching */ public Set getMethodsWithAnyParamAnnotated(Annotation annotation) { return filter(getMethodsWithAnyParamAnnotated(annotation.annotationType()), withAnyParameterAnnotation(annotation)); } /** * get all constructors annotated with a given annotation *

depends on MethodAnnotationsScanner configured */ public Set getConstructorsAnnotatedWith(final Class annotation) { Iterable methods = store.get(index(MethodAnnotationsScanner.class), annotation.getName()); return getConstructorsFromDescriptors(methods, loaders()); } /** * get all constructors annotated with a given annotation, including annotation member values matching *

depends on MethodAnnotationsScanner configured */ public Set getConstructorsAnnotatedWith(final Annotation annotation) { return filter(getConstructorsAnnotatedWith(annotation.annotationType()), withAnnotation(annotation)); } /** get constructors with parameter types matching given {@code types}*/ public Set getConstructorsMatchParams(Class... types) { return getConstructorsFromDescriptors(store.get(index(MethodParameterScanner.class), names(types).toString()), loaders()); } /** get constructors with any parameter annotated with given annotation */ public Set getConstructorsWithAnyParamAnnotated(Class annotation) { return getConstructorsFromDescriptors(store.get(index(MethodParameterScanner.class), annotation.getName()), loaders()); } /** get constructors with any parameter annotated with given annotation, including annotation member values matching */ public Set getConstructorsWithAnyParamAnnotated(Annotation annotation) { return filter(getConstructorsWithAnyParamAnnotated(annotation.annotationType()), withAnyParameterAnnotation(annotation)); } /** * get all fields annotated with a given annotation *

depends on FieldAnnotationsScanner configured */ public Set getFieldsAnnotatedWith(final Class annotation) { final Set result =new HashSet(); for (String annotated : store.get(index(FieldAnnotationsScanner.class), annotation.getName())) { result.add(getFieldFromString(annotated, loaders())); } return result; } /** * get all methods annotated with a given annotation, including annotation member values matching *

depends on FieldAnnotationsScanner configured */ public Set getFieldsAnnotatedWith(final Annotation annotation) { return filter(getFieldsAnnotatedWith(annotation.annotationType()), withAnnotation(annotation)); } /** get resources relative paths where simple name (key) matches given namePredicate *

depends on ResourcesScanner configured * */ public Set getResources(final Predicate namePredicate) { HashSet result = new HashSet<>(); Stream resources = store.get(index(ResourcesScanner.class)).keySet().stream().filter(namePredicate); store.get(index(ResourcesScanner.class), resources.collect(Collectors.toSet())).forEach(s -> result.add(s)); return result; } /** get resources relative paths where simple name (key) matches given regular expression *

depends on ResourcesScanner configured *

Set<String> xmls = reflections8.getResources(".*\\.xml");
*/ public Set getResources(final Pattern pattern) { return getResources(new Predicate() { public boolean test(String input) { return pattern.matcher(input).matches(); } }); } /** get parameter names of given {@code method} *

depends on MethodParameterNamesScanner configured */ public List getMethodParamNames(Method method) { Iterable names = store.get(index(MethodParameterNamesScanner.class), name(method)); return names != null && names.iterator().hasNext() ? Arrays.asList(ReflectionsIterables.getOnlyElement(names).split(", ")) : Arrays.asList(); } /** get parameter names of given {@code constructor} *

depends on MethodParameterNamesScanner configured */ public List getConstructorParamNames(Constructor constructor) { Iterable names = store.get(index(MethodParameterNamesScanner.class), Utils.name(constructor)); return !ReflectionsIterables.isEmpty(names) ? Arrays.asList(ReflectionsIterables.getOnlyElement(names).split(", ")) : Arrays.asList(); } /** get all given {@code field} usages in methods and constructors *

depends on MemberUsageScanner configured */ public Set getFieldUsage(Field field) { return getMembersFromDescriptors(store.get(index(MemberUsageScanner.class), name(field))); } /** get all given {@code method} usages in methods and constructors *

depends on MemberUsageScanner configured */ public Set getMethodUsage(Method method) { return getMembersFromDescriptors(store.get(index(MemberUsageScanner.class), name(method))); } /** get all given {@code constructors} usages in methods and constructors *

depends on MemberUsageScanner configured */ public Set getConstructorUsage(Constructor constructor) { return getMembersFromDescriptors(store.get(index(MemberUsageScanner.class), name(constructor))); } /** get all types scanned. this is effectively similar to getting all subtypes of Object. *

depends on SubTypesScanner configured with {@code SubTypesScanner(false)}, otherwise {@code ReflectionsException} is thrown *

note using this might be a bad practice. it is better to get types matching some criteria, * such as {@link #getSubTypesOf(Class)} or {@link #getTypesAnnotatedWith(Class)} * @return Set of String, and not of Class, in order to avoid definition of all types in PermGen */ public Set getAllTypes() { Set allTypes = ReflectionsIterables.makeSetOf(store.getAll(index(SubTypesScanner.class), Object.class.getName())); if (allTypes.isEmpty()) { throw new ReflectionsException("Couldn't find subtypes of Object. " + "Make sure SubTypesScanner initialized to include Object class - new SubTypesScanner(false)"); } return allTypes; } /** returns the {@link org.reflections8.Store} used for storing and querying the metadata */ public Store getStore() { return store; } /** returns the {@link org.reflections8.Configuration} object of this instance */ public Configuration getConfiguration() { return configuration; } /** * serialize to a given directory and filename *

* it is preferred to specify a designated directory (for example META-INF/reflections), * so that it could be found later much faster using the load method *

see the documentation for the save method on the configured {@link org.reflections8.serializers.Serializer} */ public File save(final String filename) { return save(filename, configuration.getSerializer()); } /** * serialize to a given directory and filename using given serializer *

* it is preferred to specify a designated directory (for example META-INF/reflections), * so that it could be found later much faster using the load method */ public File save(final String filename, final Serializer serializer) { File file = serializer.save(this, filename); if (log.isPresent()) //noinspection ConstantConditions log.get().info("Reflections successfully saved in " + file.getAbsolutePath() + " using " + serializer.getClass().getSimpleName()); return file; } private Optional loaders() { return configuration.getClassLoaders(); } }