Merge pull request #967 from LeoRamos01

* pr/967:
  Polish "Add support for Maven resources"
  Add support for Maven resources

Closes gh-967
This commit is contained in:
Stephane Nicoll 2019-08-23 15:06:00 +02:00
commit ccd2ec8c30
7 changed files with 453 additions and 1 deletions

View File

@ -27,6 +27,7 @@ import io.spring.initializr.generator.buildsystem.BuildItemResolver;
* Maven build for a project.
*
* @author Andy Wilkinson
* @author Stephane Nicoll
*/
public class MavenBuild extends Build {
@ -42,6 +43,10 @@ public class MavenBuild extends Build {
private final Map<String, String> properties = new TreeMap<>();
private final MavenResourceContainer resources = new MavenResourceContainer();
private final MavenResourceContainer testResources = new MavenResourceContainer();
private MavenPluginContainer plugins = new MavenPluginContainer();
private String packaging;
@ -103,6 +108,14 @@ public class MavenBuild extends Build {
this.testSourceDirectory = testSourceDirectory;
}
public MavenResourceContainer resources() {
return this.resources;
}
public MavenResourceContainer testResources() {
return this.testResources;
}
public MavenPluginContainer plugins() {
return this.plugins;
}

View File

@ -240,18 +240,65 @@ public class MavenBuildWriter {
}
private void writeBuild(IndentingWriter writer, MavenBuild build) {
if (build.getSourceDirectory() == null && build.getTestSourceDirectory() == null && build.plugins().isEmpty()) {
if (build.getSourceDirectory() == null && build.getTestSourceDirectory() == null && build.resources().isEmpty()
&& build.testResources().isEmpty() && build.plugins().isEmpty()) {
return;
}
writer.println();
writeElement(writer, "build", () -> {
writeSingleElement(writer, "sourceDirectory", build.getSourceDirectory());
writeSingleElement(writer, "testSourceDirectory", build.getTestSourceDirectory());
writeResources(writer, build);
writePlugins(writer, build);
});
}
private void writeResources(IndentingWriter writer, MavenBuild build) {
if (!build.resources().isEmpty()) {
writeElement(writer, "resources", () -> writeCollection(writer,
build.resources().values().collect(Collectors.toList()), this::writeResource));
}
if (!build.testResources().isEmpty()) {
writeElement(writer, "testResources", () -> writeCollection(writer,
build.testResources().values().collect(Collectors.toList()), this::writeTestResource));
}
}
private void writeResource(IndentingWriter writer, MavenResource resource) {
writeResource(writer, resource, "resource");
}
private void writeTestResource(IndentingWriter writer, MavenResource resource) {
writeResource(writer, resource, "testResource");
}
private void writeResource(IndentingWriter writer, MavenResource resource, String resourceName) {
writeElement(writer, resourceName, () -> {
writeSingleElement(writer, "directory", resource.getDirectory());
writeSingleElement(writer, "targetPath", resource.getTargetPath());
if (resource.isFiltering()) {
writeSingleElement(writer, "filtering", "true");
}
if (!resource.getIncludes().isEmpty()) {
writeElement(writer, "includes",
() -> writeCollection(writer, resource.getIncludes(), this::writeResourceInclude));
}
if (!resource.getExcludes().isEmpty()) {
writeElement(writer, "excludes",
() -> writeCollection(writer, resource.getExcludes(), this::writeResourceExclude));
}
});
}
private void writeResourceInclude(IndentingWriter writer, String include) {
writeSingleElement(writer, "include", include);
}
private void writeResourceExclude(IndentingWriter writer, String exclude) {
writeSingleElement(writer, "exclude", exclude);
}
private void writePlugins(IndentingWriter writer, MavenBuild build) {
if (build.plugins().isEmpty()) {
return;

View File

@ -0,0 +1,138 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.spring.initializr.generator.buildsystem.maven;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* A resource of a {@link MavenBuild}.
*
* @author Stephane Nicoll
*/
public class MavenResource {
private final String directory;
private final String targetPath;
private final boolean filtering;
private final List<String> includes;
private final List<String> excludes;
public MavenResource(Builder builder) {
this.directory = builder.directory;
this.targetPath = builder.targetPath;
this.filtering = builder.filtering;
this.includes = builder.includes;
this.excludes = builder.excludes;
}
/**
* Return the directory where resources are to be found. Can use regular maven token
* such as {@code ${basedir}/src/main}.
* @return the resources directory
*/
public String getDirectory() {
return this.directory;
}
/**
* Return the directory structure to place the set of resources from a build. Return
* {@code null} by default which represents the root directory.
* @return the target path or {@code null}
*/
public String getTargetPath() {
return this.targetPath;
}
/**
* Specify if filtering is enabled when copying resources.
* @return {@code true} if filtering is enabled
*/
public boolean isFiltering() {
return this.filtering;
}
/**
* Return files patterns which specify the files to include as resources under that
* specified directory. Can use {@code *} for all.
* @return the include patterns
*/
public List<String> getIncludes() {
return this.includes;
}
/**
* Return files patterns which specify the files to ignore as resources under that
* specified directory. In conflicts between {@code include} and {@code exclude},
* {@code exclude} wins.
* @return the exclude patterns
*/
public List<String> getExcludes() {
return this.excludes;
}
/**
* Builder for a resource.
*/
public static class Builder {
private final String directory;
private String targetPath;
private boolean filtering;
private List<String> includes = new ArrayList<>();
private List<String> excludes = new ArrayList<>();
public Builder(String directory) {
this.directory = directory;
}
public Builder targetPath(String targetPath) {
this.targetPath = targetPath;
return this;
}
public Builder filtering(Boolean filtering) {
this.filtering = filtering;
return this;
}
public Builder includes(String... includes) {
this.includes = Arrays.asList(includes);
return this;
}
public Builder excludes(String... excludes) {
this.excludes = Arrays.asList(excludes);
return this;
}
public MavenResource build() {
return new MavenResource(this);
}
}
}

View File

@ -0,0 +1,86 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.spring.initializr.generator.buildsystem.maven;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;
/**
* A container for {@link MavenResource}s.
*
* @author Stephane Nicoll
*/
public class MavenResourceContainer {
private final Map<String, MavenResource.Builder> resources = new LinkedHashMap<>();
/**
* Specify if this container is empty.
* @return {@code true} if no {@link MavenResource} is added
*/
public boolean isEmpty() {
return this.resources.isEmpty();
}
/**
* Specify if this container has a resource the specified {@code directory}.
* @param directory the resource directory
* @return {@code true} if an item for the specified {@code directory} exists
*/
public boolean has(String directory) {
return this.resources.containsKey(directory);
}
/**
* Returns a {@link Stream} of registered {@link MavenResource}s.
* @return a stream of {@link MavenResource}s
*/
public Stream<MavenResource> values() {
return this.resources.values().stream().map(MavenResource.Builder::build);
}
/**
* Add a resource with default settings for the specified {@code directory}.
* @param directory the directory to add
*/
public void add(String directory) {
this.resources.computeIfAbsent(directory, (key) -> new MavenResource.Builder(directory));
}
/**
* Add a resource with default settings for the specified {@code directory} and
* {@link Consumer} to customize the resource. If the resource has already been added,
* the consumer can be used to further tune the existing resource configuration.
* @param directory the directory to add
* @param resource a {@link Consumer} to customize the {@link MavenResource}
*/
public void add(String directory, Consumer<MavenResource.Builder> resource) {
resource.accept(this.resources.computeIfAbsent(directory, (key) -> new MavenResource.Builder(directory)));
}
/**
* Remove the resource with the specified {@code directory}.
* @param directory the directory to remove
* @return {@code true} if such a resource was registered, {@code false} otherwise
*/
public boolean remove(String directory) {
return this.resources.remove(directory) != null;
}
}

View File

@ -28,6 +28,35 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
class MavenBuildTests {
@Test
void mavenResourcesEmptyByDefault() {
MavenBuild build = new MavenBuild();
assertThat(build.resources().isEmpty()).isTrue();
assertThat(build.testResources().isEmpty()).isTrue();
}
@Test
void mavenResourcesCanBeConfigured() {
MavenBuild build = new MavenBuild();
build.resources().add("src/main/custom", (resource) -> resource.filtering(true));
assertThat(build.resources().values()).hasOnlyOneElementSatisfying((resource) -> {
assertThat(resource.getDirectory()).isEqualTo("src/main/custom");
assertThat(resource.isFiltering()).isTrue();
});
assertThat(build.testResources().isEmpty()).isTrue();
}
@Test
void mavenTestResourcesCanBeConfigured() {
MavenBuild build = new MavenBuild();
build.testResources().add("src/test/custom", (resource) -> resource.excludes("**/*.gen"));
assertThat(build.resources().isEmpty()).isTrue();
assertThat(build.testResources().values()).hasOnlyOneElementSatisfying((resource) -> {
assertThat(resource.getDirectory()).isEqualTo("src/test/custom");
assertThat(resource.getExcludes()).containsExactly("**/*.gen");
});
}
@Test
void mavenPluginCanBeConfigured() {
MavenBuild build = new MavenBuild();

View File

@ -344,6 +344,38 @@ class MavenBuildWriterTests {
assertThat(firstBom).textAtPath("scope").isEqualTo("import");
}
@Test
void pomWithResources() throws Exception {
MavenBuild build = new MavenBuild();
build.resources().add("src/main/custom", (resource) -> resource.includes("**/*.properties"));
generatePom(build, (pom) -> {
assertThat(pom).textAtPath("/project/build/resources/resource/directory").isEqualTo("src/main/custom");
assertThat(pom).textAtPath("/project/build/resources/resource/targetPath").isNullOrEmpty();
assertThat(pom).textAtPath("/project/build/resources/resource/filtering").isNullOrEmpty();
assertThat(pom).textAtPath("/project/build/resources/resource/includes/include")
.isEqualTo("**/*.properties");
assertThat(pom).textAtPath("/project/build/resources/resource/excludes").isNullOrEmpty();
assertThat(pom).textAtPath("/project/build/testResources").isNullOrEmpty();
});
}
@Test
void pomWithTestResources() throws Exception {
MavenBuild build = new MavenBuild();
build.testResources().add("src/test/custom",
(resource) -> resource.excludes("**/*.gen").filtering(true).targetPath("test"));
generatePom(build, (pom) -> {
assertThat(pom).textAtPath("/project/build/resources").isNullOrEmpty();
assertThat(pom).textAtPath("/project/build/testResources/testResource/directory")
.isEqualTo("src/test/custom");
assertThat(pom).textAtPath("/project/build/testResources/testResource/targetPath").isEqualTo("test");
assertThat(pom).textAtPath("/project/build/testResources/testResource/filtering").isEqualTo("true");
assertThat(pom).textAtPath("/project/build/testResources/testResource/includes").isNullOrEmpty();
assertThat(pom).textAtPath("/project/build/testResources/testResource/excludes/exclude")
.isEqualTo("**/*.gen");
});
}
@Test
void pomWithPlugin() throws Exception {
MavenBuild build = new MavenBuild();
@ -444,6 +476,14 @@ class MavenBuildWriterTests {
});
}
@Test
void pomWithEmptyBuild() throws Exception {
MavenBuild build = new MavenBuild();
build.setGroup("com.example.demo");
build.setArtifact("demo");
generatePom(build, (pom) -> assertThat(pom).textAtPath("/project/build/").isNullOrEmpty());
}
@Test
void pomWithMavenCentral() throws Exception {
MavenBuild build = new MavenBuild();

View File

@ -0,0 +1,99 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.spring.initializr.generator.buildsystem.maven;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MavenResourceContainer}.
*
* @author Stephane Nicoll
*/
class MavenResourceContainerTests {
@Test
void mavenResourceCanBeConfigured() {
MavenResourceContainer container = new MavenResourceContainer();
container.add("src/main/resources", (resource) -> {
resource.targetPath("targetPath");
resource.filtering(true);
resource.includes("**/*.yml");
resource.excludes("**/*.properties");
});
assertThat(container.values()).hasOnlyOneElementSatisfying((resource) -> {
assertThat(resource.getDirectory()).isEqualTo("src/main/resources");
assertThat(resource.getTargetPath()).isEqualTo("targetPath");
assertThat(resource.isFiltering()).isTrue();
assertThat(resource.getIncludes()).containsExactly("**/*.yml");
assertThat(resource.getExcludes()).containsExactly("**/*.properties");
});
}
@Test
void mavenResourceCanBeAmended() {
MavenResourceContainer container = new MavenResourceContainer();
container.add("src/main/resources", (resource) -> {
resource.filtering(true);
resource.includes("**/*.yml");
});
container.add("src/main/resources", (resource) -> {
resource.includes("**/*.yaml");
resource.excludes("**/*.properties");
});
assertThat(container.values()).hasOnlyOneElementSatisfying((resource) -> {
assertThat(resource.getDirectory()).isEqualTo("src/main/resources");
assertThat(resource.getTargetPath()).isNull();
assertThat(resource.isFiltering()).isTrue();
assertThat(resource.getIncludes()).containsExactly("**/*.yaml");
assertThat(resource.getExcludes()).containsExactly("**/*.properties");
});
assertThat(container.isEmpty()).isFalse();
}
@Test
void mavenResourceDefaultValues() {
MavenResourceContainer container = new MavenResourceContainer();
container.add("src/main/custom");
assertThat(container.values()).hasOnlyOneElementSatisfying((resource) -> {
assertThat(resource.getDirectory()).isEqualTo("src/main/custom");
assertThat(resource.getTargetPath()).isNull();
assertThat(resource.isFiltering()).isFalse();
assertThat(resource.getIncludes()).isEmpty();
assertThat(resource.getExcludes()).isEmpty();
});
}
@Test
void mavenResourceCanBeSearched() {
MavenResourceContainer container = new MavenResourceContainer();
assertThat(container.has("src/main/test")).isFalse();
container.add("src/main/test");
assertThat(container.has("src/main/test")).isTrue();
}
@Test
void mavenResourceCanBeRemoved() {
MavenResourceContainer container = new MavenResourceContainer();
container.add("src/main/test");
assertThat(container.has("src/main/test")).isTrue();
assertThat(container.remove("src/main/test")).isTrue();
assertThat(container.has("src/main/test")).isFalse();
}
}