public ClasspathScanningPrimitiveTypeRegistry(ClassLoader classLoader) { Map<String, PrimitiveType> types = CACHE.computeIfAbsent(classLoader, cl -> { final Map<String, PrimitiveType> result = new ConcurrentHashMap<>(); final String[] whitelistPackages = StringUtils.split(System.getProperty("io.atomix.whitelistPackages"), ","); final ClassGraph classGraph = whitelistPackages != null ? new ClassGraph().enableClassInfo().whitelistPackages(whitelistPackages).addClassLoader(classLoader) : new ClassGraph().enableClassInfo().addClassLoader(classLoader); try (final ScanResult scanResult = classGraph.scan()) { scanResult.getClassesImplementing(PrimitiveType.class.getName()).forEach(classInfo -> { if (classInfo.isInterface() || classInfo.isAbstract() || Modifier.isPrivate(classInfo.getModifiers())) { return; } final PrimitiveType primitiveType = newInstance(classInfo.loadClass()); final PrimitiveType oldPrimitiveType = result.put(primitiveType.name(), primitiveType); if (oldPrimitiveType != null) { LOGGER.warn("Found multiple primitives types name={}, classes=[{}, {}]", primitiveType.name(), oldPrimitiveType.getClass().getName(), primitiveType.getClass().getName()); } }); } return Collections.unmodifiableMap(result); }); primitiveTypes.putAll(types); }
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()); }
if (includeExternalClasses) { for (final ClassInfo ci : classInfoList) { allVisibleNodes.addAll(ci.getClassDependencies()); buf.append("\"").append(ci.getName()).append("\""); buf.append("[shape=").append(ci.isAnnotation() ? "oval" : ci.isInterface() ? "diamond" : "box") .append(",style=filled,fillcolor=\"#").append(ci.isAnnotation() ? ANNOTATION_COLOR : ci.isInterface() ? INTERFACE_COLOR : STANDARD_CLASS_COLOR) .append("\",label="); buf.append("<"); buf.append("<tr><td><font point-size='12'>").append(ci.getModifiersStr()).append(" ") .append(ci.isEnum() ? "enum" : ci.isAnnotation() ? "@interface" : ci.isInterface() ? "interface" : "class") .append("</font></td></tr>"); if (ci.getName().contains(".")) { buf.append("<tr><td><font point-size='14'><b>"); htmlEncode(ci.getPackageName(), buf); buf.append("</b></font></td></tr>"); htmlEncode(ci.getSimpleName(), buf); buf.append("</b></font></td></tr>"); buf.append("</table>"); for (final ClassInfo dep : ci.getClassDependencies()) { if (includeExternalClasses || allVisibleNodes.contains(dep)) { buf.append(" \"").append(ci.getName()).append("\" -> \"").append(dep.getName())
deployment.getRegistry().addPerInstanceResource(classInfo.loadClass(), "/v1"); });
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()); }
ClassInfoList csvList = scanResult.getClassesWithAnnotation(CsvMarshaller.class.getCanonicalName()); for (ClassInfo csvClassInfo : csvList) { final Class<?> csvClass = csvClassInfo.loadClass(); AnnotationInfo annotationInfo = csvClassInfo.getAnnotationInfo(Disabled.class.getCanonicalName()); if (annotationInfo == null) { LOGGER.info("Fluxtion generating CSV marshaller for:" + csvClass.getCanonicalName()); CsvToBeanBuilder beanBuilder = CsvToBeanBuilder.nameSpace(csvClassInfo.getPackageName()); if (generatedDir != null && resourceDir != null) { beanBuilder.setOutputDirs(generatedDir.getCanonicalPath(), resourceDir.getCanonicalPath()); beanBuilder.mapBean(csvClassInfo.getSimpleName(), csvClass); } else { LOGGER.info("disabled Fluxtion CSV generation for:" + csvClass.getCanonicalName());
@Override public String toString() { return toString(classInfo.getName(), /* typeNameOnly = */ false, classInfo.getModifiers(), classInfo.isAnnotation(), classInfo.isInterface()); } }
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(); } }
String name = handledType.getName(); if (handledType.isAnnotation()) { classes.addAll(scanResult.getClassesWithAnnotation(name).getNames()); classes.addAll(scanResult.getClassesWithMethodAnnotation(name).getNames()); classes.addAll(scanResult.getClassesWithFieldAnnotation(name).getNames()); else if (handledType.isInterface()) { classes.addAll(scanResult.getClassesImplementing(name).getNames());
/** * @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); }
classInfo.setScanResult(this); for (final ClassInfo ci : new ArrayList<>(classNameToClassInfo.values())) { final Set<ClassInfo> refdClasses = new HashSet<>(); for (final String refdClassName : ci.getReferencedClassNames()) { if (!ci.getName().equals(refdClassName)) { final ClassInfo refdClassInfo = ClassInfo.getOrCreateClassInfo(refdClassName, /* classModifiers are unknown */ 0, classNameToClassInfo); refdClassInfo.setScanResult(this); if (!refdClassInfo.isExternalClass() || scanSpec.enableExternalClasses) { ci.setReferencedClasses(new ClassInfoList(refdClasses, /* sortByName = */ true));
buf.append("\"").append(node.getName()).append("\""); labelClassNodeHTML(node, "box", STANDARD_CLASS_COLOR, showFields, showMethods, scanSpec, buf); buf.append(";\n"); buf.append("\"").append(node.getName()).append("\""); labelClassNodeHTML(node, "diamond", INTERFACE_COLOR, showFields, showMethods, scanSpec, buf); buf.append(";\n"); buf.append("\"").append(node.getName()).append("\""); labelClassNodeHTML(node, "oval", ANNOTATION_COLOR, showFields, showMethods, scanSpec, buf); buf.append(";\n"); for (final ClassInfo directSuperclassNode : classNode.getSuperclasses().directOnly()) { if (directSuperclassNode != null && allVisibleNodes.contains(directSuperclassNode.getName()) && !directSuperclassNode.getName().equals("java.lang.Object")) { buf.append(" \"").append(classNode.getName()).append("\" -> \"") .append(directSuperclassNode.getName()).append("\" [arrowsize=2.5]\n"); for (final ClassInfo implementedInterfaceNode : classNode.getInterfaces().directOnly()) { if (allVisibleNodes.contains(implementedInterfaceNode.getName())) { buf.append(" \"").append(classNode.getName()).append("\" -> \"") .append(implementedInterfaceNode.getName()) .append("\" [arrowhead=diamond, arrowsize=2.5]\n"); buf.append(" \"").append(fieldTypeName).append("\" -> \"").append(classNode.getName()) .append("\" [arrowtail=obox, arrowsize=2.5, dir=back]\n");
private static <T> List<Class<?>> searchForPublicConcreteSubTypesOf(final Class<T> type) { String typeName = type.getCanonicalName(); ClassInfoList subTypes = type.isInterface() ? scanResult.getClassesImplementing(typeName) : scanResult.getSubclasses(typeName); List<Class<?>> loadedSubTypes = subTypes.filter(subType -> subType.isPublic() && !subType.isAbstract()).loadClasses(true); return Collections.unmodifiableList(loadedSubTypes); } }
private String toString(final boolean typeNameOnly) { final ClassTypeSignature typeSig = getTypeSignature(); if (typeSig != null) { : isInterface ? "interface " : (modifiers & 0x4000) != 0 ? "enum " : "class "); buf.append(name); final ClassInfo superclass = getSuperclass(); if (superclass != null && !superclass.getName().equals("java.lang.Object")) { buf.append(" extends ").append(superclass.toString(/* typeNameOnly = */ true)); final Set<ClassInfo> interfaces = this.filterClassInfo(RelType.IMPLEMENTED_INTERFACES, /* strictWhitelist = */ false).directlyRelatedClasses; if (!interfaces.isEmpty()) { buf.append(", "); buf.append(iface.toString(/* typeNameOnly = */ 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()); }
/** * Returns true if this is a default method (i.e. if this is a method in an interface and the method has a * body). * * @return True if this is a default method. */ public boolean isDefault() { final ClassInfo classInfo = getClassInfo(); return classInfo != null && classInfo.isInterface() && hasBody; }
/** * @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); } }
/** Get the names of all classes refernenced by this class. */ Set<String> getReferencedClassNames() { // refdClassNames came from class refs and type signatures in the constant pool of the classfile, // but there are other sources of class refs and type signatures that are coded as CONSTANT_Utf8_info // (such as enum classes and class references in annotation parameter values), so these need to be // added to the set of referenced classes. if (referencedClassNames == null) { referencedClassNames = new HashSet<>(); } getAnnotationInfo().getReferencedClassNames(referencedClassNames); getMethodInfo().getReferencedClassNames(referencedClassNames); getFieldInfo().getReferencedClassNames(referencedClassNames); // Get rid of self-references and references to java.lang.Object referencedClassNames.remove(name); referencedClassNames.remove("java.lang.Object"); return referencedClassNames; }
@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); } }
/** * Get a the named annotation on this class, or null if the class does not have the named annotation. * * <p> * Also handles the {@link Inherited} meta-annotation, which causes an annotation to annotate a class and all of * its subclasses. * * <p> * Note that if you need to get multiple named annotations, it is faster to call {@link #getAnnotationInfo()}, * and then get the named annotations from the returned {@link AnnotationInfoList}, so that the returned list * doesn't have to be built multiple times. * * @param annotationName * The annotation name. * @return An {@link AnnotationInfo} object representing the named annotation on this class, or null if the * class does not have the named annotation. */ public AnnotationInfo getAnnotationInfo(final String annotationName) { return getAnnotationInfo().get(annotationName); }