Redesign AOT processors for consistency and simplification
There's currently a considerable amount of overlap between the implementations of AotProcessor and TestAotProcessor. In addition AotProcessor is abstract and does not include a main() method; whereas, TestAotProcessor is concrete and does include a main() method. To address these issues, this commit: - Introduces an AbstractAotProcessor base class that AotProcessor and TestAotProcessor now both extend - Moves common properties/functionality to AbstractAotProcessor - Renames AotProcessor to ContextAotProcessor - Makes TestAotProcessor abstract like ContextAotProcessor - Removes the main() method from TestAotProcessor Closes gh-29266
This commit is contained in:
@@ -16,52 +16,29 @@
|
||||
|
||||
package org.springframework.test.context.aot;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.aot.generate.FileSystemGeneratedFiles;
|
||||
import org.springframework.aot.generate.GeneratedFiles;
|
||||
import org.springframework.aot.generate.GeneratedFiles.Kind;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.nativex.FileNativeConfigurationWriter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
import org.springframework.context.aot.AbstractAotProcessor;
|
||||
|
||||
/**
|
||||
* Filesystem-based ahead-of-time (AOT) processing base implementation that scans
|
||||
* the provided classpath roots for Spring integration test classes and then
|
||||
* generates AOT artifacts for those test classes in the configured output directories.
|
||||
*
|
||||
* <p>Typically used in a build tool.
|
||||
* <p>Concrete implementations are typically used to kick off optimization of a
|
||||
* test suite in a build tool.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @author Stephane Nicoll
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 6.0
|
||||
* @see TestContextAotGenerator
|
||||
* @see FileNativeConfigurationWriter
|
||||
* @see org.springframework.context.aot.AotProcessor
|
||||
* @see org.springframework.context.aot.ContextAotProcessor
|
||||
*/
|
||||
public class TestAotProcessor {
|
||||
public abstract class TestAotProcessor extends AbstractAotProcessor {
|
||||
|
||||
private final Path[] classpathRoots;
|
||||
|
||||
private final Path sourceOutput;
|
||||
|
||||
private final Path resourceOutput;
|
||||
|
||||
private final Path classOutput;
|
||||
|
||||
private final String groupId;
|
||||
|
||||
private final String artifactId;
|
||||
private final Set<Path> classpathRoots;
|
||||
|
||||
|
||||
/**
|
||||
@@ -76,15 +53,11 @@ public class TestAotProcessor {
|
||||
* @param artifactId the artifact ID of the application, used to locate
|
||||
* {@code native-image.properties}
|
||||
*/
|
||||
public TestAotProcessor(Path[] classpathRoots, Path sourceOutput, Path resourceOutput, Path classOutput,
|
||||
public TestAotProcessor(Set<Path> classpathRoots, Path sourceOutput, Path resourceOutput, Path classOutput,
|
||||
String groupId, String artifactId) {
|
||||
|
||||
super(sourceOutput, resourceOutput, classOutput, groupId, artifactId);
|
||||
this.classpathRoots = classpathRoots;
|
||||
this.sourceOutput = sourceOutput;
|
||||
this.resourceOutput = resourceOutput;
|
||||
this.classOutput = classOutput;
|
||||
this.groupId = groupId;
|
||||
this.artifactId = artifactId;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,24 +71,6 @@ public class TestAotProcessor {
|
||||
performAotProcessing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the source, resource, and class output directories.
|
||||
*/
|
||||
protected void deleteExistingOutput() {
|
||||
deleteExistingOutput(this.sourceOutput, this.resourceOutput, this.classOutput);
|
||||
}
|
||||
|
||||
private void deleteExistingOutput(Path... paths) {
|
||||
for (Path path : paths) {
|
||||
try {
|
||||
FileSystemUtils.deleteRecursively(path);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException("Failed to delete existing output in '%s'".formatted(path), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform ahead-of-time processing of Spring integration test classes.
|
||||
* <p>Code, resources, and generated classes are stored in the configured
|
||||
@@ -124,43 +79,14 @@ public class TestAotProcessor {
|
||||
* components used by the tests.
|
||||
*/
|
||||
protected void performAotProcessing() {
|
||||
TestClassScanner scanner = new TestClassScanner(Set.of(this.classpathRoots));
|
||||
TestClassScanner scanner = new TestClassScanner(this.classpathRoots);
|
||||
Stream<Class<?>> testClasses = scanner.scan();
|
||||
|
||||
GeneratedFiles generatedFiles = new FileSystemGeneratedFiles(this::getRoot);
|
||||
GeneratedFiles generatedFiles = createFileSystemGeneratedFiles();
|
||||
TestContextAotGenerator generator = new TestContextAotGenerator(generatedFiles);
|
||||
generator.processAheadOfTime(testClasses);
|
||||
|
||||
writeHints(generator.getRuntimeHints());
|
||||
}
|
||||
|
||||
private Path getRoot(Kind kind) {
|
||||
return switch (kind) {
|
||||
case SOURCE -> this.sourceOutput;
|
||||
case RESOURCE -> this.resourceOutput;
|
||||
case CLASS -> this.classOutput;
|
||||
};
|
||||
}
|
||||
|
||||
private void writeHints(RuntimeHints hints) {
|
||||
FileNativeConfigurationWriter writer =
|
||||
new FileNativeConfigurationWriter(this.resourceOutput, this.groupId, this.artifactId);
|
||||
writer.write(hints);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
int requiredArgs = 6;
|
||||
Assert.isTrue(args.length >= requiredArgs, () ->
|
||||
"Usage: %s <classpathRoots> <sourceOutput> <resourceOutput> <classOutput> <groupId> <artifactId>"
|
||||
.formatted(TestAotProcessor.class.getName()));
|
||||
Path[] classpathRoots = Arrays.stream(args[0].split(File.pathSeparator)).map(Paths::get).toArray(Path[]::new);
|
||||
Path sourceOutput = Paths.get(args[1]);
|
||||
Path resourceOutput = Paths.get(args[2]);
|
||||
Path classOutput = Paths.get(args[3]);
|
||||
String groupId = args[4];
|
||||
String artifactId = args[5];
|
||||
new TestAotProcessor(classpathRoots, sourceOutput, resourceOutput, classOutput, groupId, artifactId).process();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user