Skip to content

Commit 96a7685

Browse files
committed
Merge branch 'main' into 4.0.x
2 parents fa4240a + a9b52c5 commit 96a7685

File tree

13 files changed

+692
-161
lines changed

13 files changed

+692
-161
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.build.autoconfigure;
18+
19+
import java.io.File;
20+
import java.io.FileInputStream;
21+
import java.io.IOException;
22+
import java.io.UncheckedIOException;
23+
import java.util.ArrayList;
24+
import java.util.Collections;
25+
import java.util.HashMap;
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.Objects;
29+
import java.util.Set;
30+
31+
import org.springframework.asm.AnnotationVisitor;
32+
import org.springframework.asm.ClassReader;
33+
import org.springframework.asm.ClassVisitor;
34+
import org.springframework.asm.SpringAsmInfo;
35+
import org.springframework.asm.Type;
36+
37+
/**
38+
* An {@code @AutoConfiguration} class.
39+
*
40+
* @param name name of the auto-configuration class
41+
* @param before values of the {@code before} attribute
42+
* @param beforeName values of the {@code beforeName} attribute
43+
* @param after values of the {@code after} attribute
44+
* @param afterName values of the {@code afterName} attribute
45+
* @author Andy Wilkinson
46+
*/
47+
public record AutoConfigurationClass(String name, List<String> before, List<String> beforeName, List<String> after,
48+
List<String> afterName) {
49+
50+
private AutoConfigurationClass(String name, Map<String, List<String>> attributes) {
51+
this(name, attributes.getOrDefault("before", Collections.emptyList()),
52+
attributes.getOrDefault("beforeName", Collections.emptyList()),
53+
attributes.getOrDefault("after", Collections.emptyList()),
54+
attributes.getOrDefault("afterName", Collections.emptyList()));
55+
}
56+
57+
static AutoConfigurationClass of(File classFile) {
58+
try (FileInputStream input = new FileInputStream(classFile)) {
59+
ClassReader classReader = new ClassReader(input);
60+
AutoConfigurationClassVisitor visitor = new AutoConfigurationClassVisitor();
61+
classReader.accept(visitor, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);
62+
return visitor.autoConfigurationClass;
63+
}
64+
catch (IOException ex) {
65+
throw new UncheckedIOException(ex);
66+
}
67+
}
68+
69+
private static final class AutoConfigurationClassVisitor extends ClassVisitor {
70+
71+
private AutoConfigurationClass autoConfigurationClass;
72+
73+
private String name;
74+
75+
private AutoConfigurationClassVisitor() {
76+
super(SpringAsmInfo.ASM_VERSION);
77+
}
78+
79+
@Override
80+
public void visit(int version, int access, String name, String signature, String superName,
81+
String[] interfaces) {
82+
this.name = Type.getObjectType(name).getClassName();
83+
}
84+
85+
@Override
86+
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
87+
String annotationClassName = Type.getType(descriptor).getClassName();
88+
if ("org.springframework.boot.autoconfigure.AutoConfiguration".equals(annotationClassName)) {
89+
return new AutoConfigurationAnnotationVisitor();
90+
}
91+
return null;
92+
}
93+
94+
private final class AutoConfigurationAnnotationVisitor extends AnnotationVisitor {
95+
96+
private Map<String, List<String>> attributes = new HashMap<>();
97+
98+
private static final Set<String> INTERESTING_ATTRIBUTES = Set.of("before", "beforeName", "after",
99+
"afterName");
100+
101+
private AutoConfigurationAnnotationVisitor() {
102+
super(SpringAsmInfo.ASM_VERSION);
103+
}
104+
105+
@Override
106+
public void visitEnd() {
107+
AutoConfigurationClassVisitor.this.autoConfigurationClass = new AutoConfigurationClass(
108+
AutoConfigurationClassVisitor.this.name, this.attributes);
109+
}
110+
111+
@Override
112+
public AnnotationVisitor visitArray(String attributeName) {
113+
if (INTERESTING_ATTRIBUTES.contains(attributeName)) {
114+
return new AnnotationVisitor(SpringAsmInfo.ASM_VERSION) {
115+
116+
@Override
117+
public void visit(String name, Object value) {
118+
if (value instanceof Type type) {
119+
value = type.getClassName();
120+
}
121+
AutoConfigurationAnnotationVisitor.this.attributes
122+
.computeIfAbsent(attributeName, (n) -> new ArrayList<>())
123+
.add(Objects.toString(value));
124+
}
125+
126+
};
127+
}
128+
return null;
129+
}
130+
131+
}
132+
133+
}
134+
135+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.build.autoconfigure;
18+
19+
import java.io.File;
20+
import java.io.IOException;
21+
import java.io.UncheckedIOException;
22+
import java.nio.file.Files;
23+
import java.util.List;
24+
25+
import org.gradle.api.DefaultTask;
26+
import org.gradle.api.Task;
27+
import org.gradle.api.file.FileCollection;
28+
import org.gradle.api.file.FileTree;
29+
import org.gradle.api.tasks.InputFiles;
30+
import org.gradle.api.tasks.PathSensitive;
31+
import org.gradle.api.tasks.PathSensitivity;
32+
import org.gradle.api.tasks.SkipWhenEmpty;
33+
34+
/**
35+
* A {@link Task} that uses a project's auto-configuration imports.
36+
*
37+
* @author Andy Wilkinson
38+
*/
39+
public abstract class AutoConfigurationImportsTask extends DefaultTask {
40+
41+
static final String IMPORTS_FILE = "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports";
42+
43+
private FileCollection sourceFiles = getProject().getObjects().fileCollection();
44+
45+
@InputFiles
46+
@SkipWhenEmpty
47+
@PathSensitive(PathSensitivity.RELATIVE)
48+
public FileTree getSource() {
49+
return this.sourceFiles.getAsFileTree().matching((filter) -> filter.include(IMPORTS_FILE));
50+
}
51+
52+
public void setSource(Object source) {
53+
this.sourceFiles = getProject().getObjects().fileCollection().from(source);
54+
}
55+
56+
protected List<String> loadImports() {
57+
File importsFile = getSource().getSingleFile();
58+
try {
59+
return Files.readAllLines(importsFile.toPath());
60+
}
61+
catch (IOException ex) {
62+
throw new UncheckedIOException(ex);
63+
}
64+
}
65+
66+
}

0 commit comments

Comments
 (0)