Skip to content

Commit 5baa6d9

Browse files
committed
Use ClassLoader with ArchitectureCheck
Prior to this commit, certain rules, like BeanPostProcessor, did not work with external classes. This commit ensures that ArchRules are executed within a context ClassLoader that includes all classes from the compile classpath. Signed-off-by: Dmytro Nosan <[email protected]>
1 parent b537b5a commit 5baa6d9

File tree

2 files changed

+28
-107
lines changed

2 files changed

+28
-107
lines changed

buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitectureCheck.java

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@
1818

1919
import java.io.File;
2020
import java.io.IOException;
21+
import java.net.URL;
22+
import java.net.URLClassLoader;
2123
import java.nio.file.Files;
2224
import java.nio.file.Path;
2325
import java.nio.file.StandardOpenOption;
26+
import java.util.ArrayList;
2427
import java.util.Collections;
2528
import java.util.List;
29+
import java.util.concurrent.Callable;
2630
import java.util.function.Supplier;
2731
import java.util.stream.Stream;
2832

29-
import com.tngtech.archunit.ArchConfiguration;
3033
import com.tngtech.archunit.core.domain.JavaClasses;
3134
import com.tngtech.archunit.core.importer.ClassFileImporter;
3235
import com.tngtech.archunit.lang.ArchRule;
@@ -84,17 +87,16 @@ private List<String> asDescriptions(List<ArchRule> rules) {
8487
}
8588

8689
@TaskAction
87-
void checkArchitecture() {
88-
ArchConfiguration.withThreadLocalScope((configuration) -> {
89-
configuration.setClassResolver(CompileClasspathClassResolver.class);
90-
configuration.setProperty(CompileClasspathClassResolver.PROPERTY_NAME, getCompileClasspath().getAsPath());
90+
void checkArchitecture() throws Exception {
91+
withCompileClasspath(() -> {
9192
JavaClasses javaClasses = new ClassFileImporter().importPaths(classFilesPaths());
9293
List<EvaluationResult> violations = evaluate(javaClasses).filter(EvaluationResult::hasViolation).toList();
9394
File outputFile = getOutputDirectory().file("failure-report.txt").get().getAsFile();
9495
writeViolationReport(violations, outputFile);
9596
if (!violations.isEmpty()) {
9697
throw new VerificationException("Architecture check failed. See '" + outputFile + "' for details.");
9798
}
99+
return null;
98100
});
99101
}
100102

@@ -106,23 +108,33 @@ private Stream<EvaluationResult> evaluate(JavaClasses javaClasses) {
106108
return getRules().get().stream().map((rule) -> rule.evaluate(javaClasses));
107109
}
108110

109-
private void writeViolationReport(List<EvaluationResult> violations, File outputFile) {
111+
private void withCompileClasspath(Callable<?> callable) throws Exception {
112+
ClassLoader previous = Thread.currentThread().getContextClassLoader();
110113
try {
111-
Files.createDirectories(outputFile.getParentFile().toPath());
112-
StringBuilder report = new StringBuilder();
113-
for (EvaluationResult violation : violations) {
114-
report.append(violation.getFailureReport());
115-
report.append(String.format("%n"));
114+
List<URL> urls = new ArrayList<>();
115+
for (File file : getCompileClasspath().getFiles()) {
116+
urls.add(file.toURI().toURL());
116117
}
117-
Files.writeString(outputFile.toPath(), report.toString(), StandardOpenOption.CREATE,
118-
StandardOpenOption.TRUNCATE_EXISTING);
118+
ClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[0]), getClass().getClassLoader());
119+
Thread.currentThread().setContextClassLoader(classLoader);
120+
callable.call();
119121
}
120-
catch (IOException ex) {
121-
throw new VerificationException(
122-
"Failed to write violation report to '" + outputFile + "' " + ex.getMessage());
122+
finally {
123+
Thread.currentThread().setContextClassLoader(previous);
123124
}
124125
}
125126

127+
private void writeViolationReport(List<EvaluationResult> violations, File outputFile) throws IOException {
128+
Files.createDirectories(outputFile.getParentFile().toPath());
129+
StringBuilder report = new StringBuilder();
130+
for (EvaluationResult violation : violations) {
131+
report.append(violation.getFailureReport());
132+
report.append(String.format("%n"));
133+
}
134+
Files.writeString(outputFile.toPath(), report.toString(), StandardOpenOption.CREATE,
135+
StandardOpenOption.TRUNCATE_EXISTING);
136+
}
137+
126138
public void setClasses(FileCollection classes) {
127139
this.classes = classes;
128140
}

buildSrc/src/main/java/org/springframework/boot/build/architecture/CompileClasspathClassResolver.java

Lines changed: 0 additions & 91 deletions
This file was deleted.

0 commit comments

Comments
 (0)