From d7b43a3c687f89529c91da8ed039b90df2b5d93c Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Apr 2021 15:07:51 +0100 Subject: [PATCH] Filter out non-public classes when documenting auto-config classes Fixes gh-25948 --- .../AutoConfigurationMetadata.java | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/AutoConfigurationMetadata.java b/buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/AutoConfigurationMetadata.java index 0eaa01055eb..724dbf6500a 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/AutoConfigurationMetadata.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/AutoConfigurationMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,11 +17,15 @@ package org.springframework.boot.build.autoconfigure; import java.io.File; +import java.io.FileInputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.io.InputStream; import java.io.Reader; +import java.util.LinkedHashSet; import java.util.Properties; +import java.util.Set; import java.util.concurrent.Callable; import org.gradle.api.DefaultTask; @@ -30,7 +34,10 @@ import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.TaskAction; +import org.springframework.asm.ClassReader; +import org.springframework.asm.Opcodes; import org.springframework.core.CollectionFactory; +import org.springframework.util.StringUtils; /** * A {@link Task} for generating metadata describing a project's auto-configuration @@ -78,12 +85,38 @@ public class AutoConfigurationMetadata extends DefaultTask { Properties autoConfiguration = CollectionFactory.createSortedProperties(true); Properties springFactories = readSpringFactories( new File(this.sourceSet.getOutput().getResourcesDir(), "META-INF/spring.factories")); - autoConfiguration.setProperty("autoConfigurationClassNames", - springFactories.getProperty("org.springframework.boot.autoconfigure.EnableAutoConfiguration")); + String enableAutoConfiguration = springFactories + .getProperty("org.springframework.boot.autoconfigure.EnableAutoConfiguration"); + Set classNames = StringUtils.commaDelimitedListToSet(enableAutoConfiguration); + Set publicClassNames = new LinkedHashSet<>(); + for (String className : classNames) { + File classFile = findClassFile(className); + if (classFile == null) { + throw new IllegalStateException("Auto-configuration class '" + className + "' not found."); + } + try (InputStream in = new FileInputStream(classFile)) { + int access = new ClassReader(in).getAccess(); + if ((access & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC) { + publicClassNames.add(className); + } + } + } + autoConfiguration.setProperty("autoConfigurationClassNames", String.join(",", publicClassNames)); autoConfiguration.setProperty("module", getProject().getName()); return autoConfiguration; } + private File findClassFile(String className) { + String classFileName = className.replace(".", "/") + ".class"; + for (File classesDir : this.sourceSet.getOutput().getClassesDirs()) { + File classFile = new File(classesDir, classFileName); + if (classFile.isFile()) { + return classFile; + } + } + return null; + } + private Properties readSpringFactories(File file) throws IOException { Properties springFactories = new Properties(); try (Reader in = new FileReader(file)) {