/** * Scans the specified packages for annotated classes, and applies Config values to them. * * @param config the Config to derive values from * @param packageNamePrefix the prefix to limit scanning to - e.g. "com.github" * @return The constructed TypesafeConfigModule. */ public static TypesafeConfigModule fromConfigWithPackage(Config config, String packageNamePrefix) { ConfigurationBuilder configBuilder = new ConfigurationBuilder() .filterInputsBy(new FilterBuilder().includePackage(packageNamePrefix)) .setUrls(ClasspathHelper.forPackage(packageNamePrefix)) .setScanners( new TypeAnnotationsScanner(), new MethodParameterScanner(), new MethodAnnotationsScanner(), new FieldAnnotationsScanner() ); Reflections reflections = new Reflections(configBuilder); return new TypesafeConfigModule(config, reflections); }
private void init(String packageName) { FilterBuilder filters = new FilterBuilder().includePackage(packageName); Scanner[] scanners = { new TypeAnnotationsScanner(), new MethodAnnotationsScanner(), new MethodParameterScanner(), new FieldAnnotationsScanner(), new SubTypesScanner().filterResultsBy(filters) }; reflections = new ConfigurationBuilder() .addUrls(ClasspathHelper.forPackage(packageName)) .addScanners(scanners) .filterInputsBy(filters) .build(); }
/** * Initializes the instance based on what is returned by {@link #ignoreAllAnnotationsAssociatedWithTheseProjectClasses()} * and {@link #specificAnnotationDeclarationExclusionsForProject()}. This is time consuming and should only be done * once per project if possible - see the usage info in the {@link ReflectionBasedJsr303AnnotationTrollerBase} * class-level javadocs. * * <p>The given set of extra packages for constraint annotation searching will be passed into {@link * #getFinalPackagesToSearchForConstraintAnnotations(Set)} to generate the final set of packages that are searched. * If you don't want the {@link #DEFAULT_CONSTRAINT_SEARCH_PACKAGES} default packages to be searched you can * override {@link #getDefaultPackagesToSearchForConstraintAnnotations()}. */ public ReflectionBasedJsr303AnnotationTrollerBase(Set<String> extraPackagesForConstraintAnnotationSearch) { /* * Set up the {@link #ignoreAllAnnotationsAssociatedWithTheseClasses} and * {@link #specificAnnotationDeclarationsExcludedFromStrictMessageRequirement} fields so we know which * annotations are project-relevant vs. unit-test-only. */ ignoreAllAnnotationsAssociatedWithTheseClasses = new ArrayList<>(setupIgnoreAllAnnotationsAssociatedWithTheseClasses()); specificAnnotationDeclarationsExcludedFromStrictMessageRequirement = new ArrayList<>(setupSpecificAnnotationDeclarationExclusions()); /* * Set up the {@link #reflections}, {@link #constraintAnnotationClasses}, and * {@link #allConstraintAnnotationsMasterList} fields. This is where the crazy reflection magic happens to troll * the project for the JSR 303 annotation declarations. */ // Create the ConfigurationBuilder to search the relevant set of packages. ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); for (String packageToAdd : getFinalPackagesToSearchForConstraintAnnotations( extraPackagesForConstraintAnnotationSearch)) { configurationBuilder.addUrls(ClasspathHelper.forPackage(packageToAdd)); } // Create the Reflections object so it scans for all validation annotations we care about and all project // classes that might have annotations on them. reflections = new Reflections(configurationBuilder.setScanners( new SubTypesScanner(), new MethodParameterScanner(), new TypeAnnotationsScanner(), new MethodAnnotationsScanner(), new FieldAnnotationsScanner() )); // Gather the list of all JSR 303 validation annotations in the project. Per the JSR 303 spec this is any // annotation class type that is marked with @Constraint. constraintAnnotationClasses = new ArrayList<>(); for (Class<?> constraintAnnotatedType : reflections.getTypesAnnotatedWith(Constraint.class, true)) { if (constraintAnnotatedType.isAnnotation()) { //noinspection unchecked constraintAnnotationClasses.add((Class<? extends Annotation>) constraintAnnotatedType); } } // We're not done gathering validation annotations though, unfortunately. JSR 303 also says that *any* // annotation (whether it is a Constraint or not) that has a value field that returns an array of actual // Constraints is treated as a "multi-value constraint", and the validation processor will run each // of the Constraints in the array as if they were declared separately on the annotated element. Therefore, // we have to dig through all the annotations in the project, find any that fall into this "multi-value // constraint" category, and include them in our calculations. for (Class<? extends Annotation> annotationClass : reflections.getSubTypesOf(Annotation.class)) { if (isMultiValueConstraintClass(annotationClass)) constraintAnnotationClasses.add(annotationClass); } // Setup the master constraint list allConstraintAnnotationsMasterList = new ArrayList<>(setupAllConstraintAnnotationsMasterList(reflections, constraintAnnotationClasses)); /* * Finally use the info we've gathered/constructed previously to populate the * {@link #projectRelevantConstraintAnnotationsExcludingUnitTestsList} field, which is the main chunk of data * that extensions of this class will care about. */ projectRelevantConstraintAnnotationsExcludingUnitTestsList = Collections.unmodifiableList( getSubAnnotationListUsingExclusionFilters(allConstraintAnnotationsMasterList, ignoreAllAnnotationsAssociatedWithTheseClasses, specificAnnotationDeclarationsExcludedFromStrictMessageRequirement)); }