From 3bfe1b00b521c56619fe8274a3e6914ff99ed425 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 20 Oct 2020 11:13:23 +0100 Subject: [PATCH] Put module deps in app layer and make customization easier Previously, when building a layered jar with Maven, dependencies on modules in the same build were treated the same as any other dependency, being included in the dependencies or snapshot dependencies layer based on their version. This commit updates the default layering when using Maven to include dependencies on modules in the same build in the application layer by default. The XML schema has also been updated to allow the layer to be customized using new and elements rather than relying on including and excluding them via a group:artifact:version pattern. Closes gh-23463 --- .../src/docs/asciidoc/packaging.adoc | 14 ++- .../boot/maven/JarIntegrationTests.java | 18 ++-- .../boot/maven/MavenBuild.java | 1 + .../jar-layered-custom/jar-classifier/pom.xml | 40 +++++++ .../projects/jar-layered-custom/jar/pom.xml | 11 ++ .../jar-layered-custom/jar/src/layers.xml | 5 +- .../projects/jar-layered-custom/pom.xml | 3 +- .../intTest/projects/jar-layered/jar/pom.xml | 5 + .../boot/maven/AbstractPackagerMojo.java | 10 +- .../boot/maven/ArtifactsLibraries.java | 44 +++++++- .../boot/maven/CustomLayersProvider.java | 28 ++++- .../src/main/xsd/layers-2.4.xsd | 100 ++++++++++++++++++ .../boot/maven/ArtifactsLibrariesTests.java | 47 +++++++- .../boot/maven/CustomLayersProviderTests.java | 3 + .../dependencies-layer-no-filter.xml | 2 +- .../src/test/resources/layers.xml | 6 +- .../resources/resource-layer-no-filter.xml | 2 +- 17 files changed, 314 insertions(+), 25 deletions(-) create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/jar-classifier/pom.xml create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/xsd/layers-2.4.xsd diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging.adoc b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging.adoc index 67d1bacc02..dbf0119f7a 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging.adoc @@ -86,7 +86,10 @@ By default, the following layers are defined: * `dependencies` for any dependency whose version does not contain `SNAPSHOT`. * `spring-boot-loader` for the jar loader classes. * `snapshot-dependencies` for any dependency whose version contains `SNAPSHOT`. -* `application` for application classes and resources. +* `application` for local module dependencies, application classes, and resources. + +Module dependencies are identified by looking at all of the modules that are part of the current build. +If a module dependency can only be resolved because it has been installed into Maven's local cache and it is not part of the current build, it will be identified as regular dependency. The layers order is important as it determines how likely previous layers can be cached when part of the application changes. The default order is `dependencies`, `spring-boot-loader`, `snapshot-dependencies`, `application`. @@ -159,6 +162,9 @@ The following example shows how the default ordering described above can be defi + + + *:*:*SNAPSHOT @@ -187,13 +193,15 @@ Any content not claimed by an earlier block remains available for subsequent blo The `` block claims content using nested `` and `` elements. The `` section uses Ant-style patch matching for include/exclude expressions. The `` section uses `group:artifact[:version]` patterns. +It also provides `` and `` elements that can be used to include or exclude local module dependencies. If no `` is defined, then all content (not claimed by an earlier block) is considered. If no `` is defined, then no exclusions are applied. -Looking at the `` example above, we can see that the first `` will claim all SNAPSHOT dependencies for the `snapshot-dependencies` layer. -The subsequent `` will claim anything left (in this case, any dependency that is not a SNAPSHOT) for the `dependencies` layer. +Looking at the `` example above, we can see that the first `` will claim all module dependencies for the `application.layer`. +The next `` will claim all SNAPSHOT dependencies for the `snapshot-dependencies` layer. +The final `` will claim anything left (in this case, any dependency that is not a SNAPSHOT) for the `dependencies` layer. The `` block has similar rules. First claiming `org/springframework/boot/loader/**` content for the `spring-boot-loader` layer. diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java index 09e75be907..8ebfbdafcf 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java @@ -304,12 +304,13 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests { .hasEntryWithNameStartingWith("BOOT-INF/lib/jar-release") .hasEntryWithNameStartingWith("BOOT-INF/lib/jar-snapshot").hasEntryWithNameStartingWith( "BOOT-INF/lib/" + JarModeLibrary.LAYER_TOOLS.getCoordinates().getArtifactId()); - try { - try (JarFile jarFile = new JarFile(repackaged)) { - Map> layerIndex = readLayerIndex(jarFile); - assertThat(layerIndex.keySet()).containsExactly("dependencies", "spring-boot-loader", - "snapshot-dependencies", "application"); - } + try (JarFile jarFile = new JarFile(repackaged)) { + Map> layerIndex = readLayerIndex(jarFile); + assertThat(layerIndex.keySet()).containsExactly("dependencies", "spring-boot-loader", + "snapshot-dependencies", "application"); + assertThat(layerIndex.get("application")).contains("BOOT-INF/lib/jar-release-0.0.1.RELEASE.jar", + "BOOT-INF/lib/jar-snapshot-0.0.1.BUILD-SNAPSHOT.jar"); + assertThat(layerIndex.get("dependencies")).contains("BOOT-INF/lib/log4j-api-2.12.1.jar"); } catch (IOException ex) { } @@ -351,6 +352,11 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests { Map> layerIndex = readLayerIndex(jarFile); assertThat(layerIndex.keySet()).containsExactly("my-dependencies-name", "snapshot-dependencies", "configuration", "application"); + assertThat(layerIndex.get("application")) + .contains("BOOT-INF/lib/jar-release-0.0.1.RELEASE.jar", + "BOOT-INF/lib/jar-snapshot-0.0.1.BUILD-SNAPSHOT.jar", + "BOOT-INF/lib/jar-classifier-0.0.1-bravo.jar") + .doesNotContain("BOOT-INF/lib/jar-classifier-0.0.1-alpha.jar"); } }); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/MavenBuild.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/MavenBuild.java index f0f4e79290..a42ce9fe63 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/MavenBuild.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/MavenBuild.java @@ -170,6 +170,7 @@ class MavenBuild { request.setUserSettingsFile(new File(this.temp, "settings.xml")); request.setUpdateSnapshots(true); request.setBatchMode(true); + // request.setMavenOpts("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000"); File target = new File(this.temp, "target"); target.mkdirs(); if (this.preparation != null) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/jar-classifier/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/jar-classifier/pom.xml new file mode 100644 index 0000000000..509a9fec77 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/jar-classifier/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + org.springframework.boot.maven.it + jar-classifier + 0.0.1 + jar + jar + Classifier Jar dependency + + + + maven-jar-plugin + + + alpha + package + + jar + + + alpha + + + + bravo + package + + jar + + + bravo + + + + + + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/jar/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/jar/pom.xml index a987ad7980..03d6b66d4d 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/jar/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/jar/pom.xml @@ -43,5 +43,16 @@ jar-release 0.0.1.RELEASE + + org.springframework.boot.maven.it + jar-classifier + 0.0.1 + bravo + + + org.apache.logging.log4j + log4j-api + @log4j2.version@ + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/jar/src/layers.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/jar/src/layers.xml index b2e12e2c4a..c7552b9776 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/jar/src/layers.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/jar/src/layers.xml @@ -1,7 +1,7 @@ + https://www.springframework.org/schema/layers/layers-2.4.xsd"> **/application*.* @@ -9,6 +9,9 @@ + + + *:*:*-SNAPSHOT diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/pom.xml index fdd9895381..6ee622cf58 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered-custom/pom.xml @@ -12,8 +12,9 @@ @java.version@ - jar-snapshot + jar-classifier jar-release + jar-snapshot jar diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered/jar/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered/jar/pom.xml index 53d7a40c14..e63261909b 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered/jar/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/jar-layered/jar/pom.xml @@ -27,6 +27,11 @@ + + org.apache.logging.log4j + log4j-api + @log4j2.version@ + org.springframework.boot.maven.it jar-snapshot diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java index 79d6555c62..0022001068 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java @@ -28,6 +28,7 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.maven.artifact.Artifact; +import org.apache.maven.execution.MavenSession; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Component; @@ -66,6 +67,13 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo @Parameter(defaultValue = "${project}", readonly = true, required = true) protected MavenProject project; + /** + * The Maven session. + * @since 2.4.0 + */ + @Parameter(defaultValue = "${session}", readonly = true, required = true) + protected MavenSession session; + /** * Maven project helper utils. * @since 1.0.0 @@ -173,7 +181,7 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo */ protected final Libraries getLibraries(Collection unpacks) throws MojoExecutionException { Set artifacts = filterDependencies(this.project.getArtifacts(), getFilters(getAdditionalFilters())); - return new ArtifactsLibraries(artifacts, unpacks, getLog()); + return new ArtifactsLibraries(artifacts, this.session.getProjects(), unpacks, getLog()); } private ArtifactsFilter[] getAdditionalFilters() { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java index a81fe874d3..47b46e6e93 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java @@ -27,6 +27,7 @@ import java.util.Set; import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; import org.springframework.boot.loader.tools.Libraries; import org.springframework.boot.loader.tools.Library; @@ -58,12 +59,38 @@ public class ArtifactsLibraries implements Libraries { private final Set artifacts; + private final Collection localProjects; + private final Collection unpacks; private final Log log; + /** + * Creates a new {@code ArtifactsLibraries} from the given {@code artifacts}. + * @param artifacts the artifacts to represent as libraries + * @param unpacks artifacts that should be unpacked on launch + * @param log the log + * @deprecated since 2.4.0 in favour of + * {@link #ArtifactsLibraries(Set, Collection, Collection, Log)} + */ + @Deprecated public ArtifactsLibraries(Set artifacts, Collection unpacks, Log log) { + this(artifacts, Collections.emptyList(), unpacks, log); + } + + /** + * Creates a new {@code ArtifactsLibraries} from the given {@code artifacts}. + * @param artifacts the artifacts to represent as libraries + * @param localProjects projects for which {@link Library#isLocal() local} libraries + * should be created + * @param unpacks artifacts that should be unpacked on launch + * @param log the log + * @since 2.4.0 + */ + public ArtifactsLibraries(Set artifacts, Collection localProjects, + Collection unpacks, Log log) { this.artifacts = artifacts; + this.localProjects = localProjects; this.unpacks = unpacks; this.log = log; } @@ -81,7 +108,8 @@ public class ArtifactsLibraries implements Libraries { this.log.debug("Renamed to: " + name); } LibraryCoordinates coordinates = new ArtifactLibraryCoordinates(artifact); - callback.library(new Library(name, artifact.getFile(), scope, coordinates, isUnpackRequired(artifact))); + callback.library(new Library(name, artifact.getFile(), scope, coordinates, isUnpackRequired(artifact), + isLocal(artifact))); } } } @@ -110,6 +138,20 @@ public class ArtifactsLibraries implements Libraries { return false; } + private boolean isLocal(Artifact artifact) { + for (MavenProject localProject : this.localProjects) { + if (localProject.getArtifact().equals(artifact)) { + return true; + } + for (Artifact attachedArtifact : localProject.getAttachedArtifacts()) { + if (attachedArtifact.equals(artifact)) { + return true; + } + } + } + return false; + } + private String getFileName(Artifact artifact) { StringBuilder sb = new StringBuilder(); sb.append(artifact.getArtifactId()).append("-").append(artifact.getBaseVersion()); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CustomLayersProvider.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CustomLayersProvider.java index ffdcb43f8e..5d01b34caa 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CustomLayersProvider.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CustomLayersProvider.java @@ -53,11 +53,11 @@ class CustomLayersProvider { } private List> getApplicationSelectors(Element root) { - return getSelectors(root, "application", ApplicationContentFilter::new); + return getSelectors(root, "application", (element) -> getSelector(element, ApplicationContentFilter::new)); } private List> getLibrarySelectors(Element root) { - return getSelectors(root, "dependencies", LibraryContentFilter::new); + return getSelectors(root, "dependencies", (element) -> getLibrarySelector(element, LibraryContentFilter::new)); } private List getLayers(Element root) { @@ -69,7 +69,7 @@ class CustomLayersProvider { } private List> getSelectors(Element root, String elementName, - Function> filterFactory) { + Function> selectorFactory) { Element element = getChildElement(root, elementName); if (element == null) { return Collections.emptyList(); @@ -79,7 +79,7 @@ class CustomLayersProvider { for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); if (child instanceof Element) { - ContentSelector selector = getSelector((Element) child, filterFactory); + ContentSelector selector = selectorFactory.apply((Element) child); selectors.add(selector); } } @@ -93,6 +93,26 @@ class CustomLayersProvider { return new IncludeExcludeContentSelector<>(layer, includes, excludes, filterFactory); } + private ContentSelector getLibrarySelector(Element element, + Function> filterFactory) { + Layer layer = new Layer(element.getAttribute("layer")); + List includes = getChildNodeTextContent(element, "include"); + List excludes = getChildNodeTextContent(element, "exclude"); + Element includeModuleDependencies = getChildElement(element, "includeModuleDependencies"); + Element excludeModuleDependencies = getChildElement(element, "excludeModuleDependencies"); + List> includeFilters = includes.stream().map(filterFactory).collect(Collectors.toList()); + if (includeModuleDependencies != null) { + includeFilters = new ArrayList<>(includeFilters); + includeFilters.add(Library::isLocal); + } + List> excludeFilters = excludes.stream().map(filterFactory).collect(Collectors.toList()); + if (excludeModuleDependencies != null) { + excludeFilters = new ArrayList<>(excludeFilters); + excludeFilters.add(Library::isLocal); + } + return new IncludeExcludeContentSelector<>(layer, includeFilters, excludeFilters); + } + private List getChildNodeTextContent(Element element, String tagName) { List patterns = new ArrayList<>(); NodeList nodes = element.getElementsByTagName(tagName); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/xsd/layers-2.4.xsd b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/xsd/layers-2.4.xsd new file mode 100644 index 0000000000..57eac0d6b9 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/xsd/layers-2.4.xsd @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ArtifactsLibrariesTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ArtifactsLibrariesTests.java index 7c228ade0e..022affaaec 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ArtifactsLibrariesTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ArtifactsLibrariesTests.java @@ -27,6 +27,7 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.handler.ArtifactHandler; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -74,7 +75,7 @@ class ArtifactsLibrariesTests { @BeforeEach void setup() { this.artifacts = Collections.singleton(this.artifact); - this.libs = new ArtifactsLibraries(this.artifacts, null, mock(Log.class)); + this.libs = new ArtifactsLibraries(this.artifacts, Collections.emptyList(), null, mock(Log.class)); given(this.artifactHandler.getExtension()).willReturn("jar"); } @@ -101,7 +102,8 @@ class ArtifactsLibrariesTests { Dependency unpack = new Dependency(); unpack.setGroupId("gid"); unpack.setArtifactId("aid"); - this.libs = new ArtifactsLibraries(this.artifacts, Collections.singleton(unpack), mock(Log.class)); + this.libs = new ArtifactsLibraries(this.artifacts, Collections.emptyList(), Collections.singleton(unpack), + mock(Log.class)); this.libs.doWithLibraries(this.callback); verify(this.callback).library(this.libraryCaptor.capture()); assertThat(this.libraryCaptor.getValue().isUnpackRequired()).isTrue(); @@ -124,7 +126,7 @@ class ArtifactsLibrariesTests { given(artifact2.getFile()).willReturn(new File("a")); given(artifact2.getArtifactHandler()).willReturn(this.artifactHandler); this.artifacts = new LinkedHashSet<>(Arrays.asList(artifact1, artifact2)); - this.libs = new ArtifactsLibraries(this.artifacts, null, mock(Log.class)); + this.libs = new ArtifactsLibraries(this.artifacts, Collections.emptyList(), null, mock(Log.class)); this.libs.doWithLibraries(this.callback); verify(this.callback, times(2)).library(this.libraryCaptor.capture()); assertThat(this.libraryCaptor.getAllValues().get(0).getName()).isEqualTo("g1-artifact-1.0.jar"); @@ -140,8 +142,43 @@ class ArtifactsLibrariesTests { given(snapshotArtifact.getFile()).willReturn(new File("a")); given(snapshotArtifact.getArtifactHandler()).willReturn(this.artifactHandler); this.artifacts = Collections.singleton(snapshotArtifact); - new ArtifactsLibraries(this.artifacts, null, mock(Log.class)).doWithLibraries( - (library) -> assertThat(library.getCoordinates().getVersion()).isEqualTo("1.0-SNAPSHOT")); + new ArtifactsLibraries(this.artifacts, Collections.emptyList(), null, mock(Log.class)) + .doWithLibraries((library) -> { + assertThat(library.isLocal()).isFalse(); + assertThat(library.getCoordinates().getVersion()).isEqualTo("1.0-SNAPSHOT"); + }); + } + + @Test + void artifactForLocalProjectProducesLocalLibrary() throws IOException { + Artifact artifact = mock(Artifact.class); + given(artifact.getScope()).willReturn("compile"); + given(artifact.getArtifactId()).willReturn("artifact"); + given(artifact.getBaseVersion()).willReturn("1.0-SNAPSHOT"); + given(artifact.getFile()).willReturn(new File("a")); + given(artifact.getArtifactHandler()).willReturn(this.artifactHandler); + MavenProject mavenProject = mock(MavenProject.class); + given(mavenProject.getArtifact()).willReturn(artifact); + this.artifacts = Collections.singleton(artifact); + new ArtifactsLibraries(this.artifacts, Collections.singleton(mavenProject), null, mock(Log.class)) + .doWithLibraries((library) -> assertThat(library.isLocal()).isTrue()); + } + + @Test + void attachedArtifactForLocalProjectProducesLocalLibrary() throws IOException { + MavenProject mavenProject = mock(MavenProject.class); + Artifact artifact = mock(Artifact.class); + given(mavenProject.getArtifact()).willReturn(artifact); + Artifact attachedArtifact = mock(Artifact.class); + given(attachedArtifact.getScope()).willReturn("compile"); + given(attachedArtifact.getArtifactId()).willReturn("attached-artifact"); + given(attachedArtifact.getBaseVersion()).willReturn("1.0-SNAPSHOT"); + given(attachedArtifact.getFile()).willReturn(new File("a")); + given(attachedArtifact.getArtifactHandler()).willReturn(this.artifactHandler); + given(mavenProject.getAttachedArtifacts()).willReturn(Collections.singletonList(attachedArtifact)); + this.artifacts = Collections.singleton(attachedArtifact); + new ArtifactsLibraries(this.artifacts, Collections.singleton(mavenProject), null, mock(Log.class)) + .doWithLibraries((library) -> assertThat(library.isLocal()).isTrue()); } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/CustomLayersProviderTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/CustomLayersProviderTests.java index a4aac074ca..f67f3b7d10 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/CustomLayersProviderTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/CustomLayersProviderTests.java @@ -57,9 +57,12 @@ public class CustomLayersProviderTests { Library snapshot = mockLibrary("test-SNAPSHOT.jar", "org.foo", "1.0.0-SNAPSHOT"); Library groupId = mockLibrary("my-library", "com.acme", null); Library otherDependency = mockLibrary("other-library", "org.foo", null); + Library localSnapshotDependency = mockLibrary("local-library", "org.foo", "1.0-SNAPSHOT"); + given(localSnapshotDependency.isLocal()).willReturn(true); assertThat(layers.getLayer(snapshot).toString()).isEqualTo("snapshot-dependencies"); assertThat(layers.getLayer(groupId).toString()).isEqualTo("my-deps"); assertThat(layers.getLayer(otherDependency).toString()).isEqualTo("my-dependencies-name"); + assertThat(layers.getLayer(localSnapshotDependency).toString()).isEqualTo("application"); assertThat(layers.getLayer("META-INF/resources/test.css").toString()).isEqualTo("my-resources"); assertThat(layers.getLayer("application.yml").toString()).isEqualTo("configuration"); assertThat(layers.getLayer("test").toString()).isEqualTo("application"); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/resources/dependencies-layer-no-filter.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/resources/dependencies-layer-no-filter.xml index fb45f1d7c2..d0ed724ac5 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/resources/dependencies-layer-no-filter.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/resources/dependencies-layer-no-filter.xml @@ -1,7 +1,7 @@ + https://www.springframework.org/schema/boot/layers/layers-2.4.xsd"> diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/resources/layers.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/resources/layers.xml index 64a7e9eb18..929e2b9f10 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/resources/layers.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/resources/layers.xml @@ -1,7 +1,7 @@ + https://www.springframework.org/schema/boot/layers/layers-2.4.xsd"> META-INF/resources/** @@ -15,6 +15,10 @@ *:*:*-SNAPSHOT + + + + com.acme:* diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/resources/resource-layer-no-filter.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/resources/resource-layer-no-filter.xml index 089ba63ff1..983fc85912 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/resources/resource-layer-no-filter.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/resources/resource-layer-no-filter.xml @@ -1,7 +1,7 @@ + https://www.springframework.org/schema/boot/layers/layers-2.4.xsd">