/**
  * 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)}.
  *
  * <p>for example, for classes A,B,C where A supertype of B, B supertype of C:
  *
  * <ul>
  *   <li>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
  *   <li>if expanding supertypes, B will be expanded with A (A->B in store) - then getSubTypes(A)
  *       will return C
  * </ul>
  */
 public void expandSuperTypes() {
   if (store.keySet().contains(index(SubTypesScanner.class))) {
     Multimap<String, String> mmap = store.get(index(SubTypesScanner.class));
     Sets.SetView<String> keys = Sets.difference(mmap.keySet(), Sets.newHashSet(mmap.values()));
     Multimap<String, String> expand = HashMultimap.create();
     for (String key : keys) {
       expandSupertypes(expand, key, forName(key));
     }
     mmap.putAll(expand);
   }
 }
 /**
  * get parameter names of given {@code constructor}
  *
  * <p>depends on MethodParameterNamesScanner configured
  */
 public List<String> getConstructorParamNames(Constructor constructor) {
   Iterable<String> names =
       store.get(index(MethodParameterNamesScanner.class), Utils.name(constructor));
   return !Iterables.isEmpty(names)
       ? Arrays.asList(Iterables.getOnlyElement(names).split(", "))
       : Arrays.<String>asList();
 }
 /**
  * get all fields annotated with a given annotation
  *
  * <p>depends on FieldAnnotationsScanner configured
  */
 public Set<Field> getFieldsAnnotatedWith(final Class<? extends Annotation> annotation) {
   final Set<Field> result = Sets.newHashSet();
   for (String annotated : store.get(index(FieldAnnotationsScanner.class), annotation.getName())) {
     result.add(getFieldFromString(annotated, loaders()));
   }
   return result;
 }
  /**
   * 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
   * XmlSerializer} or using the optionally supplied optionalSerializer
   *
   * <p>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 XmlSerializer} will be used
   */
  public static Reflections collect(
      final String packagePrefix,
      final Predicate<String> resourceNameFilter,
      @Nullable Serializer... optionalSerializer) {
    Serializer serializer =
        optionalSerializer != null && optionalSerializer.length == 1
            ? optionalSerializer[0]
            : new XmlSerializer();

    Collection<URL> urls = ClasspathHelper.forPackage(packagePrefix);
    if (urls.isEmpty()) return null;
    long start = System.currentTimeMillis();
    final Reflections reflections = new Reflections();
    Iterable<Vfs.File> 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) {
      Store store = reflections.getStore();
      int keys = 0;
      int values = 0;
      for (String index : store.keySet()) {
        keys += store.get(index).keySet().size();
        values += store.get(index).size();
      }

      log.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 reflections;
  }
 /**
  * get types annotated with a given annotation, both classes and annotations
  *
  * <p>{@link Inherited} is honored according to given honorInherited.
  *
  * <p>when honoring @Inherited, meta-annotation should only effect annotated super classes and
  * it's sub types
  *
  * <p>when not honoring @Inherited, meta annotation effects all subtypes, including annotations
  * interfaces and classes
  *
  * <p><i>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.</i>
  *
  * <p>depends on TypeAnnotationsScanner and SubTypesScanner configured
  */
 public Set<Class<?>> getTypesAnnotatedWith(
     final Class<? extends Annotation> annotation, boolean honorInherited) {
   Iterable<String> annotated =
       store.get(index(TypeAnnotationsScanner.class), annotation.getName());
   Iterable<String> classes =
       getAllAnnotated(annotated, annotation.isAnnotationPresent(Inherited.class), honorInherited);
   return Sets.newHashSet(concat(forNames(annotated, loaders()), forNames(classes, loaders())));
 }
 /**
  * get all types scanned. this is effectively similar to getting all subtypes of Object.
  *
  * <p>depends on SubTypesScanner configured with {@code SubTypesScanner(false)}, otherwise {@code
  * ReflectionsException} is thrown
  *
  * <p><i>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)}</i>
  *
  * @return Set of String, and not of Class, in order to avoid definition of all types in PermGen
  */
 public Set<String> getAllTypes() {
   Set<String> allTypes =
       Sets.newHashSet(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;
 }
 /**
  * get types annotated with a given annotation, both classes and annotations, including annotation
  * member values matching
  *
  * <p>{@link Inherited} is honored according to given honorInherited
  *
  * <p>depends on TypeAnnotationsScanner configured
  */
 public Set<Class<?>> getTypesAnnotatedWith(final Annotation annotation, boolean honorInherited) {
   Iterable<String> annotated =
       store.get(index(TypeAnnotationsScanner.class), annotation.annotationType().getName());
   Iterable<Class<?>> filter = filter(forNames(annotated, loaders()), withAnnotation(annotation));
   Iterable<String> classes =
       getAllAnnotated(
           names(filter),
           annotation.annotationType().isAnnotationPresent(Inherited.class),
           honorInherited);
   return Sets.newHashSet(
       concat(filter, forNames(filter(classes, not(in(Sets.newHashSet(annotated)))), loaders())));
 }
 /** merges a Reflections instance metadata into this instance */
 public Reflections merge(final Reflections reflections) {
   if (reflections.store != null) {
     for (String indexName : reflections.store.keySet()) {
       Multimap<String, String> index = reflections.store.get(indexName);
       for (String key : index.keySet()) {
         for (String string : index.get(key)) {
           store.getOrCreate(indexName).put(key, string);
         }
       }
     }
   }
   return this;
 }
 protected Iterable<String> getAllAnnotated(
     Iterable<String> annotated, boolean inherited, boolean honorInherited) {
   if (honorInherited) {
     if (inherited) {
       Iterable<String> subTypes =
           store.get(
               index(SubTypesScanner.class),
               filter(
                   annotated,
                   new Predicate<String>() {
                     public boolean apply(@Nullable String input) {
                       return !ReflectionUtils.forName(input, loaders()).isInterface();
                     }
                   }));
       return concat(subTypes, store.getAll(index(SubTypesScanner.class), subTypes));
     } else {
       return annotated;
     }
   } else {
     Iterable<String> subTypes =
         concat(annotated, store.getAll(index(TypeAnnotationsScanner.class), annotated));
     return concat(subTypes, store.getAll(index(SubTypesScanner.class), subTypes));
   }
 }
示例#10
0
  /**
   * constructs a Reflections instance and scan according to given {@link
   * org.reflections.Configuration}
   *
   * <p>it is preferred to use {@link 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(scanner.getClass().getSimpleName()));
      }

      scan();

      if (configuration.shouldExpandSuperTypes()) {
        expandSuperTypes();
      }
    }
  }
示例#11
0
 /**
  * get all given {@code constructors} usages in methods and constructors
  *
  * <p>depends on MemberUsageScanner configured
  */
 public Set<Member> getConstructorUsage(Constructor constructor) {
   return getMembersFromDescriptors(store.get(index(MemberUsageScanner.class), name(constructor)));
 }
示例#12
0
 /**
  * get all constructors annotated with a given annotation
  *
  * <p>depends on MethodAnnotationsScanner configured
  */
 public Set<Constructor> getConstructorsAnnotatedWith(
     final Class<? extends Annotation> annotation) {
   Iterable<String> methods =
       store.get(index(MethodAnnotationsScanner.class), annotation.getName());
   return getConstructorsFromDescriptors(methods, loaders());
 }
示例#13
0
 /**
  * get all given {@code field} usages in methods and constructors
  *
  * <p>depends on MemberUsageScanner configured
  */
 public Set<Member> getFieldUsage(Field field) {
   return getMembersFromDescriptors(store.get(index(MemberUsageScanner.class), name(field)));
 }
示例#14
0
 /**
  * get all given {@code method} usages in methods and constructors
  *
  * <p>depends on MemberUsageScanner configured
  */
 public Set<Member> getMethodUsage(Method method) {
   return getMembersFromDescriptors(store.get(index(MemberUsageScanner.class), name(method)));
 }
示例#15
0
 /**
  * get parameter names of given {@code method}
  *
  * <p>depends on MethodParameterNamesScanner configured
  */
 public List<String> getMethodParamNames(Method method) {
   Iterable<String> names = store.get(index(MethodParameterNamesScanner.class), name(method));
   return !Iterables.isEmpty(names)
       ? Arrays.asList(Iterables.getOnlyElement(names).split(", "))
       : Arrays.<String>asList();
 }
示例#16
0
 /**
  * gets all sub types in hierarchy of a given type
  *
  * <p>depends on SubTypesScanner configured
  */
 public <T> Set<Class<? extends T>> getSubTypesOf(final Class<T> type) {
   return Sets.newHashSet(
       ReflectionUtils.<T>forNames(
           store.getAll(index(SubTypesScanner.class), Arrays.asList(type.getName())), loaders()));
 }
示例#17
0
 /**
  * get resources relative paths where simple name (key) matches given namePredicate
  *
  * <p>depends on ResourcesScanner configured
  */
 public Set<String> getResources(final Predicate<String> namePredicate) {
   Iterable<String> resources =
       Iterables.filter(store.get(index(ResourcesScanner.class)).keySet(), namePredicate);
   return Sets.newHashSet(store.get(index(ResourcesScanner.class), resources));
 }
示例#18
0
 /** get methods with return type match given type */
 public Set<Method> getMethodsReturn(Class returnType) {
   return getMethodsFromDescriptors(
       store.get(index(MethodParameterScanner.class), names(returnType)), loaders());
 }
示例#19
0
 /** get constructors with any parameter annotated with given annotation */
 public Set<Constructor> getConstructorsWithAnyParamAnnotated(
     Class<? extends Annotation> annotation) {
   return getConstructorsFromDescriptors(
       store.get(index(MethodParameterScanner.class), annotation.getName()), loaders());
 }
示例#20
0
 /** get constructors with parameter types matching given {@code types} */
 public Set<Constructor> getConstructorsMatchParams(Class<?>... types) {
   return getConstructorsFromDescriptors(
       store.get(index(MethodParameterScanner.class), names(types).toString()), loaders());
 }
示例#21
0
  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:\n" + Joiner.on("\n").join(configuration.getUrls()));
    }

    long time = System.currentTimeMillis();
    int scannedUrls = 0;
    ExecutorService executorService = configuration.getExecutorService();
    List<Future<?>> futures = Lists.newArrayList();

    for (final URL url : configuration.getUrls()) {
      try {
        if (executorService != null) {
          futures.add(
              executorService.submit(
                  new Runnable() {
                    public void run() {
                      if (log != null && log.isDebugEnabled())
                        log.debug("[" + Thread.currentThread().toString() + "] scanning " + url);
                      scan(url);
                    }
                  }));
        } else {
          scan(url);
        }
        scannedUrls++;
      } catch (ReflectionsException e) {
        if (log != null && log.isWarnEnabled())
          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);
        }
      }
    }

    time = System.currentTimeMillis() - time;

    // gracefully shutdown the parallel scanner executor service.
    if (executorService != null) {
      executorService.shutdown();
    }

    if (log != null) {
      int keys = 0;
      int values = 0;
      for (String index : store.keySet()) {
        keys += store.get(index).keySet().size();
        values += store.get(index).size();
      }

      log.info(
          format(
              "Reflections took %d ms to scan %d urls, producing %d keys and %d values %s",
              time,
              scannedUrls,
              keys,
              values,
              executorService != null && executorService instanceof ThreadPoolExecutor
                  ? format(
                      "[using %d cores]",
                      ((ThreadPoolExecutor) executorService).getMaximumPoolSize())
                  : ""));
    }
  }