diff --git a/pom.xml b/pom.xml
index 030c6ce8..0d42cec0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -108,10 +108,9 @@ under the License.
org.eclipse.aether
- aether-api
+ aether-util
1.0.0.v20140518
- provided
org.slf4j
diff --git a/src/it/projects/dependency-sets/massembly-1008/pom.xml b/src/it/projects/dependency-sets/massembly-1008/pom.xml
new file mode 100644
index 00000000..82e605c5
--- /dev/null
+++ b/src/it/projects/dependency-sets/massembly-1008/pom.xml
@@ -0,0 +1,71 @@
+
+
+
+ 4.0.0
+
+ org.apache.maven.plugin.assembly.test
+ it-project-parent
+ 1
+
+
+ test
+ massembly-1008
+ 1
+
+ https://issues.apache.org/jira/browse/MASSEMBLY-1008
+
+
+ UTF-8
+
+
+
+ com.google.inject
+ guice
+ 6.0.0
+
+
+ com.google.guava
+ guava
+ 31.0.1-jre
+ test
+
+
+
+
+
+ maven-assembly-plugin
+
+
+ assembly
+ package
+
+ single
+
+
+
+ src/main/assembly/bin.xml
+
+
+
+
+
+
+
+
diff --git a/src/it/projects/dependency-sets/massembly-1008/src/main/assembly/bin.xml b/src/it/projects/dependency-sets/massembly-1008/src/main/assembly/bin.xml
new file mode 100644
index 00000000..230d3c93
--- /dev/null
+++ b/src/it/projects/dependency-sets/massembly-1008/src/main/assembly/bin.xml
@@ -0,0 +1,33 @@
+
+
+ bin
+
+ dir
+
+ false
+
+
+ false
+ runtime
+
+ false
+
+
+
diff --git a/src/it/projects/dependency-sets/massembly-1008/verify.groovy b/src/it/projects/dependency-sets/massembly-1008/verify.groovy
new file mode 100644
index 00000000..55d7b281
--- /dev/null
+++ b/src/it/projects/dependency-sets/massembly-1008/verify.groovy
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.
+ */
+
+import java.io.*;
+
+def expectedFilenames = [
+ "aopalliance-1.0.jar",
+ "checker-qual-3.12.0.jar",
+ "error_prone_annotations-2.7.1.jar",
+ "failureaccess-1.0.1.jar",
+ "guava-31.0.1-jre.jar",
+ "guice-6.0.0.jar",
+ "j2objc-annotations-1.3.jar",
+ "jakarta.inject-api-2.0.1.jar",
+ "javax.inject-1.jar",
+ "jsr305-3.0.2.jar",
+ "listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar"
+]
+
+File assemblyBasedir = new File( basedir, "target/massembly-1008-1-bin/" )
+
+assert assemblyBasedir.listFiles().length == expectedFilenames.size()
+
+for ( fileName in expectedFilenames )
+{
+ File file = new File( assemblyBasedir, fileName )
+ assert file.isFile() // exists and is file
+}
+
+// defined set vs listed set: same cardinality and all present: OK
+
+return true
diff --git a/src/main/java/org/apache/maven/plugins/assembly/artifact/DefaultDependencyResolver.java b/src/main/java/org/apache/maven/plugins/assembly/artifact/DefaultDependencyResolver.java
index 9081af35..6bbd7b00 100644
--- a/src/main/java/org/apache/maven/plugins/assembly/artifact/DefaultDependencyResolver.java
+++ b/src/main/java/org/apache/maven/plugins/assembly/artifact/DefaultDependencyResolver.java
@@ -22,15 +22,24 @@
import javax.inject.Named;
import javax.inject.Singleton;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.maven.RepositoryUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.versioning.VersionRange;
+import org.apache.maven.model.DependencyManagement;
import org.apache.maven.plugins.assembly.AssemblerConfigurationSource;
import org.apache.maven.plugins.assembly.archive.ArchiveCreationException;
import org.apache.maven.plugins.assembly.archive.phase.ModuleSetAssemblyPhase;
@@ -40,6 +49,17 @@
import org.apache.maven.plugins.assembly.model.ModuleSet;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.StringUtils;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.collection.CollectRequest;
+import org.eclipse.aether.graph.DefaultDependencyNode;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.graph.DependencyFilter;
+import org.eclipse.aether.graph.DependencyNode;
+import org.eclipse.aether.graph.DependencyVisitor;
+import org.eclipse.aether.resolution.DependencyRequest;
+import org.eclipse.aether.resolution.DependencyResult;
+import org.eclipse.aether.util.filter.DependencyFilterUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,7 +67,6 @@
/**
* @author jdcasey
- *
*/
@Singleton
@Named
@@ -56,9 +75,12 @@ public class DefaultDependencyResolver implements DependencyResolver {
private final ArtifactHandlerManager artifactHandlerManager;
+ private final RepositorySystem repositorySystem;
+
@Inject
- public DefaultDependencyResolver(ArtifactHandlerManager artifactHandlerManager) {
+ public DefaultDependencyResolver(ArtifactHandlerManager artifactHandlerManager, RepositorySystem repositorySystem) {
this.artifactHandlerManager = requireNonNull(artifactHandlerManager);
+ this.repositorySystem = requireNonNull(repositorySystem);
}
@Override
@@ -75,7 +97,8 @@ public Map> resolveDependencySets(
final MavenProject currentProject = configSource.getProject();
final ResolutionManagementInfo info = new ResolutionManagementInfo();
- updateDependencySetResolutionRequirements(dependencySet, info, currentProject);
+ updateDependencySetResolutionRequirements(
+ configSource.getMavenSession().getRepositorySession(), dependencySet, info, currentProject);
updateModuleSetResolutionRequirements(moduleSet, dependencySet, info, configSource);
result.put(dependencySet, info.getArtifacts());
@@ -96,7 +119,8 @@ public Map> resolveDependencySets(
final MavenProject currentProject = configSource.getProject();
final ResolutionManagementInfo info = new ResolutionManagementInfo();
- updateDependencySetResolutionRequirements(dependencySet, info, currentProject);
+ updateDependencySetResolutionRequirements(
+ configSource.getMavenSession().getRepositorySession(), dependencySet, info, currentProject);
result.put(dependencySet, info.getArtifacts());
}
@@ -127,7 +151,10 @@ void updateModuleSetResolutionRequirements(
if (binaries.isIncludeDependencies()) {
updateDependencySetResolutionRequirements(
- dependencySet, requirements, projects.toArray(new MavenProject[0]));
+ configSource.getMavenSession().getRepositorySession(),
+ dependencySet,
+ requirements,
+ projects.toArray(new MavenProject[0]));
}
}
}
@@ -149,7 +176,10 @@ private Artifact createArtifact(String groupId, String artifactId, String versio
}
void updateDependencySetResolutionRequirements(
- final DependencySet set, final ResolutionManagementInfo requirements, final MavenProject... projects)
+ RepositorySystemSession systemSession,
+ final DependencySet set,
+ final ResolutionManagementInfo requirements,
+ final MavenProject... projects)
throws DependencyResolutionException {
for (final MavenProject project : projects) {
if (project == null) {
@@ -158,14 +188,91 @@ void updateDependencySetResolutionRequirements(
Set dependencyArtifacts = null;
if (set.isUseTransitiveDependencies()) {
- dependencyArtifacts = project.getArtifacts();
+ try {
+ // we need resolve project again according to requested scope
+ dependencyArtifacts = resolveTransitive(systemSession, set.getScope(), project);
+ } catch (org.eclipse.aether.resolution.DependencyResolutionException e) {
+ throw new DependencyResolutionException(e.getMessage(), e);
+ }
} else {
+ // FIXME remove using deprecated method
dependencyArtifacts = project.getDependencyArtifacts();
}
requirements.addArtifacts(dependencyArtifacts);
- LOGGER.debug("Dependencies for project: " + project.getId() + " are:\n"
- + StringUtils.join(dependencyArtifacts.iterator(), "\n"));
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug(
+ "Dependencies for project: {} are:\n{}",
+ project.getId(),
+ StringUtils.join(dependencyArtifacts.iterator(), "\n"));
+ }
}
}
+
+ private Set resolveTransitive(
+ RepositorySystemSession repositorySession, String scope, MavenProject project)
+ throws org.eclipse.aether.resolution.DependencyResolutionException {
+
+ // scope dependency filter
+ DependencyFilter scoopeDependencyFilter = DependencyFilterUtils.classpathFilter(scope);
+
+ // get project dependencies filtered by requested scope
+ List dependencies = project.getDependencies().stream()
+ .map(d -> RepositoryUtils.toDependency(d, repositorySession.getArtifactTypeRegistry()))
+ .filter(d -> scoopeDependencyFilter.accept(new DefaultDependencyNode(d), null))
+ .collect(Collectors.toList());
+
+ List managedDependencies = Optional.ofNullable(project.getDependencyManagement())
+ .map(DependencyManagement::getDependencies)
+ .map(list -> list.stream()
+ .map(d -> RepositoryUtils.toDependency(d, repositorySession.getArtifactTypeRegistry()))
+ .collect(Collectors.toList()))
+ .orElse(null);
+
+ CollectRequest collectRequest = new CollectRequest();
+ collectRequest.setManagedDependencies(managedDependencies);
+ collectRequest.setRepositories(project.getRemoteProjectRepositories());
+ collectRequest.setDependencies(dependencies);
+ collectRequest.setRootArtifact(RepositoryUtils.toArtifact(project.getArtifact()));
+
+ DependencyRequest request = new DependencyRequest(collectRequest, scoopeDependencyFilter);
+
+ DependencyResult dependencyResult = repositorySystem.resolveDependencies(repositorySession, request);
+
+ // cache for artifact mapping
+ Map aetherToMavenArtifacts = new HashMap<>();
+ Deque stack = new ArrayDeque<>();
+ stack.push(project.getArtifact().getId());
+
+ Set artifacts = new HashSet<>();
+
+ // we need rebuild artifact dependencyTrail - it is used by useTransitiveFiltering
+ dependencyResult.getRoot().accept(new DependencyVisitor() {
+ @Override
+ public boolean visitEnter(DependencyNode node) {
+ if (node.getDependency() != null) {
+ stack.push(aetherToMavenArtifacts
+ .computeIfAbsent(node.getDependency().getArtifact(), RepositoryUtils::toArtifact)
+ .getId());
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visitLeave(DependencyNode node) {
+ if (node.getDependency() != null) {
+ Artifact artifact = aetherToMavenArtifacts.computeIfAbsent(
+ node.getDependency().getArtifact(), RepositoryUtils::toArtifact);
+ List depTrail = new ArrayList<>();
+ stack.descendingIterator().forEachRemaining(depTrail::add);
+ stack.pop();
+ artifact.setDependencyTrail(depTrail);
+ artifacts.add(artifact);
+ }
+ return true;
+ }
+ });
+
+ return artifacts;
+ }
}
diff --git a/src/test/java/org/apache/maven/plugins/assembly/artifact/DefaultDependencyResolverTest.java b/src/test/java/org/apache/maven/plugins/assembly/artifact/DefaultDependencyResolverTest.java
index dda82cb1..fb311754 100644
--- a/src/test/java/org/apache/maven/plugins/assembly/artifact/DefaultDependencyResolverTest.java
+++ b/src/test/java/org/apache/maven/plugins/assembly/artifact/DefaultDependencyResolverTest.java
@@ -27,55 +27,84 @@
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
+import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.versioning.VersionRange;
+import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Model;
import org.apache.maven.plugins.assembly.AssemblerConfigurationSource;
import org.apache.maven.plugins.assembly.model.DependencySet;
import org.apache.maven.plugins.assembly.model.ModuleBinaries;
import org.apache.maven.plugins.assembly.model.ModuleSet;
import org.apache.maven.project.MavenProject;
-import org.codehaus.plexus.ContainerConfiguration;
-import org.codehaus.plexus.PlexusConstants;
-import org.codehaus.plexus.PlexusTestCase;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.graph.DefaultDependencyNode;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.resolution.DependencyRequest;
+import org.eclipse.aether.resolution.DependencyResult;
import org.junit.Test;
-
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-public class DefaultDependencyResolverTest extends PlexusTestCase {
+@RunWith(MockitoJUnitRunner.class)
+public class DefaultDependencyResolverTest {
- private DefaultDependencyResolver resolver;
+ @Mock
+ private ArtifactHandlerManager artifactHandlerManager;
- protected void customizeContainerConfiguration(ContainerConfiguration configuration) {
- configuration.setClassPathScanning(PlexusConstants.SCANNING_CACHE).setAutoWiring(true);
- }
+ @Mock
+ private RepositorySystem repositorySystem;
- @Override
- public void setUp() throws Exception {
- super.setUp();
+ @Mock
+ private RepositorySystemSession systemSession;
- resolver = (DefaultDependencyResolver) lookup(DependencyResolver.class);
- }
+ @InjectMocks
+ private DefaultDependencyResolver resolver;
@Test
- public void test_getDependencySetResolutionRequirements_transitive() throws DependencyResolutionException {
+ public void test_getDependencySetResolutionRequirements_transitive() throws Exception {
final DependencySet ds = new DependencySet();
ds.setScope(Artifact.SCOPE_SYSTEM);
ds.setUseTransitiveDependencies(true);
final MavenProject project = createMavenProject("main-group", "main-artifact", "1", null);
- Set dependencyArtifacts = new HashSet<>();
- dependencyArtifacts.add(newArtifact("g.id", "a-id", "1"));
- Set artifacts = new HashSet<>(dependencyArtifacts);
+ Set artifacts = new HashSet<>();
+ artifacts.add(newArtifact("g.id", "a-id", "1"));
artifacts.add(newArtifact("g.id", "a-id-2", "2"));
- project.setArtifacts(artifacts);
- project.setDependencyArtifacts(dependencyArtifacts);
+
+ DefaultDependencyNode node1 = new DefaultDependencyNode(
+ new Dependency(new org.eclipse.aether.artifact.DefaultArtifact("g.id:a-id:1"), "runtime"));
+ DefaultDependencyNode node2 = new DefaultDependencyNode(
+ new Dependency(new org.eclipse.aether.artifact.DefaultArtifact("g.id:a-id-2:2"), "runtime"));
+
+ DependencyResult dependencyResult = new DependencyResult(new DependencyRequest());
+ DefaultDependencyNode rootDependencyNode = new DefaultDependencyNode((Dependency) null);
+ rootDependencyNode.setChildren(Arrays.asList(node1, node2));
+ dependencyResult.setRoot(rootDependencyNode);
+
+ when(repositorySystem.resolveDependencies(eq(systemSession), any())).thenReturn(dependencyResult);
final ResolutionManagementInfo info = new ResolutionManagementInfo();
- resolver.updateDependencySetResolutionRequirements(ds, info, project);
+ resolver.updateDependencySetResolutionRequirements(systemSession, ds, info, project);
assertEquals(artifacts, info.getArtifacts());
+ // dependencyTrail is set
+ info.getArtifacts().forEach(artifact -> {
+ assertEquals(2, artifact.getDependencyTrail().size());
+ assertEquals(
+ project.getArtifact().getId(), artifact.getDependencyTrail().get(0));
+ assertEquals(artifact.getId(), artifact.getDependencyTrail().get(1));
+ });
}
@Test
@@ -94,7 +123,7 @@ public void test_getDependencySetResolutionRequirements_nonTransitive() throws D
project.setDependencyArtifacts(dependencyArtifacts);
final ResolutionManagementInfo info = new ResolutionManagementInfo();
- resolver.updateDependencySetResolutionRequirements(ds, info, project);
+ resolver.updateDependencySetResolutionRequirements(systemSession, ds, info, project);
assertEquals(dependencyArtifacts, info.getArtifacts());
}
@@ -118,7 +147,7 @@ public void test_getModuleSetResolutionRequirements_withoutBinaries() throws Dep
}
@Test
- public void test_getModuleSetResolutionRequirements_includeDeps() throws DependencyResolutionException {
+ public void test_getModuleSetResolutionRequirements_includeDeps() throws Exception {
final File rootDir = new File("root");
final MavenProject project = createMavenProject("main-group", "main-artifact", "1", rootDir);
final MavenProject module1 = createMavenProject("main-group", "module-1", "1", new File(rootDir, "module-1"));
@@ -135,6 +164,9 @@ public void test_getModuleSetResolutionRequirements_includeDeps() throws Depende
final AssemblerConfigurationSource cs = mock(AssemblerConfigurationSource.class);
when(cs.getReactorProjects()).thenReturn(Arrays.asList(project, module1, module2));
when(cs.getProject()).thenReturn(project);
+ MavenSession mavenSession = mock(MavenSession.class);
+ when(cs.getMavenSession()).thenReturn(mavenSession);
+ when(mavenSession.getRepositorySession()).thenReturn(systemSession);
final ResolutionManagementInfo info = new ResolutionManagementInfo();
@@ -142,8 +174,19 @@ public void test_getModuleSetResolutionRequirements_includeDeps() throws Depende
final ModuleBinaries mb = new ModuleBinaries();
mb.setIncludeDependencies(true);
ms.setBinaries(mb);
+ // FIXME - this is not checked - because ms.UseAllReactorProjects is false
ms.addInclude("*:module-1");
+ DefaultDependencyNode node1 = new DefaultDependencyNode(
+ new Dependency(new org.eclipse.aether.artifact.DefaultArtifact("group.id:module-1-dep:1"), "runtime"));
+
+ DependencyResult dependencyResult = new DependencyResult(new DependencyRequest());
+ DefaultDependencyNode rootDependencyNode = new DefaultDependencyNode((Dependency) null);
+ rootDependencyNode.setChildren(Collections.singletonList(node1));
+ dependencyResult.setRoot(rootDependencyNode);
+
+ when(repositorySystem.resolveDependencies(eq(systemSession), any())).thenReturn(dependencyResult);
+
resolver.updateModuleSetResolutionRequirements(ms, new DependencySet(), info, cs);
assertEquals(module1Artifacts, info.getArtifacts());