Add group discriminant in case of conflict
Prior to this commit, the repackage goal silently ignored the case of two libraries having the same name and version but a different group. As a result, the second library was overwriting the first one in the repackaged jar. This commit adds support for custom Library names and updates the Maven and Gradle plugins so that the name includes the group ID when there would otherwise be a duplicate. Fixes gh-1475
This commit is contained in:
committed by
Phillip Webb
parent
449752c9e2
commit
f46fe32264
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>acme-lib</artifactId>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot.maven.it</groupId>
|
||||
<artifactId>jar-lib-name-conflict</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>4.0.5.RELEASE</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.boot.maven.it.another</groupId>
|
||||
<artifactId>acme-lib</artifactId>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot.maven.it</groupId>
|
||||
<artifactId>jar-lib-name-conflict</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.boot.maven.it</groupId>
|
||||
<artifactId>jar-lib-name-conflict</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
<module>acme-lib</module>
|
||||
<module>another-acme-lib</module>
|
||||
<module>test-project</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.boot.maven.it</groupId>
|
||||
<artifactId>test-project</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>@project.groupId@</groupId>
|
||||
<artifactId>@project.artifactId@</artifactId>
|
||||
<version>@project.version@</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Not-Used>Foo</Not-Used>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<!-- Two dependencies with the same artifactId -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot.maven.it</groupId>
|
||||
<artifactId>acme-lib</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot.maven.it.another</groupId>
|
||||
<artifactId>acme-lib</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.test;
|
||||
|
||||
public class SampleApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import java.io.*;
|
||||
import org.springframework.boot.maven.*;
|
||||
|
||||
File f = new File(basedir, "test-project/target/test-project-0.0.1.BUILD-SNAPSHOT.jar")
|
||||
new Verify.JarArchiveVerification(f, Verify.SAMPLE_APP) {
|
||||
@Override
|
||||
protected void verifyZipEntries(Verify.ArchiveVerifier verifier) throws Exception {
|
||||
super.verifyZipEntries(verifier)
|
||||
verifier.assertHasEntryNameStartingWith("lib/org.springframework.boot.maven.it-acme-lib-0.0.1.BUILD-SNAPSHOT.jar")
|
||||
verifier.assertHasEntryNameStartingWith("lib/org.springframework.boot.maven.it.another-acme-lib-0.0.1.BUILD-SNAPSHOT.jar")
|
||||
}
|
||||
}.verify();
|
||||
|
||||
|
||||
@@ -20,11 +20,13 @@ import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
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.springframework.boot.loader.tools.Libraries;
|
||||
import org.springframework.boot.loader.tools.Library;
|
||||
import org.springframework.boot.loader.tools.LibraryCallback;
|
||||
@@ -51,22 +53,44 @@ public class ArtifactsLibraries implements Libraries {
|
||||
|
||||
private final Collection<Dependency> unpacks;
|
||||
|
||||
public ArtifactsLibraries(Set<Artifact> artifacts, Collection<Dependency> unpacks) {
|
||||
private final Log log;
|
||||
|
||||
public ArtifactsLibraries(Set<Artifact> artifacts, Collection<Dependency> unpacks,
|
||||
Log log) {
|
||||
this.artifacts = artifacts;
|
||||
this.unpacks = unpacks;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWithLibraries(LibraryCallback callback) throws IOException {
|
||||
Set<String> duplicates = getDuplicates(this.artifacts);
|
||||
for (Artifact artifact : this.artifacts) {
|
||||
LibraryScope scope = SCOPES.get(artifact.getScope());
|
||||
if (scope != null && artifact.getFile() != null) {
|
||||
callback.library(new Library(artifact.getFile(), scope,
|
||||
String name = artifact.getFile().getName();
|
||||
if (duplicates.contains(name)) {
|
||||
this.log.debug("Duplicate found: " + name);
|
||||
name = artifact.getGroupId() + "-" + name;
|
||||
this.log.debug("Renamed to: " + name);
|
||||
}
|
||||
callback.library(new Library(name, artifact.getFile(), scope,
|
||||
isUnpackRequired(artifact)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> getDuplicates(Set<Artifact> artifacts) {
|
||||
Set<String> duplicates = new HashSet<String>();
|
||||
Set<String> seen = new HashSet<String>();
|
||||
for (Artifact artifact : artifacts) {
|
||||
if (artifact.getFile() != null && !seen.add(artifact.getFile().getName())) {
|
||||
duplicates.add(artifact.getFile().getName());
|
||||
}
|
||||
}
|
||||
return duplicates;
|
||||
}
|
||||
|
||||
private boolean isUnpackRequired(Artifact artifact) {
|
||||
if (this.unpacks != null) {
|
||||
for (Dependency unpack : this.unpacks) {
|
||||
@@ -78,4 +102,5 @@ public class ArtifactsLibraries implements Libraries {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -153,7 +153,8 @@ public class RepackageMojo extends AbstractDependencyFilterMojo {
|
||||
Set<Artifact> artifacts = filterDependencies(this.project.getArtifacts(),
|
||||
getFilters());
|
||||
|
||||
Libraries libraries = new ArtifactsLibraries(artifacts, this.requiresUnpack);
|
||||
Libraries libraries = new ArtifactsLibraries(artifacts, this.requiresUnpack,
|
||||
getLog());
|
||||
try {
|
||||
repackager.repackage(target, libraries);
|
||||
}
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
package org.springframework.boot.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
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.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -35,6 +38,8 @@ import org.springframework.boot.loader.tools.LibraryScope;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
@@ -63,7 +68,7 @@ public class ArtifactsLibrariesTests {
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
this.artifacts = Collections.singleton(this.artifact);
|
||||
this.libs = new ArtifactsLibraries(this.artifacts, null);
|
||||
this.libs = new ArtifactsLibraries(this.artifacts, null, mock(Log.class));
|
||||
given(this.artifact.getFile()).willReturn(this.file);
|
||||
}
|
||||
|
||||
@@ -88,9 +93,31 @@ public class ArtifactsLibrariesTests {
|
||||
Dependency unpack = new Dependency();
|
||||
unpack.setGroupId("gid");
|
||||
unpack.setArtifactId("aid");
|
||||
this.libs = new ArtifactsLibraries(this.artifacts, Collections.singleton(unpack));
|
||||
this.libs = new ArtifactsLibraries(this.artifacts, Collections.singleton(unpack),
|
||||
mock(Log.class));
|
||||
this.libs.doWithLibraries(this.callback);
|
||||
verify(this.callback).library(this.libraryCaptor.capture());
|
||||
assertThat(this.libraryCaptor.getValue().isUnpackRequired(), equalTo(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void renamesDuplicates() throws Exception {
|
||||
Artifact artifact1 = mock(Artifact.class);
|
||||
Artifact artifact2 = mock(Artifact.class);
|
||||
given(artifact1.getType()).willReturn("jar");
|
||||
given(artifact1.getScope()).willReturn("compile");
|
||||
given(artifact1.getGroupId()).willReturn("g1");
|
||||
given(artifact1.getFile()).willReturn(new File("a"));
|
||||
given(artifact2.getType()).willReturn("jar");
|
||||
given(artifact2.getScope()).willReturn("compile");
|
||||
given(artifact2.getGroupId()).willReturn("g2");
|
||||
given(artifact2.getFile()).willReturn(new File("a"));
|
||||
this.artifacts = new LinkedHashSet<Artifact>(Arrays.asList(artifact1, artifact2));
|
||||
this.libs = new ArtifactsLibraries(this.artifacts, 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(), equalTo("g1-a"));
|
||||
assertThat(this.libraryCaptor.getAllValues().get(1).getName(), equalTo("g2-a"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user