1616
1717package org .springframework .boot .build .autoconfigure ;
1818
19- import java .io .File ;
20- import java .io .IOException ;
21- import java .nio .file .Files ;
22- import java .nio .file .Path ;
2319import java .util .Collections ;
24- import java .util .List ;
20+ import java .util .Map ;
2521
26- import com .tngtech .archunit .core .domain .JavaClass ;
27- import com .tngtech .archunit .core .domain .JavaModifier ;
28- import com .tngtech .archunit .lang .ArchCondition ;
29- import com .tngtech .archunit .lang .ArchRule ;
30- import com .tngtech .archunit .lang .ConditionEvents ;
31- import com .tngtech .archunit .lang .SimpleConditionEvent ;
32- import com .tngtech .archunit .lang .syntax .ArchRuleDefinition ;
3322import org .gradle .api .Plugin ;
3423import org .gradle .api .Project ;
3524import org .gradle .api .artifacts .Configuration ;
3625import org .gradle .api .plugins .JavaPlugin ;
3726import org .gradle .api .plugins .JavaPluginExtension ;
38- import org .gradle .api .provider .Provider ;
39- import org .gradle .api .tasks .PathSensitivity ;
4027import org .gradle .api .tasks .SourceSet ;
28+ import org .gradle .api .tasks .TaskProvider ;
4129
4230import org .springframework .boot .build .DeployedPlugin ;
43- import org .springframework .boot .build .architecture .ArchitectureCheck ;
4431import org .springframework .boot .build .architecture .ArchitecturePlugin ;
32+ import org .springframework .boot .build .optional .OptionalDependenciesPlugin ;
4533
4634/**
4735 * {@link Plugin} for projects that define auto-configuration. When applied, the plugin
@@ -71,14 +59,16 @@ public class AutoConfigurationPlugin implements Plugin<Project> {
7159 */
7260 public static final String AUTO_CONFIGURATION_METADATA_CONFIGURATION_NAME = "autoConfigurationMetadata" ;
7361
74- private static final String AUTO_CONFIGURATION_IMPORTS_PATH = "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports" ;
75-
7662 @ Override
7763 public void apply (Project project ) {
7864 project .getPlugins ().apply (DeployedPlugin .class );
7965 project .getPlugins ().withType (JavaPlugin .class , (javaPlugin ) -> {
8066 Configuration annotationProcessors = project .getConfigurations ()
8167 .getByName (JavaPlugin .ANNOTATION_PROCESSOR_CONFIGURATION_NAME );
68+ SourceSet main = project .getExtensions ()
69+ .getByType (JavaPluginExtension .class )
70+ .getSourceSets ()
71+ .getByName (SourceSet .MAIN_SOURCE_SET_NAME );
8272 annotationProcessors .getDependencies ()
8373 .add (project .getDependencies ()
8474 .project (Collections .singletonMap ("path" ,
@@ -88,10 +78,6 @@ public void apply(Project project) {
8878 .project (Collections .singletonMap ("path" ,
8979 ":spring-boot-project:spring-boot-tools:spring-boot-configuration-processor" )));
9080 project .getTasks ().register ("autoConfigurationMetadata" , AutoConfigurationMetadata .class , (task ) -> {
91- SourceSet main = project .getExtensions ()
92- .getByType (JavaPluginExtension .class )
93- .getSourceSets ()
94- .getByName (SourceSet .MAIN_SOURCE_SET_NAME );
9581 task .setSourceSet (main );
9682 task .dependsOn (main .getClassesTaskName ());
9783 task .getOutputFile ()
@@ -100,76 +86,37 @@ public void apply(Project project) {
10086 .add (AutoConfigurationPlugin .AUTO_CONFIGURATION_METADATA_CONFIGURATION_NAME , task .getOutputFile (),
10187 (artifact ) -> artifact .builtBy (task ));
10288 });
89+ project .getTasks ()
90+ .register ("checkAutoConfigurationImports" , CheckAutoConfigurationImports .class , (task ) -> {
91+ task .setSource (main .getResources ());
92+ task .setClasspath (main .getOutput ().getClassesDirs ());
93+ task .setDescription ("Checks the %s file of the main source set."
94+ .formatted (AutoConfigurationImportsTask .IMPORTS_FILE ));
95+ });
96+ Configuration requiredClasspath = project .getConfigurations ()
97+ .create ("autoConfigurationRequiredClasspath" )
98+ .extendsFrom (project .getConfigurations ().getByName (main .getImplementationConfigurationName ()),
99+ project .getConfigurations ().getByName (main .getRuntimeOnlyConfigurationName ()));
100+ requiredClasspath .getDependencies ()
101+ .add (project .getDependencies ()
102+ .project (Map .of ("path" , ":spring-boot-project:spring-boot-autoconfigure" )));
103+ TaskProvider <CheckAutoConfigurationClasses > checkAutoConfigurationClasses = project .getTasks ()
104+ .register ("checkAutoConfigurationClasses" , CheckAutoConfigurationClasses .class , (task ) -> {
105+ task .setSource (main .getResources ());
106+ task .setClasspath (main .getOutput ().getClassesDirs ());
107+ task .setRequiredDependencies (requiredClasspath );
108+ task .setDescription ("Checks the auto-configuration classes of the main source set." );
109+ });
103110 project .getPlugins ()
104- .withType (ArchitecturePlugin .class , (plugin ) -> configureArchitecturePluginTasks (project ));
105- });
106- }
107-
108- private void configureArchitecturePluginTasks (Project project ) {
109- project .getTasks ().configureEach ((task ) -> {
110- if ("checkArchitectureMain" .equals (task .getName ()) && task instanceof ArchitectureCheck architectureCheck ) {
111- configureCheckArchitectureMain (project , architectureCheck );
112- }
111+ .withType (OptionalDependenciesPlugin .class ,
112+ (plugin ) -> checkAutoConfigurationClasses .configure ((check ) -> {
113+ Configuration optionalClasspath = project .getConfigurations ()
114+ .create ("autoConfigurationOptionalClassPath" )
115+ .extendsFrom (project .getConfigurations ()
116+ .getByName (OptionalDependenciesPlugin .OPTIONAL_CONFIGURATION_NAME ));
117+ check .setOptionalDependencies (optionalClasspath );
118+ }));
113119 });
114120 }
115121
116- private void configureCheckArchitectureMain (Project project , ArchitectureCheck architectureCheck ) {
117- SourceSet main = project .getExtensions ()
118- .getByType (JavaPluginExtension .class )
119- .getSourceSets ()
120- .getByName (SourceSet .MAIN_SOURCE_SET_NAME );
121- File resourcesDirectory = main .getOutput ().getResourcesDir ();
122- architectureCheck .dependsOn (main .getProcessResourcesTaskName ());
123- architectureCheck .getInputs ()
124- .files (resourcesDirectory )
125- .optional ()
126- .withPathSensitivity (PathSensitivity .RELATIVE );
127- architectureCheck .getRules ()
128- .add (allConcreteClassesAnnotatedWithAutoConfigurationShouldBeListedInAutoConfigurationImports (
129- autoConfigurationImports (project , resourcesDirectory )));
130- }
131-
132- private ArchRule allConcreteClassesAnnotatedWithAutoConfigurationShouldBeListedInAutoConfigurationImports (
133- Provider <AutoConfigurationImports > imports ) {
134- return ArchRuleDefinition .classes ()
135- .that ()
136- .doNotHaveModifier (JavaModifier .ABSTRACT )
137- .and ()
138- .areAnnotatedWith ("org.springframework.boot.autoconfigure.AutoConfiguration" )
139- .should (beListedInAutoConfigurationImports (imports ))
140- .allowEmptyShould (true );
141- }
142-
143- private ArchCondition <JavaClass > beListedInAutoConfigurationImports (Provider <AutoConfigurationImports > imports ) {
144- return new ArchCondition <>("be listed in " + AUTO_CONFIGURATION_IMPORTS_PATH ) {
145-
146- @ Override
147- public void check (JavaClass item , ConditionEvents events ) {
148- AutoConfigurationImports autoConfigurationImports = imports .get ();
149- if (!autoConfigurationImports .imports .contains (item .getName ())) {
150- events .add (SimpleConditionEvent .violated (item ,
151- item .getName () + " was not listed in " + autoConfigurationImports .importsFile ));
152- }
153- }
154-
155- };
156- }
157-
158- private Provider <AutoConfigurationImports > autoConfigurationImports (Project project , File resourcesDirectory ) {
159- Path importsFile = new File (resourcesDirectory , AUTO_CONFIGURATION_IMPORTS_PATH ).toPath ();
160- return project .provider (() -> {
161- try {
162- return new AutoConfigurationImports (project .getProjectDir ().toPath ().relativize (importsFile ),
163- Files .readAllLines (importsFile ));
164- }
165- catch (IOException ex ) {
166- throw new RuntimeException ("Failed to read AutoConfiguration.imports" , ex );
167- }
168- });
169- }
170-
171- private record AutoConfigurationImports (Path importsFile , List <String > imports ) {
172-
173- }
174-
175122}
0 commit comments