This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch support-ivy-as-component-source
in repository https://gitbox.apache.org/repos/asf/ant-antlibs-cyclonedx.git
The following commit(s) were added to
refs/heads/support-ivy-as-component-source by this push:
new 3e052f5 calculate hashes for Ivy dependencies retrieved
3e052f5 is described below
commit 3e052f53c3b7640b68e73974aa74d0eb453a26a9
Author: Stefan Bodewig <[email protected]>
AuthorDate: Fri Aug 7 16:17:21 2026 +0200
calculate hashes for Ivy dependencies retrieved
---
src/main/org/apache/ant/cyclonedx/Component.java | 14 +++++
.../ant/cyclonedx/IvyModuleComponentResolver.java | 63 +++++++++++++++++++++-
2 files changed, 75 insertions(+), 2 deletions(-)
diff --git a/src/main/org/apache/ant/cyclonedx/Component.java
b/src/main/org/apache/ant/cyclonedx/Component.java
index e3fc9f7..4b51d7a 100644
--- a/src/main/org/apache/ant/cyclonedx/Component.java
+++ b/src/main/org/apache/ant/cyclonedx/Component.java
@@ -1109,6 +1109,7 @@ public class Component extends DataType {
private String externalConf;
private String resolveId;
private Reference antIvyEngineRef;
+ private String pattern;
/**
* Sets the configurations to include in the SBOM.
@@ -1191,5 +1192,18 @@ public class Component extends DataType {
String getExternalConf() {
return externalConf;
}
+
+ /**
+ * The retrieve pattern usde for retrieving the dependnecy artifacts.
+ *
+ * <p>Defaults to {@code ${ivy.retrieve.pattern}}.</p>
+ */
+ public void setPattern(String pattern) {
+ this.pattern = pattern;
+ }
+
+ String getPattern() {
+ return pattern;
+ }
}
}
diff --git a/src/main/org/apache/ant/cyclonedx/IvyModuleComponentResolver.java
b/src/main/org/apache/ant/cyclonedx/IvyModuleComponentResolver.java
index 79aca12..1c68e24 100644
--- a/src/main/org/apache/ant/cyclonedx/IvyModuleComponentResolver.java
+++ b/src/main/org/apache/ant/cyclonedx/IvyModuleComponentResolver.java
@@ -17,7 +17,9 @@
*/
package org.apache.ant.cyclonedx;
+import java.io.File;
import java.io.IOException;
+import java.text.ParseException;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
@@ -32,16 +34,21 @@ import java.util.stream.Stream;
import org.apache.ivy.Ivy;
import org.apache.ivy.ant.IvyAntSettings;
+import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.License;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.report.ArtifactDownloadReport;
import org.apache.ivy.core.report.ResolveReport;
import org.apache.ivy.core.resolve.IvyNode;
import org.apache.ivy.core.resolve.IvyNodeCallers.Caller;
+import org.apache.ivy.core.retrieve.RetrieveEngine;
+import org.apache.ivy.core.retrieve.RetrieveOptions;
import org.apache.ivy.core.settings.IvySettings;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.types.resources.URLResource;
import org.cyclonedx.model.Component.Scope;
@@ -93,10 +100,11 @@ class IvyModuleComponentResolver {
populateDependencyTree(settings, report, optionalModules,
externalModules);
fillFromModuleDescriptor(component, root, dependencyTree);
+ Map<ModuleRevisionId, File> componentFiles =
findDownloadedArtifacts(ivy, settings, root.getModuleRevisionId());
Collection<ModuleDescriptor> allDependencies =
getDependencies(dependencyTree, root);
return allDependencies.stream()
- .map(d -> toComponent(d, dependencyTree, optionalModules,
externalModules))
+ .map(d -> toComponent(d, dependencyTree, optionalModules,
externalModules, componentFiles))
.collect(Collectors.toList());
}
@@ -167,7 +175,8 @@ class IvyModuleComponentResolver {
private Component toComponent(ModuleDescriptor md,
Map<ModuleRevisionId, Set<IvyNode>>
dependencyTree,
Set<ModuleRevisionId> optionalModules,
- Set<ModuleRevisionId> externalModules) {
+ Set<ModuleRevisionId> externalModules,
+ Map<ModuleRevisionId, File> componentFiles) {
Component c = new Component();
c.setProject(project);
fillFromModuleDescriptor(c, md, dependencyTree);
@@ -177,6 +186,10 @@ class IvyModuleComponentResolver {
c.setScope(ComponentScope.from(Scope.OPTIONAL));
}
c.setIsExternal(externalModules.contains(mrid));
+ File f = componentFiles.get(mrid);
+ if (f != null) {
+ c.add(new FileResource(f));
+ }
return c;
}
@@ -295,6 +308,52 @@ class IvyModuleComponentResolver {
}
}
+ private Map<ModuleRevisionId, File> findDownloadedArtifacts(Ivy ivy,
+ IvySettings
settings,
+
ModuleRevisionId mrid) {
+ String pattern = ivyModule.getPattern();
+ if (pattern == null) {
+ pattern = settings.getVariable("ivy.retrieve.pattern");
+ }
+ if (pattern == null) {
+ project.log("no retrieve pattern, won't look for dependency
artifact files");
+ return Collections.emptyMap();
+ }
+
+ RetrieveEngine retrieveEngine = ivy.getRetrieveEngine();
+ if (retrieveEngine == null) {
+ project.log("no RetrieveEngine, won't look for dependency artifact
files");
+ return Collections.emptyMap();
+ }
+
+ RetrieveOptions opts = new RetrieveOptions();
+ String[] confs = includedConfigurations.isEmpty()
+ ? new String[] { "*" }
+ : includedConfigurations.toArray(new
String[includedConfigurations.size()]);
+ opts.setConfs(confs);
+ String resolveId = ivyModule.getResolveId();
+ if (resolveId != null) {
+ opts.setResolveId(resolveId);
+ }
+
+ try {
+ Map<ArtifactDownloadReport, Set<String>> artifacts =
+ retrieveEngine.determineArtifactsToCopy(mrid, pattern, opts);
+ Map<ModuleRevisionId, File> result = new HashMap<>();
+ for (ArtifactDownloadReport ar : artifacts.keySet()) {
+ File f = ar.getLocalFile();
+ if (f != null) {
+ Artifact a = ar.getArtifact();
+ result.put(a.getModuleRevisionId(), f);
+ }
+ }
+ return result;
+ } catch (ParseException | IOException e) {
+ project.log(e.getMessage(), Project.MSG_ERR);
+ throw new BuildException("syntax errors in ivy file: " + e, e);
+ }
+ }
+
private Set<String> confAsSet(String conf) {
if (conf == null) {
return Collections.emptySet();