public Set<Class<?>> scanClasspathForAnnotation(Class<?> annotation, String... onlyFromPackages) { ClassInfoList classInfoList = scanResult.getClassesWithAnnotation(annotation.getName()); classInfoList = classInfoList .filter(ci -> Arrays.stream(onlyFromPackages) .anyMatch(p -> classMatchesPackage(ci.getName(), p))); return classInfoList.loadClasses().stream().collect(toSet()); }
public Set<Class<?>> scanPackagesForClassesImplementing(Class<?> implementedInterface, String... onlyFromPackages) { ClassInfoList classInfoList = scanResult.getClassesImplementing(implementedInterface.getName()) .filter(ci -> !ci.isAbstract() && !ci.isInterface() && ci.isPublic()); classInfoList = classInfoList .filter(ci -> Arrays.stream(onlyFromPackages) .anyMatch(p -> classMatchesPackage(ci.getName(), p))); return classInfoList.loadClasses().stream().collect(toSet()); }
.anyMatch(c.getName()::startsWith);
@Override protected String getClassName() { return classInfo != null ? classInfo.getName() : null; }
/** * Merge a {@link ClassInfo} object for a package-info.class file into this PackageInfo. (The same * package-info.class file may be present in multiple definitions of the package in different modules.) */ void addClassInfo(final ClassInfo classInfo) { memberClassNameToClassInfo.put(classInfo.getName(), classInfo); }
/** * Get the {@link ClassInfo} object for the named class in this module, or null if the class was not found in * this module. */ public ClassInfo getClassInfo(final String className) { if (classInfoSet == null) { return null; } for (final ClassInfo ci : classInfoSet) { if (ci.getName().equals(className)) { return ci; } } return null; }
private static Stream<Class<?>> loadClass(ClassInfo classInfo, Class superType) { try { return Stream.of(Class.forName(classInfo.getName(), true, superType.getClassLoader())); } catch (ClassNotFoundException e) { log.warn(String.format("Auto discovered class %s could not be loaded using the same loader that loaded %s." + " Trying other loaders... For details see %s", classInfo.getName(), superType.getName(), Urls.Errors.IMPLEMENTATION_CLASS_LOADING_FAILED)); } try { return Stream.of(classInfo.loadClass()); } catch (Exception e) { log.error("Auto discovered type " + classInfo.getName() + " failed to load and will be ignored", e); return Stream.empty(); } }
/** * Get the single direct superclass of this class, or null if none. Does not return the superinterfaces, if this * is an interface (use {@link #getInterfaces()} to get superinterfaces of an interface.} * * @return the superclass of this class, or null if none. */ public ClassInfo getSuperclass() { final Set<ClassInfo> superClasses = relatedClasses.get(RelType.SUPERCLASSES); if (superClasses == null || superClasses.isEmpty()) { return null; } else if (superClasses.size() > 2) { throw new IllegalArgumentException("More than one superclass: " + superClasses); } else { final ClassInfo superclass = superClasses.iterator().next(); if (superclass.getName().equals("java.lang.Object")) { return null; } else { return superclass; } } }
/** * @return A list of {@link AnnotationParameterValue} objects for each of the default parameter values for this * annotation, if this is an annotation class with default parameter values, otherwise the empty list. */ public AnnotationParameterValueList getAnnotationDefaultParameterValues() { if (!scanResult.scanSpec.enableAnnotationInfo) { throw new IllegalArgumentException("Please call ClassGraph#enableAnnotationInfo() before #scan()"); } if (!isAnnotation) { throw new IllegalArgumentException("Class is not an annotation: " + getName()); } if (annotationDefaultParamValues == null) { return AnnotationParameterValueList.EMPTY_LIST; } if (!annotationDefaultParamValuesHasBeenConvertedToPrimitive) { annotationDefaultParamValues.convertWrapperArraysToPrimitiveArrays(this); annotationDefaultParamValuesHasBeenConvertedToPrimitive = true; } return annotationDefaultParamValues; }
/** * @return the list of the classes (and their subclasses) that implement this interface, if this is an * interface, otherwise returns the empty list. */ public ClassInfoList getClassesImplementing() { if (!isInterface) { throw new IllegalArgumentException("Class is not an interface: " + getName()); } // Subclasses of implementing classes also implement the interface final ReachableAndDirectlyRelatedClasses implementingClasses = this .filterClassInfo(RelType.CLASSES_IMPLEMENTING, /* strictWhitelist = */ !isExternalClass); final Set<ClassInfo> allImplementingClasses = new LinkedHashSet<>(implementingClasses.reachableClasses); for (final ClassInfo implementingClass : implementingClasses.reachableClasses) { final Set<ClassInfo> implementingSubclasses = implementingClass.filterClassInfo(RelType.SUBCLASSES, /* strictWhitelist = */ !implementingClass.isExternalClass).reachableClasses; allImplementingClasses.addAll(implementingSubclasses); } return new ClassInfoList(allImplementingClasses, implementingClasses.directlyRelatedClasses, /* sortByName = */ true); }
/** * Resolves the {@link Class}[] of the {@code HandlesTypes}-annotations present on the given * {@code ServletContainerInitializer} implementation. * * @param servletContainerInitializerClassInfo The {@link ClassInfo} object representing the {@code ServletContainerInitializer} implementation * @return The classes listed in the {@code HandlesTypes} annotation of the given class. */ private List<ClassInfo> resolveHandledTypes(ClassInfo servletContainerInitializerClassInfo) { AnnotationInfo handlesTypes = servletContainerInitializerClassInfo.getAnnotationInfo(HANDLES_TYPES); Object[] value = (Object[]) handlesTypes.getParameterValues().get("value"); return Arrays.stream(value) .map(AnnotationClassRef.class::cast) .map(annotationClassRef -> { ClassInfo classInfo = annotationClassRef.getClassInfo(); if (classInfo == null) { log.warn("{} not found in the scan result, but declared in the @HandlesTypes annotation of {}", annotationClassRef.getName(), servletContainerInitializerClassInfo.getName()); } return classInfo; }) .filter(Objects::nonNull) .collect(Collectors.toList()); }
/** * Get the subclasses of this class, sorted in order of name. Call {@link ClassInfoList#directOnly()} to get * direct subclasses. * * @return the list of subclasses of this class, or the empty list if none. */ public ClassInfoList getSubclasses() { if (getName().equals("java.lang.Object")) { // Make an exception for querying all subclasses of java.lang.Object return scanResult.getAllClasses(); } else { return new ClassInfoList( this.filterClassInfo(RelType.SUBCLASSES, /* strictWhitelist = */ !isExternalClass), /* sortByName = */ true); } }
/** * @return A list of standard classes and non-annotation interfaces that are annotated by this class, if this is * an annotation class, or the empty list if none. Also handles the {@link Inherited} meta-annotation, * which causes an annotation on a class to be inherited by all of its subclasses. */ public ClassInfoList getClassesWithAnnotation() { if (!scanResult.scanSpec.enableAnnotationInfo) { throw new IllegalArgumentException("Please call ClassGraph#enableAnnotationInfo() before #scan()"); } if (!isAnnotation) { throw new IllegalArgumentException("Class is not an annotation: " + getName()); } // Get classes that have this annotation final ReachableAndDirectlyRelatedClasses classesWithAnnotation = this .filterClassInfo(RelType.CLASSES_WITH_ANNOTATION, /* strictWhitelist = */ !isExternalClass); if (isInherited) { // If this is an inherited annotation, add into the result all subclasses of the annotated classes. final Set<ClassInfo> classesWithAnnotationAndTheirSubclasses = new LinkedHashSet<>( classesWithAnnotation.reachableClasses); for (final ClassInfo classWithAnnotation : classesWithAnnotation.reachableClasses) { classesWithAnnotationAndTheirSubclasses.addAll(classWithAnnotation.getSubclasses()); } return new ClassInfoList(classesWithAnnotationAndTheirSubclasses, classesWithAnnotation.directlyRelatedClasses, /* sortByName = */ true); } else { // If not inherited, only return the annotated classes return new ClassInfoList(classesWithAnnotation, /* sortByName = */ true); } }
buf.append(name); final ClassInfo superclass = getSuperclass(); if (superclass != null && !superclass.getName().equals("java.lang.Object")) { buf.append(" extends ").append(superclass.toString(/* typeNameOnly = */ true));
/** Find the transitive closure of meta-annotations. */ private static void findMetaAnnotations(final AnnotationInfo ai, final AnnotationInfoList allAnnotationsOut, final Set<ClassInfo> visited) { final ClassInfo annotationClassInfo = ai.getClassInfo(); if (annotationClassInfo != null && annotationClassInfo.annotationInfo != null) { // Don't get in a cycle if (visited.add(annotationClassInfo)) { for (final AnnotationInfo metaAnnotationInfo : annotationClassInfo.annotationInfo) { final ClassInfo metaAnnotationClassInfo = metaAnnotationInfo.getClassInfo(); final String metaAnnotationClassName = metaAnnotationClassInfo.getName(); // Don't treat java.lang.annotation annotations as meta-annotations if (!metaAnnotationClassName.startsWith("java.lang.annotation.")) { // Add the meta-annotation to the transitive closure allAnnotationsOut.add(metaAnnotationInfo); // Recurse to meta-meta-annotation findMetaAnnotations(metaAnnotationInfo, allAnnotationsOut, visited); } } } } }
/** * Load the class named returned by {@link #getClassInfo()}, or if that returns null, the class named by * {@link #getClassName()}. Returns a {@code Class<?>} reference for the class. * * @param ignoreExceptions * If true, ignore classloading exceptions and return null on failure. * @return The {@code Class<?>} reference for the referenced class, or null if the class could not be loaded and * ignoreExceptions is true. * @throws IllegalArgumentException * if the class could not be loaded and ignoreExceptions was false. */ Class<?> loadClass(final boolean ignoreExceptions) { if (classRef == null) { String className; final ClassInfo classInfo = getClassInfo(); if (classInfo != null) { // Get class name from getClassInfo().getName() className = classInfo.getName(); } else { // Get class name from getClassName() className = getClassName(); } if (className == null) { throw new IllegalArgumentException("Class name is not set"); } classRef = scanResult.loadClass(className, ignoreExceptions); } return classRef; }
@Override public String toString() { return toString(classInfo.getName(), /* typeNameOnly = */ false, classInfo.getModifiers(), classInfo.isAnnotation(), classInfo.isInterface()); } }
if (classInfo != null) { className = classInfo.getName(); } else {
@Override public void handle(ScanResult scanResult, File joinfacesBaseDir) throws IOException { ClassInfoList scis = scanResult.getClassesImplementing(SERVLET_CONTAINER_INITIALIZER) .filter(classInfo -> classInfo.hasAnnotation(HANDLES_TYPES)); for (ClassInfo sciClassInfo : scis) { List<ClassInfo> handledTypes = resolveHandledTypes(sciClassInfo); SortedSet<String> classes = findHandledClasses(scanResult, handledTypes); File resultFile = new File(joinfacesBaseDir, sciClassInfo.getName() + ".classes"); writeClassList(resultFile, classes); } }
String name = handledType.getName();