
alluxio.shaded.client.org.reflections.Reflections Maven / Gradle / Ivy
package alluxio.shaded.client.org.reflections;
import alluxio.shaded.client.org.reflections.scanners.FieldAnnotationsScanner;
import alluxio.shaded.client.org.reflections.scanners.MemberUsageScanner;
import alluxio.shaded.client.org.reflections.scanners.MethodAnnotationsScanner;
import alluxio.shaded.client.org.reflections.scanners.MethodParameterNamesScanner;
import alluxio.shaded.client.org.reflections.scanners.MethodParameterScanner;
import alluxio.shaded.client.org.reflections.scanners.ResourcesScanner;
import alluxio.shaded.client.org.reflections.scanners.Scanner;
import alluxio.shaded.client.org.reflections.scanners.SubTypesScanner;
import alluxio.shaded.client.org.reflections.scanners.TypeAnnotationsScanner;
import alluxio.shaded.client.org.reflections.serializers.Serializer;
import alluxio.shaded.client.org.reflections.serializers.XmlSerializer;
import alluxio.shaded.client.org.reflections.util.ClasspathHelper;
import alluxio.shaded.client.org.reflections.util.ConfigurationBuilder;
import alluxio.shaded.client.org.reflections.util.FilterBuilder;
import alluxio.shaded.client.org.reflections.util.Utils;
import alluxio.shaded.client.org.reflections.vfs.Vfs;
import alluxio.shaded.client.org.slf4j.Logger;
import java.alluxio.shaded.client.io.File;
import java.alluxio.shaded.client.io.FileInputStream;
import java.alluxio.shaded.client.io.FileNotFoundException;
import java.alluxio.shaded.client.io.IOException;
import java.alluxio.shaded.client.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.Collections;
import java.util.HashSet;
import java.util.List;
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 static java.lang.String.format;
import static alluxio.shaded.client.org.reflections.ReflectionUtils.*;
import static alluxio.shaded.client.org.reflections.util.Utils.*;
/**
* 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 = reflections.getSubTypesOf(SomeType.class);
*
* Set<Class<?>> annotated = reflections.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 = reflections.getSubTypesOf(alluxio.shaded.client.alluxio.shaded.client.com.google.inject.Module.class);
* Set<Class<?>> singletons = reflections.getTypesAnnotatedWith(alluxio.shaded.client.javax.inject.Singleton.class);
*
* Set<String> properties = reflections.getResources(Pattern.alluxio.shaded.client.com.ile(".*\\.properties"));
* Set<Constructor> injectables = reflections.getConstructorsAnnotatedWith(alluxio.shaded.client.javax.inject.Inject.class);
* Set<Method> deprecateds = reflections.getMethodsAnnotatedWith(alluxio.shaded.client.javax.ws.rs.Path.class);
* Set<Field> ids = reflections.getFieldsAnnotatedWith(alluxio.shaded.client.javax.persistence.Id.class);
*
* Set<Method> someMethods = reflections.getMethodsMatchParams(long.class, int.class);
* Set<Method> voidMethods = reflections.getMethodsReturn(void.class);
* Set<Method> pathParamMethods = reflections.getMethodsWithAnyParamAnnotated(PathParam.class);
* Set<Method> floatToString = reflections.getConverters(Float.class, String.class);
* List<String> parameterNames = reflections.getMethodsParamNames(Method.class);
*
* Set<Member> fieldUsage = reflections.getFieldUsage(Field.class);
* Set<Member> methodUsage = reflections.getMethodUsage(Method.class);
* Set<Member> constructorUsage = reflections.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, alluxio.shaded.client.org.reflections.serializers.Serializer)}
* for example with {@link alluxio.shaded.client.org.reflections.serializers.XmlSerializer} or {@link alluxio.shaded.client.org.reflections.serializers.JavaCodeSerializer}
*
In order to collect pre saved metadata and avoid re-scanning, use {@link #collect(String, java.util.function.Predicate, alluxio.shaded.client.org.reflections.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.alluxio.shaded.client.com.ronmamo/reflections/
*/
public class Reflections {
public static Logger log = findLogger(Reflections.class);
protected final transient Configuration configuration;
protected Store store;
/**
* constructs a Reflections instance and scan according to given {@link alluxio.shaded.client.org.reflections.Configuration}
*
it is preferred to use {@link alluxio.shaded.client.org.reflections.util.ConfigurationBuilder}
*/
public Reflections(final Configuration configuration) {
this.configuration = configuration;
store = new Store();
if (configuration.getScanners() != null && !configuration.getScanners().isEmpty()) {
//inject to scanners
for (Scanner scanner : configuration.getScanners()) {
scanner.setConfiguration(configuration);
}
scan();
if (configuration.shouldExpandSuperTypes()) {
expandSuperTypes();
}
}
}
/**
* a convenient constructor for scanning within a package prefix.
*
this actually create a {@link alluxio.shaded.client.org.reflections.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 alluxio.shaded.client.org.reflections.scanners.TypeAnnotationsScanner} and {@link alluxio.shaded.client.org.reflections.scanners.SubTypesScanner}.
* @param prefix package prefix, to be used with {@link alluxio.shaded.client.org.reflections.util.ClasspathHelper#forPackage(String, ClassLoader...)} )}
* @param scanners optionally supply scanners, otherwise defaults to {@link alluxio.shaded.client.org.reflections.scanners.TypeAnnotationsScanner} and {@link alluxio.shaded.client.org.reflections.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 alluxio.shaded.client.org.reflections.util.ClasspathHelper#forPackage(String, ClassLoader...)} ()}
* - {@link Class} - would add urls using {@link alluxio.shaded.client.org.reflections.util.ClasspathHelper#forClass(Class, ClassLoader...)}
* - {@link ClassLoader} - would use this classloaders in order to find urls in {@link alluxio.shaded.client.org.reflections.util.ClasspathHelper#forPackage(String, ClassLoader...)} and {@link alluxio.shaded.client.org.reflections.util.ClasspathHelper#forClass(Class, ClassLoader...)}
* - {@link alluxio.shaded.client.org.reflections.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 alluxio.shaded.client.org.reflections.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();
}
//
protected void scan() {
if (configuration.getUrls() == null || configuration.getUrls().isEmpty()) {
if (log != null) log.warn("given scan urls are empty. set urls in the configuration");
return;
}
if (log != null && log.isDebugEnabled()) {
log.debug("going to scan these urls: {}", configuration.getUrls());
}
long time = System.currentTimeMillis();
int scannedUrls = 0;
ExecutorService executorService = configuration.getExecutorService();
List> futures = new ArrayList<>();
for (final URL url : configuration.getUrls()) {
try {
if (executorService != null) {
futures.add(executorService.submit(() -> {
if (log != null) {
log.debug("[{}] scanning {}", Thread.currentThread().toString(), url);
}
scan(url);
}));
} else {
scan(url);
}
scannedUrls++;
} catch (ReflectionsException e) {
if (log != null) {
log.warn("could not create Vfs.Dir from url. ignoring the exception and continuing", e);
}
}
}
//todo use CompletionService
if (executorService != null) {
for (Future future : futures) {
try { future.get(); } catch (Exception e) { throw new RuntimeException(e); }
}
}
//gracefully shutdown the parallel scanner executor service.
if (executorService != null) {
executorService.shutdown();
}
if (log != null) {
log.info(format("Reflections took %d ms to scan %d urls, producing %s %s",
System.currentTimeMillis() - time, scannedUrls, producingDescription(store),
executorService instanceof ThreadPoolExecutor ?
format("[using %d cores]", ((ThreadPoolExecutor) executorService).getMaximumPoolSize()) : ""));
}
}
private static String producingDescription(Store store) {
int keys = 0;
int values = 0;
for (String index : store.keySet()) {
keys += store.keys(index).size();
values += store.values(index).size();
}
return String.format("%d keys and %d values", keys, values);
}
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
Predicate inputsFilter = configuration.getInputsFilter();
String path = file.getRelativePath();
String fqn = path.replace('/', '.');
if (inputsFilter == null || inputsFilter.test(path) || inputsFilter.test(fqn)) {
Object classObject = null;
for (Scanner scanner : configuration.getScanners()) {
try {
if (scanner.acceptsInput(path) || scanner.acceptsInput(fqn)) {
classObject = scanner.scan(file, classObject, store);
}
} catch (Exception e) {
if (log != null) {
// SLF4J will filter out Throwables from the format string arguments.
log.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 alluxio.shaded.client.org.reflections.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 alluxio.shaded.client.org.reflections.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 reflections = new Reflections();
Iterable files = Vfs.findFiles(urls, packagePrefix, resourceNameFilter);
for (final Vfs.File file : files) {
InputStream inputStream = null;
try {
inputStream = file.openInputStream();
reflections.merge(serializer.read(inputStream));
} catch (IOException e) {
throw new ReflectionsException("could not merge " + file, e);
} finally {
close(inputStream);
}
}
if (log != null) {
log.info(format("Reflections took %d ms to collect %d url, producing %s",
System.currentTimeMillis() - start, urls.size(), producingDescription(reflections.store)));
}
return reflections;
}
/** 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 != null) log.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 reflections) {
store.merge(reflections.store);
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() {
String index = index(SubTypesScanner.class);
Set keys = store.keys(index);
keys.removeAll(store.values(index));
for (String key : keys) {
final Class> type = forName(key, loaders());
if (type != null) {
expandSupertypes(store, key, type);
}
}
}
private void expandSupertypes(Store store, String key, Class> type) {
for (Class> supertype : ReflectionUtils.getSuperTypes(type)) {
if (store.put(SubTypesScanner.class, supertype.getName(), key)) {
if (log != null) log.debug("expanded subtype {} -> {}", supertype.getName(), key);
expandSupertypes(store, 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 forNames(store.getAll(SubTypesScanner.class, 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 extends Annotation> 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 extends Annotation> annotation, boolean honorInherited) {
Set annotated = store.get(TypeAnnotationsScanner.class, annotation.getName());
annotated.addAll(getAllAnnotated(annotated, annotation, honorInherited));
return forNames(annotated, loaders());
}
/**
* 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) {
Set annotated = store.get(TypeAnnotationsScanner.class, annotation.annotationType().getName());
Set> allAnnotated = filter(forNames(annotated, loaders()), withAnnotation(annotation));
Set> classes = forNames(filter(getAllAnnotated(names(allAnnotated), annotation.annotationType(), honorInherited), s -> !annotated.contains(s)), loaders());
allAnnotated.addAll(classes);
return allAnnotated;
}
protected Collection getAllAnnotated(Collection annotated, Class extends Annotation> annotation, boolean honorInherited) {
if (honorInherited) {
if (annotation.isAnnotationPresent(Inherited.class)) {
Set subTypes = store.get(SubTypesScanner.class, filter(annotated, input -> {
final Class> type = forName(input, loaders());
return type != null && !type.isInterface();
}));
return store.getAllIncluding(SubTypesScanner.class, subTypes);
} else {
return annotated;
}
} else {
Collection subTypes = store.getAllIncluding(TypeAnnotationsScanner.class, annotated);
return store.getAllIncluding(SubTypesScanner.class, subTypes);
}
}
/**
* get all methods annotated with a given annotation
* depends on MethodAnnotationsScanner configured
*/
public Set getMethodsAnnotatedWith(final Class extends Annotation> annotation) {
return getMethodsFromDescriptors(store.get(MethodAnnotationsScanner.class, annotation.getName()), 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(MethodParameterScanner.class, names(types).toString()), loaders());
}
/** get methods with return type match given type */
public Set getMethodsReturn(Class returnType) {
return getMethodsFromDescriptors(store.get(MethodParameterScanner.class, names(returnType)), loaders());
}
/** get methods with any parameter annotated with given annotation */
public Set getMethodsWithAnyParamAnnotated(Class extends Annotation> annotation) {
return getMethodsFromDescriptors(store.get(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 extends Annotation> annotation) {
return getConstructorsFromDescriptors(store.get(MethodAnnotationsScanner.class, annotation.getName()), 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(MethodParameterScanner.class, names(types).toString()), loaders());
}
/** get constructors with any parameter annotated with given annotation */
public Set getConstructorsWithAnyParamAnnotated(Class extends Annotation> annotation) {
return getConstructorsFromDescriptors(store.get(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 extends Annotation> annotation) {
return store.get(FieldAnnotationsScanner.class, annotation.getName()).stream()
.map(annotated -> getFieldFromString(annotated, loaders()))
.collect(Collectors.toSet());
}
/**
* 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) {
Set resources = filter(store.keys(index(ResourcesScanner.class)), namePredicate);
return store.get(ResourcesScanner.class, resources);
}
/** get resources relative paths where simple name (key) matches given regular expression
* depends on ResourcesScanner configured
*
Set xmls = reflections.getResources(".*\\.xml");
*/
public Set getResources(final Pattern pattern) {
return getResources(input -> pattern.matcher(input).matches());
}
/** get parameter names of given {@code method}
* depends on MethodParameterNamesScanner configured
*/
public List getMethodParamNames(Method method) {
Set names = store.get(MethodParameterNamesScanner.class, name(method));
return names.size() == 1 ? Arrays.asList(names.iterator().next().split(", ")) : Collections.emptyList();
}
/** get parameter names of given {@code constructor}
* depends on MethodParameterNamesScanner configured
*/
public List getConstructorParamNames(Constructor constructor) {
Set names = store.get(MethodParameterNamesScanner.class, Utils.name(constructor));
return names.size() == 1 ? Arrays.asList(names.iterator().next().split(", ")) : Collections.emptyList();
}
/** get all given {@code field} usages in methods and constructors
* depends on MemberUsageScanner configured
*/
public Set getFieldUsage(Field field) {
return getMembersFromDescriptors(store.get(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(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(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 = new HashSet<>(store.getAll(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 alluxio.shaded.client.org.reflections.Store} used for storing and querying the metadata */
public Store getStore() {
return store;
}
/** returns the {@link alluxio.shaded.client.org.reflections.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 alluxio.shaded.client.org.reflections.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 != null)
log.info("Reflections successfully saved in " + file.getAbsolutePath() + " using " + serializer.getClass().getSimpleName());
return file;
}
private ClassLoader[] loaders() { return configuration.getClassLoaders(); }
}