From a454008545f44fb86e5bae73cbcee27842e676e4 Mon Sep 17 00:00:00 2001 From: Kevin Conner Date: Mon, 1 May 2023 11:24:05 -0700 Subject: [PATCH] Remove extra dependency collection through Mojo annotation, fixes #354 Signed-off-by: Kevin Conner --- .../maven/CycloneDxAggregateMojo.java | 6 +-- .../org/cyclonedx/maven/CycloneDxMojo.java | 15 ++++--- .../cyclonedx/maven/CycloneDxPackageMojo.java | 4 +- .../DefaultProjectDependenciesConverter.java | 42 ++++++++++++++++--- .../maven/ProjectDependenciesConverter.java | 8 +++- 5 files changed, 56 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/cyclonedx/maven/CycloneDxAggregateMojo.java b/src/main/java/org/cyclonedx/maven/CycloneDxAggregateMojo.java index 447ffefb..a3e2c0c9 100644 --- a/src/main/java/org/cyclonedx/maven/CycloneDxAggregateMojo.java +++ b/src/main/java/org/cyclonedx/maven/CycloneDxAggregateMojo.java @@ -43,9 +43,7 @@ defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true, aggregator = true, - requiresOnline = true, - requiresDependencyCollection = ResolutionScope.TEST, - requiresDependencyResolution = ResolutionScope.TEST + requiresOnline = true ) public class CycloneDxAggregateMojo extends CycloneDxMojo { @Parameter(property = "reactorProjects", readonly = true, required = true) @@ -129,7 +127,7 @@ protected String extractComponentsAndDependencies(final Set topLevelComp components.put(projectBomComponent.getPurl(), projectBomComponent); topLevelComponents.add(projectBomComponent.getPurl()); - populateComponents(topLevelComponents, components, bomDependencies.getArtifacts(), doProjectDependencyAnalysis(mavenProject)); + populateComponents(topLevelComponents, components, bomDependencies.getArtifacts(), doProjectDependencyAnalysis(mavenProject, bomDependencies)); projectDependencies.forEach(dependencies::putIfAbsent); } diff --git a/src/main/java/org/cyclonedx/maven/CycloneDxMojo.java b/src/main/java/org/cyclonedx/maven/CycloneDxMojo.java index 463a0687..83294d31 100644 --- a/src/main/java/org/cyclonedx/maven/CycloneDxMojo.java +++ b/src/main/java/org/cyclonedx/maven/CycloneDxMojo.java @@ -18,6 +18,7 @@ */ package org.cyclonedx.maven; +import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; @@ -33,6 +34,7 @@ import org.cyclonedx.model.Component; import org.cyclonedx.model.Dependency; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -43,9 +45,7 @@ name = "makeBom", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true, - requiresOnline = true, - requiresDependencyCollection = ResolutionScope.TEST, - requiresDependencyResolution = ResolutionScope.TEST + requiresOnline = true ) public class CycloneDxMojo extends BaseCycloneDxMojo { @@ -82,9 +82,12 @@ private ProjectDependencyAnalyzer getProjectDependencyAnalyzer() throws MojoExec return dependencyAnalyzer; } - protected ProjectDependencyAnalysis doProjectDependencyAnalysis(MavenProject mavenProject) throws MojoExecutionException { + protected ProjectDependencyAnalysis doProjectDependencyAnalysis(final MavenProject mavenProject, final BomDependencies bomDependencies) throws MojoExecutionException { + final MavenProject localMavenProject = new MavenProject(mavenProject); + localMavenProject.setArtifacts(new LinkedHashSet<>(bomDependencies.getArtifacts().values())); + localMavenProject.setDependencyArtifacts(new LinkedHashSet<>(bomDependencies.getDependencyArtifacts().values())); try { - return getProjectDependencyAnalyzer().analyze(mavenProject); + return getProjectDependencyAnalyzer().analyze(localMavenProject); } catch (ProjectDependencyAnalyzerException pdae) { getLog().debug("Could not analyze " + mavenProject.getId(), pdae); // TODO should warn... } @@ -101,7 +104,7 @@ protected String extractComponentsAndDependencies(final Set topLevelComp components.put(projectBomComponent.getPurl(), projectBomComponent); topLevelComponents.add(projectBomComponent.getPurl()); - populateComponents(topLevelComponents, components, bomDependencies.getArtifacts(), doProjectDependencyAnalysis(getProject())); + populateComponents(topLevelComponents, components, bomDependencies.getArtifacts(), doProjectDependencyAnalysis(getProject(), bomDependencies)); projectDependencies.forEach(dependencies::putIfAbsent); diff --git a/src/main/java/org/cyclonedx/maven/CycloneDxPackageMojo.java b/src/main/java/org/cyclonedx/maven/CycloneDxPackageMojo.java index 3dbb3182..740d808f 100644 --- a/src/main/java/org/cyclonedx/maven/CycloneDxPackageMojo.java +++ b/src/main/java/org/cyclonedx/maven/CycloneDxPackageMojo.java @@ -43,9 +43,7 @@ defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true, aggregator = true, - requiresOnline = true, - requiresDependencyCollection = ResolutionScope.TEST, - requiresDependencyResolution = ResolutionScope.TEST + requiresOnline = true ) public class CycloneDxPackageMojo extends BaseCycloneDxMojo { @Parameter(property = "reactorProjects", readonly = true, required = true) diff --git a/src/main/java/org/cyclonedx/maven/DefaultProjectDependenciesConverter.java b/src/main/java/org/cyclonedx/maven/DefaultProjectDependenciesConverter.java index d2db0e12..3b00edaf 100644 --- a/src/main/java/org/cyclonedx/maven/DefaultProjectDependenciesConverter.java +++ b/src/main/java/org/cyclonedx/maven/DefaultProjectDependenciesConverter.java @@ -26,6 +26,7 @@ import org.apache.maven.project.ProjectBuildingRequest; import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilder; import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilderException; +import org.apache.maven.shared.dependency.graph.internal.ConflictData; import org.apache.maven.shared.dependency.graph.internal.DefaultDependencyCollectorBuilder; import org.cyclonedx.model.Component; import org.cyclonedx.model.Dependency; @@ -38,6 +39,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.lang.reflect.Field; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; @@ -73,12 +75,13 @@ public BomDependencies extractBOMDependencies(MavenProject mavenProject, MavenDe final Map dependencies = new LinkedHashMap<>(); final Map mavenArtifacts = new LinkedHashMap<>(); + final Map mavenDependencyArtifacts = new LinkedHashMap<>(); try { final DelegatingRepositorySystem delegateRepositorySystem = new DelegatingRepositorySystem(aetherRepositorySystem); final DependencyCollectorBuilder dependencyCollectorBuilder = new DefaultDependencyCollectorBuilder(delegateRepositorySystem); final org.apache.maven.shared.dependency.graph.DependencyNode mavenRoot = dependencyCollectorBuilder.collectDependencyGraph(buildingRequest, null); - populateArtifactMap(mavenArtifacts, mavenRoot, false); + populateArtifactMap(mavenArtifacts, mavenDependencyArtifacts, mavenRoot, 0); final CollectResult collectResult = delegateRepositorySystem.getCollectResult(); if (collectResult == null) { @@ -95,16 +98,45 @@ public BomDependencies extractBOMDependencies(MavenProject mavenProject, MavenDe // rather than throwing an exception https://github.com/CycloneDX/cyclonedx-maven-plugin/issues/55 logger.warn("An error occurred building dependency graph: " + e.getMessage()); } - return new BomDependencies(dependencies, mavenArtifacts); + return new BomDependencies(dependencies, mavenArtifacts, mavenDependencyArtifacts); } - private void populateArtifactMap(final Map artifactMap, final org.apache.maven.shared.dependency.graph.DependencyNode node, final boolean resolve) { + private void populateArtifactMap(final Map artifactMap, final Map dependencyArtifactMap, final org.apache.maven.shared.dependency.graph.DependencyNode node, final int level) { + final ConflictData conflictData = getConflictData(node); + if ((conflictData != null) && (conflictData.getWinnerVersion() != null)) { + return; + } + final Artifact artifact = node.getArtifact(); final String purl = modelConverter.generatePackageUrl(artifact); - artifactMap.putIfAbsent(purl, artifact); + if (level > 0) { + artifactMap.putIfAbsent(purl, artifact); + } + if (level == 1) { + dependencyArtifactMap.putIfAbsent(purl, artifact); + } + final int childLevel = level + 1; for (org.apache.maven.shared.dependency.graph.DependencyNode child: node.getChildren()) { - populateArtifactMap(artifactMap, child, true); + populateArtifactMap(artifactMap, dependencyArtifactMap, child, childLevel); + } + } + + private ConflictData getConflictData(final org.apache.maven.shared.dependency.graph.DependencyNode node) { + if (!node.getChildren().isEmpty()) { + return null; + } + final Field field ; + try { + field = node.getClass().getDeclaredField("data"); + } catch (final NoSuchFieldException nsfe) { + return null; + } + field.setAccessible(true); + try { + return (ConflictData)field.get(node); + } catch (final IllegalAccessException iae) { + return null; } } diff --git a/src/main/java/org/cyclonedx/maven/ProjectDependenciesConverter.java b/src/main/java/org/cyclonedx/maven/ProjectDependenciesConverter.java index 1fa0f53d..906fb334 100644 --- a/src/main/java/org/cyclonedx/maven/ProjectDependenciesConverter.java +++ b/src/main/java/org/cyclonedx/maven/ProjectDependenciesConverter.java @@ -60,16 +60,22 @@ public MavenDependencyScopes(boolean compile, boolean provided, boolean runtime, public static class BomDependencies { private final Map dependencies; private final Map artifacts; + private final Map dependencyArtifacts; - public BomDependencies(final Map dependencies, final Map artifacts) { + public BomDependencies(final Map dependencies, final Map artifacts, final Map dependencyArtifacts) { this.dependencies = dependencies; this.artifacts = artifacts; + this.dependencyArtifacts = dependencyArtifacts; } public final Map getDependencies() { return dependencies; } + public final Map getDependencyArtifacts() { + return dependencyArtifacts; + } + public final Map getArtifacts() { return artifacts; }