Merge branch '2.3.x'

Closes gh-21649
This commit is contained in:
Phillip Webb 2020-06-01 21:21:20 -07:00
commit ac9482d463

View File

@ -22,11 +22,13 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import io.spring.javaformat.formatter.FileEdit;
import io.spring.javaformat.formatter.FileFormatter;
import org.gradle.api.DefaultTask;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.file.CopySpec;
import org.gradle.api.plugins.JavaLibraryPlugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
@ -52,6 +54,7 @@ import org.springframework.boot.build.test.IntegrationTestPlugin;
* Plugin for building Spring Boot's Maven Plugin.
*
* @author Andy Wilkinson
* @author Phillip Webb
*/
public class MavenPluginPlugin implements Plugin<Project> {
@ -62,113 +65,150 @@ public class MavenPluginPlugin implements Plugin<Project> {
project.getPlugins().apply(DeployedPlugin.class);
project.getPlugins().apply(MavenRepositoryPlugin.class);
project.getPlugins().apply(IntegrationTestPlugin.class);
Copy populateIntTestMavenRepository = project.getTasks().create("populateIntTestMavenRepository", Copy.class);
populateIntTestMavenRepository.setDestinationDir(project.getBuildDir());
populateIntTestMavenRepository.into("int-test-maven-repository", (copy) -> {
copy.from(project.getConfigurations().getByName(MavenRepositoryPlugin.MAVEN_REPOSITORY_CONFIGURATION_NAME));
copy.from(new File(project.getBuildDir(), "maven-repository"));
});
populateIntTestMavenRepository
.dependsOn(project.getTasks().getByName(MavenRepositoryPlugin.PUBLISH_TO_PROJECT_REPOSITORY_TASK_NAME));
Jar jarTask = (Jar) project.getTasks().getByName(JavaPlugin.JAR_TASK_NAME);
configurePomPackaging(project);
MavenExec generateHelpMojo = configureMojoGenerationTasks(project);
MavenExec generatePluginDescriptor = configurePluginDescriptorGenerationTasks(project, generateHelpMojo);
DocumentPluginGoals documentPluginGoals = project.getTasks().create("documentPluginGoals",
DocumentPluginGoals.class);
documentPluginGoals.setPluginXml(generatePluginDescriptor.getOutputs().getFiles().getSingleFile());
documentPluginGoals.setOutputDir(new File(project.getBuildDir(), "docs/generated/goals/"));
documentPluginGoals.dependsOn(generatePluginDescriptor);
Jar jar = (Jar) project.getTasks().getByName(JavaPlugin.JAR_TASK_NAME);
includeDescriptorInJar(jar, generatePluginDescriptor);
includeHelpMojoInJar(jar, generateHelpMojo);
PrepareMavenBinaries prepareMavenBinaries = project.getTasks().create("prepareMavenBinaries",
PrepareMavenBinaries.class);
prepareMavenBinaries.setOutputDir(new File(project.getBuildDir(), "maven-binaries"));
project.getTasks().getByName(IntegrationTestPlugin.INT_TEST_TASK_NAME).dependsOn(populateIntTestMavenRepository,
prepareMavenBinaries);
addPopulateIntTestMavenRepositoryTask(project);
MavenExec generateHelpMojoTask = addGenerateHelpMojoTask(project, jarTask);
MavenExec generatePluginDescriptorTask = addGeneratePluginDescriptorTask(project, jarTask,
generateHelpMojoTask);
addDocumentPluginGoalsTask(project, generatePluginDescriptorTask);
addPrepareMavenBinariesTask(project);
}
private void configurePomPackaging(Project project) {
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
publishing.getPublications().withType(MavenPublication.class,
(mavenPublication) -> mavenPublication.pom((pom) -> pom.setPackaging("maven-plugin")));
publishing.getPublications().withType(MavenPublication.class, this::setPackaging);
}
private MavenExec configureMojoGenerationTasks(Project project) {
private void setPackaging(MavenPublication mavenPublication) {
mavenPublication.pom((pom) -> pom.setPackaging("maven-plugin"));
}
private void addPopulateIntTestMavenRepositoryTask(Project project) {
Copy task = project.getTasks().create("populateIntTestMavenRepository", Copy.class);
task.setDestinationDir(project.getBuildDir());
task.into("int-test-maven-repository", (copy) -> copyIntTestMavenRepositoryFiles(project, copy));
task.dependsOn(project.getTasks().getByName(MavenRepositoryPlugin.PUBLISH_TO_PROJECT_REPOSITORY_TASK_NAME));
project.getTasks().getByName(IntegrationTestPlugin.INT_TEST_TASK_NAME).dependsOn(task);
}
private void copyIntTestMavenRepositoryFiles(Project project, CopySpec copy) {
copy.from(project.getConfigurations().getByName(MavenRepositoryPlugin.MAVEN_REPOSITORY_CONFIGURATION_NAME));
copy.from(new File(project.getBuildDir(), "maven-repository"));
}
private void addDocumentPluginGoalsTask(Project project, MavenExec generatePluginDescriptorTask) {
DocumentPluginGoals task = project.getTasks().create("documentPluginGoals", DocumentPluginGoals.class);
File pluginXml = new File(generatePluginDescriptorTask.getOutputs().getFiles().getSingleFile(), "plugin.xml");
task.setPluginXml(pluginXml);
task.setOutputDir(new File(project.getBuildDir(), "docs/generated/goals/"));
task.dependsOn(generatePluginDescriptorTask);
}
private MavenExec addGenerateHelpMojoTask(Project project, Jar jarTask) {
File helpMojoDir = new File(project.getBuildDir(), "help-mojo");
Copy helpMojoInputs = createCopyHelpMojoInputs(project, helpMojoDir);
MavenExec generateHelpMojo = createGenerateHelpMojo(project, helpMojoDir);
generateHelpMojo.dependsOn(helpMojoInputs);
return generateHelpMojo;
MavenExec task = createGenerateHelpMojoTask(project, helpMojoDir);
task.dependsOn(createCopyHelpMojoInputsTask(project, helpMojoDir));
includeHelpMojoInJar(jarTask, task);
return task;
}
private Copy createCopyHelpMojoInputs(Project project, File mavenDir) {
Copy mojoInputs = project.getTasks().create("copyHelpMojoInputs", Copy.class);
mojoInputs.setDestinationDir(mavenDir);
mojoInputs.from(new File(project.getProjectDir(), "src/maven/resources/pom.xml"),
(sync) -> sync.filter((input) -> input.replace("{{version}}", project.getVersion().toString())));
return mojoInputs;
private MavenExec createGenerateHelpMojoTask(Project project, File helpMojoDir) {
MavenExec task = project.getTasks().create("generateHelpMojo", MavenExec.class);
task.setProjectDir(helpMojoDir);
task.args("org.apache.maven.plugins:maven-plugin-plugin:3.6.0:helpmojo");
task.getOutputs().dir(new File(helpMojoDir, "target/generated-sources/plugin"));
return task;
}
private MavenExec createGenerateHelpMojo(Project project, File mavenDir) {
MavenExec generateHelpMojo = project.getTasks().create("generateHelpMojo", MavenExec.class);
generateHelpMojo.setProjectDir(mavenDir);
generateHelpMojo.args("org.apache.maven.plugins:maven-plugin-plugin:3.6.0:helpmojo");
generateHelpMojo.getOutputs().dir(new File(mavenDir, "target/generated-sources/plugin"));
return generateHelpMojo;
private Copy createCopyHelpMojoInputsTask(Project project, File helpMojoDir) {
Copy task = project.getTasks().create("copyHelpMojoInputs", Copy.class);
task.setDestinationDir(helpMojoDir);
File pomFile = new File(project.getProjectDir(), "src/maven/resources/pom.xml");
task.from(pomFile, (copy) -> replaceVersionPlaceholder(copy, project));
return task;
}
private MavenExec configurePluginDescriptorGenerationTasks(Project project, MavenExec generateHelpMojo) {
private void includeHelpMojoInJar(Jar jarTask, JavaExec generateHelpMojoTask) {
jarTask.from(generateHelpMojoTask).exclude("**/*.java");
jarTask.dependsOn(generateHelpMojoTask);
}
private MavenExec addGeneratePluginDescriptorTask(Project project, Jar jarTask, MavenExec generateHelpMojoTask) {
File pluginDescriptorDir = new File(project.getBuildDir(), "plugin-descriptor");
SourceSetContainer sourceSets = project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets();
SourceSet mainSourceSet = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
File generatedHelpMojoDir = new File(project.getBuildDir(), "generated/sources/helpMojo");
project.getTasks().withType(Javadoc.class,
(javadoc) -> ((StandardJavadocDocletOptions) javadoc.getOptions()).addMultilineStringsOption("tag")
.setValue(Arrays.asList("goal:X", "requiresProject:X", "threadSafe:X")));
FormatHelpMojoSource copyFormattedHelpMojoSource = project.getTasks().create("copyFormattedHelpMojoSource",
FormatHelpMojoSource.class);
copyFormattedHelpMojoSource.setGenerator(generateHelpMojo);
copyFormattedHelpMojoSource.setOutputDir(generatedHelpMojoDir);
mainSourceSet.getAllJava().srcDir(generatedHelpMojoDir);
project.getTasks().getByName(mainSourceSet.getCompileJavaTaskName()).dependsOn(copyFormattedHelpMojoSource);
SourceSet mainSourceSet = getMainSourceSet(project);
project.getTasks().withType(Javadoc.class, this::setJavadocOptions);
FormatHelpMojoSourceTask copyFormattedHelpMojoSourceTask = createCopyFormattedHelpMojoSourceTask(project,
generateHelpMojoTask, generatedHelpMojoDir);
project.getTasks().getByName(mainSourceSet.getCompileJavaTaskName()).dependsOn(copyFormattedHelpMojoSourceTask);
mainSourceSet.java((javaSources) -> javaSources.srcDir(generatedHelpMojoDir));
Copy pluginDescriptorInputs = createCopyPluginDescriptorInputs(project, pluginDescriptorDir, mainSourceSet);
pluginDescriptorInputs.dependsOn(mainSourceSet.getClassesTaskName());
MavenExec generatePluginDescriptor = createGeneratePluginDescriptor(project, pluginDescriptorDir);
generatePluginDescriptor.dependsOn(pluginDescriptorInputs);
return generatePluginDescriptor;
MavenExec task = createGeneratePluginDescriptorTask(project, pluginDescriptorDir);
task.dependsOn(pluginDescriptorInputs);
includeDescriptorInJar(jarTask, task);
return task;
}
private SourceSet getMainSourceSet(Project project) {
SourceSetContainer sourceSets = project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets();
return sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
}
private void setJavadocOptions(Javadoc javadoc) {
StandardJavadocDocletOptions options = (StandardJavadocDocletOptions) javadoc.getOptions();
options.addMultilineStringsOption("tag").setValue(Arrays.asList("goal:X", "requiresProject:X", "threadSafe:X"));
}
private FormatHelpMojoSourceTask createCopyFormattedHelpMojoSourceTask(Project project,
MavenExec generateHelpMojoTask, File generatedHelpMojoDir) {
FormatHelpMojoSourceTask copyFormattedHelpMojoSourceTask = project.getTasks()
.create("copyFormattedHelpMojoSource", FormatHelpMojoSourceTask.class);
copyFormattedHelpMojoSourceTask.setGenerator(generateHelpMojoTask);
copyFormattedHelpMojoSourceTask.setOutputDir(generatedHelpMojoDir);
return copyFormattedHelpMojoSourceTask;
}
private Copy createCopyPluginDescriptorInputs(Project project, File destination, SourceSet sourceSet) {
Copy pluginDescriptorInputs = project.getTasks().create("copyPluginDescriptorInputs", Copy.class);
pluginDescriptorInputs.setDestinationDir(destination);
pluginDescriptorInputs.from(new File(project.getProjectDir(), "src/maven/resources/pom.xml"),
(sync) -> sync.filter((input) -> input.replace("{{version}}", project.getVersion().toString())));
File pomFile = new File(project.getProjectDir(), "src/maven/resources/pom.xml");
pluginDescriptorInputs.from(pomFile, (copy) -> replaceVersionPlaceholder(copy, project));
pluginDescriptorInputs.from(sourceSet.getOutput().getClassesDirs(), (sync) -> sync.into("target/classes"));
pluginDescriptorInputs.from(sourceSet.getAllJava().getSrcDirs(), (sync) -> sync.into("src/main/java"));
return pluginDescriptorInputs;
}
private MavenExec createGeneratePluginDescriptor(Project project, File mavenDir) {
private MavenExec createGeneratePluginDescriptorTask(Project project, File mavenDir) {
MavenExec generatePluginDescriptor = project.getTasks().create("generatePluginDescriptor", MavenExec.class);
generatePluginDescriptor.args("org.apache.maven.plugins:maven-plugin-plugin:3.6.0:descriptor");
generatePluginDescriptor.getOutputs().file(new File(mavenDir, "target/classes/META-INF/maven/plugin.xml"));
generatePluginDescriptor.getOutputs().dir(new File(mavenDir, "target/classes/META-INF/maven"));
generatePluginDescriptor.getInputs().dir(new File(mavenDir, "target/classes/org"));
generatePluginDescriptor.setProjectDir(mavenDir);
return generatePluginDescriptor;
}
private void includeDescriptorInJar(Jar jar, JavaExec generatePluginDescriptor) {
jar.from(generatePluginDescriptor, (copy) -> copy.into("META-INF/maven/"));
jar.dependsOn(generatePluginDescriptor);
private void includeDescriptorInJar(Jar jar, JavaExec generatePluginDescriptorTask) {
jar.from(generatePluginDescriptorTask, (copy) -> copy.into("META-INF/maven/"));
jar.dependsOn(generatePluginDescriptorTask);
}
private void includeHelpMojoInJar(Jar jar, JavaExec generateHelpMojo) {
jar.from(generateHelpMojo);
jar.dependsOn(generateHelpMojo);
private void addPrepareMavenBinariesTask(Project project) {
PrepareMavenBinaries task = project.getTasks().create("prepareMavenBinaries", PrepareMavenBinaries.class);
task.setOutputDir(new File(project.getBuildDir(), "maven-binaries"));
project.getTasks().getByName(IntegrationTestPlugin.INT_TEST_TASK_NAME).dependsOn(task);
}
public static class FormatHelpMojoSource extends DefaultTask {
private void replaceVersionPlaceholder(CopySpec copy, Project project) {
copy.filter((input) -> replaceVersionPlaceholder(project, input));
}
private String replaceVersionPlaceholder(Project project, String input) {
return input.replace("{{version}}", project.getVersion().toString());
}
public static class FormatHelpMojoSourceTask extends DefaultTask {
private Task generator;
@ -190,19 +230,22 @@ public class MavenPluginPlugin implements Plugin<Project> {
@TaskAction
void syncAndFormat() {
FileFormatter fileFormatter = new FileFormatter();
FileFormatter formatter = new FileFormatter();
for (File output : this.generator.getOutputs().getFiles()) {
fileFormatter.formatFiles(getProject().fileTree(output), StandardCharsets.UTF_8).forEach((fileEdit) -> {
Path relativePath = output.toPath().relativize(fileEdit.getFile().toPath());
Path outputLocation = this.outputDir.toPath().resolve(relativePath);
try {
Files.createDirectories(outputLocation.getParent());
Files.write(outputLocation, fileEdit.getFormattedContent().getBytes(StandardCharsets.UTF_8));
}
catch (Exception ex) {
throw new TaskExecutionException(this, ex);
}
});
formatter.formatFiles(getProject().fileTree(output), StandardCharsets.UTF_8)
.forEach((edit) -> save(output, edit));
}
}
private void save(File output, FileEdit edit) {
Path relativePath = output.toPath().relativize(edit.getFile().toPath());
Path outputLocation = this.outputDir.toPath().resolve(relativePath);
try {
Files.createDirectories(outputLocation.getParent());
Files.write(outputLocation, edit.getFormattedContent().getBytes(StandardCharsets.UTF_8));
}
catch (Exception ex) {
throw new TaskExecutionException(this, ex);
}
}