Harmonize Maven build to use containers

Closes gh-996
This commit is contained in:
Stephane Nicoll
2019-09-04 16:37:02 +02:00
parent 04a78a94d6
commit 88f986b7c1
8 changed files with 159 additions and 123 deletions

View File

@@ -29,7 +29,7 @@ class GroovyMavenBuildCustomizer implements BuildCustomizer<MavenBuild> {
@Override
public void customize(MavenBuild build) {
build.plugins().add("org.codehaus.gmavenplus", "gmavenplus-plugin", (groovyMavenPlugin) -> {
groovyMavenPlugin.setVersion("1.6.3");
groovyMavenPlugin.version("1.6.3");
groovyMavenPlugin.execution(null,
(execution) -> execution.goal("addSources").goal("addTestSources").goal("generateStubs")
.goal("compile").goal("generateTestStubs").goal("compileTests").goal("removeStubs")

View File

@@ -39,7 +39,7 @@ class KotlinMavenFullBuildCustomizer implements BuildCustomizer<MavenBuild> {
build.settings().sourceDirectory("${project.basedir}/src/main/kotlin")
.testSourceDirectory("${project.basedir}/src/test/kotlin");
build.plugins().add("org.jetbrains.kotlin", "kotlin-maven-plugin", (kotlinMavenPlugin) -> {
kotlinMavenPlugin.setVersion("${kotlin.version}");
kotlinMavenPlugin.version("${kotlin.version}");
kotlinMavenPlugin.configuration((configuration) -> {
configuration.configure("args",
(args) -> this.settings.getCompilerArgs().forEach((arg) -> args.add("arg", arg)));

View File

@@ -36,24 +36,25 @@ public class MavenPlugin {
private final String artifactId;
private String version;
private final String version;
private final Map<String, ExecutionBuilder> executions = new LinkedHashMap<>();
private final boolean extensions;
private final List<Dependency> dependencies = new ArrayList<>();
private final List<Execution> executions;
private ConfigurationCustomization configurationCustomization = null;
private final List<Dependency> dependencies;
private boolean extensions;
private final Configuration configuration;
public MavenPlugin(String groupId, String artifactId) {
this(groupId, artifactId, null);
}
public MavenPlugin(String groupId, String artifactId, String version) {
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
protected MavenPlugin(Builder builder) {
this.groupId = builder.groupId;
this.artifactId = builder.artifactId;
this.version = builder.version;
this.extensions = builder.extensions;
this.executions = Collections.unmodifiableList(
builder.executions.values().stream().map(ExecutionBuilder::build).collect(Collectors.toList()));
this.dependencies = Collections.unmodifiableList(new ArrayList<>(builder.dependencies));
this.configuration = (builder.configurationBuilder == null) ? null : builder.configurationBuilder.build();
}
public String getGroupId() {
@@ -68,50 +69,82 @@ public class MavenPlugin {
return this.version;
}
public void setVersion(String version) {
this.version = version;
}
public void configuration(Consumer<ConfigurationCustomization> consumer) {
if (this.configurationCustomization == null) {
this.configurationCustomization = new ConfigurationCustomization();
}
consumer.accept(this.configurationCustomization);
}
public void execution(String id, Consumer<ExecutionBuilder> customizer) {
customizer.accept(this.executions.computeIfAbsent(id, (key) -> new ExecutionBuilder(id)));
}
public List<Execution> getExecutions() {
return this.executions.values().stream().map(ExecutionBuilder::build).collect(Collectors.toList());
}
public void dependency(String groupId, String artifactId, String version) {
this.dependencies.add(new Dependency(groupId, artifactId, version));
}
public List<Dependency> getDependencies() {
return Collections.unmodifiableList(this.dependencies);
}
public Configuration getConfiguration() {
return (this.configurationCustomization == null) ? null : this.configurationCustomization.build();
}
public boolean isExtensions() {
return this.extensions;
}
/**
* Enables loading plugin extensions.
*/
public void extensions() {
this.extensions = true;
public List<Execution> getExecutions() {
return this.executions;
}
public List<Dependency> getDependencies() {
return this.dependencies;
}
public Configuration getConfiguration() {
return this.configuration;
}
/**
* Builder for creation an {@link Execution}.
* Builder for a {@link MavenPlugin}.
*/
public static class Builder {
private final String groupId;
private final String artifactId;
private String version;
private boolean extensions;
private final Map<String, ExecutionBuilder> executions = new LinkedHashMap<>();
private final List<Dependency> dependencies = new ArrayList<>();
private ConfigurationBuilder configurationBuilder;
public Builder(String groupId, String artifactId) {
this.groupId = groupId;
this.artifactId = artifactId;
}
public Builder version(String version) {
this.version = version;
return this;
}
public Builder extensions() {
this.extensions = true;
return this;
}
public Builder configuration(Consumer<ConfigurationBuilder> consumer) {
if (this.configurationBuilder == null) {
this.configurationBuilder = new ConfigurationBuilder();
}
consumer.accept(this.configurationBuilder);
return this;
}
public Builder execution(String id, Consumer<ExecutionBuilder> customizer) {
customizer.accept(this.executions.computeIfAbsent(id, (key) -> new ExecutionBuilder(id)));
return this;
}
public Builder dependency(String groupId, String artifactId, String version) {
this.dependencies.add(new Dependency(groupId, artifactId, version));
return this;
}
public MavenPlugin build() {
return new MavenPlugin(this);
}
}
/**
* Builder for an {@link Execution}.
*/
public static class ExecutionBuilder {
@@ -121,7 +154,7 @@ public class MavenPlugin {
private List<String> goals = new ArrayList<>();
private ConfigurationCustomization configurationCustomization = null;
private ConfigurationBuilder configurationCustomization = null;
public ExecutionBuilder(String id) {
this.id = id;
@@ -142,9 +175,9 @@ public class MavenPlugin {
return this;
}
public void configuration(Consumer<ConfigurationCustomization> consumer) {
public void configuration(Consumer<ConfigurationBuilder> consumer) {
if (this.configurationCustomization == null) {
this.configurationCustomization = new ConfigurationCustomization();
this.configurationCustomization = new ConfigurationBuilder();
}
consumer.accept(this.configurationCustomization);
}
@@ -152,9 +185,9 @@ public class MavenPlugin {
}
/**
* Customization of a {@link Configuration}.
* Builder for a {@link Configuration}.
*/
public static class ConfigurationCustomization {
public static class ConfigurationBuilder {
private final List<Setting> settings = new ArrayList<>();
@@ -164,7 +197,7 @@ public class MavenPlugin {
* @param value the single value of the parameter
* @return this for method chaining
*/
public ConfigurationCustomization add(String name, String value) {
public ConfigurationBuilder add(String name, String value) {
this.settings.add(new Setting(name, value));
return this;
}
@@ -177,18 +210,18 @@ public class MavenPlugin {
* @throws IllegalArgumentException if a parameter with the same name is
* registered with a single value
*/
public ConfigurationCustomization configure(String name, Consumer<ConfigurationCustomization> consumer) {
public ConfigurationBuilder configure(String name, Consumer<ConfigurationBuilder> consumer) {
Object value = this.settings.stream().filter((candidate) -> candidate.getName().equals(name)).findFirst()
.orElseGet(() -> {
Setting nestedSetting = new Setting(name, new ConfigurationCustomization());
Setting nestedSetting = new Setting(name, new ConfigurationBuilder());
this.settings.add(nestedSetting);
return nestedSetting;
}).getValue();
if (!(value instanceof ConfigurationCustomization)) {
if (!(value instanceof ConfigurationBuilder)) {
throw new IllegalArgumentException(String.format(
"Could not customize parameter '%s', a single value %s is already registered", name, value));
}
ConfigurationCustomization nestedConfiguration = (ConfigurationCustomization) value;
ConfigurationBuilder nestedConfiguration = (ConfigurationBuilder) value;
consumer.accept(nestedConfiguration);
return this;
}
@@ -199,8 +232,8 @@ public class MavenPlugin {
}
private Setting resolve(String key, Object value) {
if (value instanceof ConfigurationCustomization) {
List<Setting> values = ((ConfigurationCustomization) value).settings.stream()
if (value instanceof ConfigurationBuilder) {
List<Setting> values = ((ConfigurationBuilder) value).settings.stream()
.map((entry) -> resolve(entry.getName(), entry.getValue())).collect(Collectors.toList());
return new Setting(key, values);
}
@@ -219,11 +252,11 @@ public class MavenPlugin {
private final List<Setting> settings;
private Configuration(List<Setting> settings) {
this.settings = settings;
this.settings = Collections.unmodifiableList(settings);
}
public List<Setting> getSettings() {
return Collections.unmodifiableList(this.settings);
return this.settings;
}
}
@@ -268,7 +301,7 @@ public class MavenPlugin {
private Execution(String id, String phase, List<String> goals, Configuration configuration) {
this.id = id;
this.phase = phase;
this.goals = goals;
this.goals = Collections.unmodifiableList(goals);
this.configuration = configuration;
}

View File

@@ -21,6 +21,8 @@ import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;
import io.spring.initializr.generator.buildsystem.maven.MavenPlugin.Builder;
/**
* A container for {@link MavenPlugin}s.
*
@@ -28,7 +30,7 @@ import java.util.stream.Stream;
*/
public class MavenPluginContainer {
private final Map<String, MavenPlugin> plugins = new LinkedHashMap<>();
private final Map<String, MavenPlugin.Builder> plugins = new LinkedHashMap<>();
/**
* Specify if this container is empty.
@@ -55,7 +57,7 @@ public class MavenPluginContainer {
* @return a stream of {@link MavenPlugin}s
*/
public Stream<MavenPlugin> values() {
return this.plugins.values().stream();
return this.plugins.values().stream().map(Builder::build);
}
/**
@@ -70,21 +72,20 @@ public class MavenPluginContainer {
}
/**
* Add a {@link MavenPlugin}with the specified {@code groupId} and {@code artifactId}
* and {@link Consumer} to customize the object. If the plugin has already been added,
* Add a {@link MavenPlugin} with the specified {@code groupId} and {@code artifactId}
* and {@link Consumer} to customize the plugin. If the plugin has already been added,
* the consumer can be used to further tune the existing plugin configuration.
* @param groupId the groupId of the plugin
* @param artifactId the artifactId of the plugin
* @param plugin a {@link Consumer} to customize the {@link MavenPlugin}
*/
public void add(String groupId, String artifactId, Consumer<MavenPlugin> plugin) {
MavenPlugin mavenPlugin = addPlugin(groupId, artifactId);
plugin.accept(mavenPlugin);
public void add(String groupId, String artifactId, Consumer<MavenPlugin.Builder> plugin) {
plugin.accept(addPlugin(groupId, artifactId));
}
private MavenPlugin addPlugin(String groupId, String artifactId) {
private MavenPlugin.Builder addPlugin(String groupId, String artifactId) {
return this.plugins.computeIfAbsent(pluginKey(groupId, artifactId),
(pluginId) -> new MavenPlugin(groupId, artifactId));
(pluginId) -> new MavenPlugin.Builder(groupId, artifactId));
}
/**

View File

@@ -16,6 +16,7 @@
package io.spring.initializr.generator.buildsystem.maven;
import io.spring.initializr.generator.buildsystem.maven.MavenPlugin.Builder;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -76,7 +77,7 @@ class MavenBuildTests {
void mavenPluginVersionCanBeAmended() {
MavenBuild build = new MavenBuild();
build.plugins().add("com.example", "test-plugin");
build.plugins().add("com.example", "test-plugin", (plugin) -> plugin.setVersion("1.0.0"));
build.plugins().add("com.example", "test-plugin", (plugin) -> plugin.version("1.0.0"));
assertThat(build.plugins().values()).hasOnlyOneElementSatisfying((testPlugin) -> {
assertThat(testPlugin.getGroupId()).isEqualTo("com.example");
assertThat(testPlugin.getArtifactId()).isEqualTo("test-plugin");
@@ -88,8 +89,8 @@ class MavenBuildTests {
@Test
void mavenPluginVersionCanBeAmendedWithCustomizer() {
MavenBuild build = new MavenBuild();
build.plugins().add("com.example", "test-plugin", (plugin) -> plugin.setVersion("1.0.0"));
build.plugins().add("com.example", "test-plugin", (plugin) -> plugin.setVersion(null));
build.plugins().add("com.example", "test-plugin", (plugin) -> plugin.version("1.0.0"));
build.plugins().add("com.example", "test-plugin", (plugin) -> plugin.version(null));
assertThat(build.plugins().values()).hasOnlyOneElementSatisfying((testPlugin) -> {
assertThat(testPlugin.getGroupId()).isEqualTo("com.example");
assertThat(testPlugin.getArtifactId()).isEqualTo("test-plugin");
@@ -100,7 +101,7 @@ class MavenBuildTests {
@Test
void mavenPluginVersionIsNotLostOnAmend() {
MavenBuild build = new MavenBuild();
build.plugins().add("com.example", "test-plugin", (plugin) -> plugin.setVersion("1.0.0"));
build.plugins().add("com.example", "test-plugin", (plugin) -> plugin.version("1.0.0"));
build.plugins().add("com.example", "test-plugin");
assertThat(build.plugins().values()).hasOnlyOneElementSatisfying((testPlugin) -> {
assertThat(testPlugin.getGroupId()).isEqualTo("com.example");
@@ -134,7 +135,7 @@ class MavenBuildTests {
@Test
void mavenPluginExtensionsCanBeLoaded() {
MavenBuild build = new MavenBuild();
build.plugins().add("com.example", "test-plugin", MavenPlugin::extensions);
build.plugins().add("com.example", "test-plugin", Builder::extensions);
assertThat(build.plugins().values())
.hasOnlyOneElementSatisfying((testPlugin) -> assertThat(testPlugin.isExtensions()).isTrue());
}

View File

@@ -392,7 +392,7 @@ class MavenBuildWriterTests {
MavenBuild build = new MavenBuild();
build.settings().coordinates("com.example.demo", "demo");
build.plugins().add("org.asciidoctor", "asciidoctor-maven-plugin", (plugin) -> {
plugin.setVersion("1.5.3");
plugin.version("1.5.3");
plugin.execution("generateProject-docs", (execution) -> {
execution.goal("process-asciidoc");
execution.phase("generateProject-resources");
@@ -438,7 +438,7 @@ class MavenBuildWriterTests {
void pomWithPluginWithExtensions() throws Exception {
MavenBuild build = new MavenBuild();
build.settings().coordinates("com.example.demo", "demo");
build.plugins().add("com.example.demo", "demo-plugin", MavenPlugin::extensions);
build.plugins().add("com.example.demo", "demo-plugin", MavenPlugin.Builder::extensions);
generatePom(build, (pom) -> {
NodeAssert plugin = pom.nodeAtPath("/project/build/plugins/plugin");
assertThat(plugin).textAtPath("groupId").isEqualTo("com.example.demo");

View File

@@ -42,10 +42,8 @@ public class MavenPluginContainerTests {
@Test
void addPluginWithConsumer() {
MavenPluginContainer pluginContainer = new MavenPluginContainer();
pluginContainer.add("com.example", "test-plugin", (plugin) -> {
plugin.setVersion("1.0");
plugin.execution("first", (first) -> first.goal("run-this"));
});
pluginContainer.add("com.example", "test-plugin",
(plugin) -> plugin.version("1.0").execution("first", (first) -> first.goal("run-this")));
assertThat(pluginContainer.values()).hasOnlyOneElementSatisfying((plugin) -> {
assertThat(plugin.getGroupId()).isEqualTo("com.example");
assertThat(plugin.getArtifactId()).isEqualTo("test-plugin");
@@ -59,14 +57,8 @@ public class MavenPluginContainerTests {
@Test
void addPluginSeveralTimeReuseConfiguration() {
MavenPluginContainer pluginContainer = new MavenPluginContainer();
pluginContainer.add("com.example", "test-plugin", (plugin) -> {
assertThat(plugin.getVersion()).isNull();
plugin.setVersion("1.0");
});
pluginContainer.add("com.example", "test-plugin", (plugin) -> {
assertThat(plugin.getVersion()).isEqualTo("1.0");
plugin.setVersion("2.0");
});
pluginContainer.add("com.example", "test-plugin", (plugin) -> plugin.version("1.0"));
pluginContainer.add("com.example", "test-plugin", (plugin) -> plugin.version("2.0"));
assertThat(pluginContainer.values()).hasOnlyOneElementSatisfying((plugin) -> {
assertThat(plugin.getGroupId()).isEqualTo("com.example");
assertThat(plugin.getArtifactId()).isEqualTo("test-plugin");

View File

@@ -18,6 +18,7 @@ package io.spring.initializr.generator.buildsystem.maven;
import java.util.List;
import io.spring.initializr.generator.buildsystem.maven.MavenPlugin.Builder;
import io.spring.initializr.generator.buildsystem.maven.MavenPlugin.Setting;
import org.junit.jupiter.api.Test;
@@ -33,9 +34,9 @@ class MavenPluginTests {
@Test
void configurationParameterCanBeCustomized() {
MavenPlugin plugin = new MavenPlugin("com.example", "test-plugin");
plugin.configuration((configuration) -> configuration.add("enabled", "false").add("skip", "true"));
plugin.configuration((configuration) -> configuration.add("another", "test"));
MavenPlugin plugin = plugin("com.example", "test-plugin")
.configuration((configuration) -> configuration.add("enabled", "false").add("skip", "true"))
.configuration((configuration) -> configuration.add("another", "test")).build();
assertThat(plugin.getConfiguration().getSettings().stream().map(Setting::getName)).containsExactly("enabled",
"skip", "another");
assertThat(plugin.getConfiguration().getSettings().stream().map(Setting::getValue)).containsExactly("false",
@@ -44,9 +45,9 @@ class MavenPluginTests {
@Test
void configurationParameterCanBeAdded() {
MavenPlugin plugin = new MavenPlugin("com.example", "test-plugin");
plugin.configuration((configuration) -> configuration.add("enabled", "true"));
plugin.configuration((configuration) -> configuration.add("skip", "false"));
MavenPlugin plugin = plugin("com.example", "test-plugin")
.configuration((configuration) -> configuration.add("enabled", "true"))
.configuration((configuration) -> configuration.add("skip", "false")).build();
assertThat(plugin.getConfiguration().getSettings().stream().map(Setting::getName)).containsExactly("enabled",
"skip");
assertThat(plugin.getConfiguration().getSettings().stream().map(Setting::getValue)).containsExactly("true",
@@ -56,9 +57,10 @@ class MavenPluginTests {
@Test
@SuppressWarnings("unchecked")
void configurationParameterWithNestedValuesCanBeCustomized() {
MavenPlugin plugin = new MavenPlugin("com.example", "test-plugin");
plugin.configuration((configuration) -> configuration.configure("items", (items) -> items.add("item", "one")));
plugin.configuration((configuration) -> configuration.configure("items", (items) -> items.add("item", "two")));
MavenPlugin plugin = plugin("com.example", "test-plugin")
.configuration((configuration) -> configuration.configure("items", (items) -> items.add("item", "one")))
.configuration((configuration) -> configuration.configure("items", (items) -> items.add("item", "two")))
.build();
assertThat(plugin.getConfiguration().getSettings()).hasSize(1);
Setting setting = plugin.getConfiguration().getSettings().get(0);
assertThat(setting.getName()).isEqualTo("items");
@@ -71,11 +73,15 @@ class MavenPluginTests {
@Test
@SuppressWarnings("unchecked")
void configurationParameterWithSeveralLevelOfNestedValuesCanBeCustomized() {
MavenPlugin plugin = new MavenPlugin("com.example", "test-plugin");
plugin.configuration((configuration) -> configuration.configure("items",
(items) -> items.configure("item", (subItems) -> subItems.add("subItem", "one"))));
plugin.configuration((configuration) -> configuration.configure("items", (items) -> items.configure("item",
(subItems) -> subItems.add("subItem", "two").add("subItem", "three"))));
MavenPlugin plugin = plugin("com.example", "test-plugin")
.configuration((configuration) -> configuration.configure("items",
(items) -> items.configure("item", (subItems) -> subItems.add("subItem", "one"))))
.configuration(
(configuration) -> configuration
.configure("items",
(items) -> items.configure("item",
(subItems) -> subItems.add("subItem", "two").add("subItem", "three"))))
.build();
assertThat(plugin.getConfiguration().getSettings()).hasSize(1);
Setting setting = plugin.getConfiguration().getSettings().get(0);
assertThat(setting.getName()).isEqualTo("items");
@@ -92,43 +98,46 @@ class MavenPluginTests {
@Test
void configurationParameterWithSingleValueCannotBeSwitchedToNestedValue() {
MavenPlugin plugin = new MavenPlugin("com.example", "test-plugin");
plugin.configuration((configuration) -> configuration.add("test", "value"));
MavenPlugin.Builder builder = plugin("com.example", "test-plugin")
.configuration((configuration) -> configuration.add("test", "value"));
assertThatIllegalArgumentException()
.isThrownBy(() -> plugin
.isThrownBy(() -> builder
.configuration((customizer) -> customizer.configure("test", (test) -> test.add("one", "true"))))
.withMessageContaining("test").withMessageContaining("value");
}
@Test
void executionPhasesCanBeOverridden() {
MavenPlugin plugin = new MavenPlugin("com.example", "test-plugin");
plugin.execution("test", (test) -> test.phase("compile"));
plugin.execution("test", (test) -> test.phase("process-resources"));
MavenPlugin plugin = plugin("com.example", "test-plugin").execution("test", (test) -> test.phase("compile"))
.execution("test", (test) -> test.phase("process-resources")).build();
assertThat(plugin.getExecutions()).hasSize(1);
assertThat(plugin.getExecutions().get(0).getPhase()).isEqualTo("process-resources");
}
@Test
void executionGoalsCanBeAmended() {
MavenPlugin plugin = new MavenPlugin("com.example", "test-plugin");
plugin.execution("test", (test) -> test.goal("first"));
plugin.execution("test", (test) -> test.goal("second"));
MavenPlugin plugin = plugin("com.example", "test-plugin").execution("test", (test) -> test.goal("first"))
.execution("test", (test) -> test.goal("second")).build();
assertThat(plugin.getExecutions()).hasSize(1);
assertThat(plugin.getExecutions().get(0).getGoals()).containsExactly("first", "second");
}
@Test
void executionConfigurationCanBeOverridden() {
MavenPlugin plugin = new MavenPlugin("com.example", "test-plugin");
plugin.execution("test",
(test) -> test.configuration((testConfiguration) -> testConfiguration.add("enabled", "true")));
plugin.execution("test",
(test) -> test.configuration((testConfiguration) -> testConfiguration.add("another", "test")));
MavenPlugin plugin = plugin("com.example", "test-plugin")
.execution("test",
(test) -> test.configuration((testConfiguration) -> testConfiguration.add("enabled", "true")))
.execution("test",
(test) -> test.configuration((testConfiguration) -> testConfiguration.add("another", "test")))
.build();
assertThat(plugin.getExecutions()).hasSize(1);
List<Setting> settings = plugin.getExecutions().get(0).getConfiguration().getSettings();
assertThat(settings.stream().map(Setting::getName)).containsExactly("enabled", "another");
assertThat(settings.stream().map(Setting::getValue)).containsExactly("true", "test");
}
private MavenPlugin.Builder plugin(String groupId, String artifactId) {
return new Builder(groupId, artifactId);
}
}