|
|
|
@ -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 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 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 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 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 void includeHelpMojoInJar(Jar jarTask, JavaExec generateHelpMojoTask) {
|
|
|
|
|
jarTask.from(generateHelpMojoTask).exclude("**/*.java");
|
|
|
|
|
jarTask.dependsOn(generateHelpMojoTask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private MavenExec configurePluginDescriptorGenerationTasks(Project project, MavenExec generateHelpMojo) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|