This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ant-antlibs-cyclonedx.git
The following commit(s) were added to refs/heads/main by this push:
new 61e4d8b refactor sbomLink and ivyModule into a reusable componentdef
61e4d8b is described below
commit 61e4d8b2d942b7890ed7d42eb2fb4073f5e19f55
Author: Stefan Bodewig <[email protected]>
AuthorDate: Sun Aug 16 16:52:47 2026 +0200
refactor sbomLink and ivyModule into a reusable componentdef
---
build.xml | 74 ++---
changes.xml | 11 +-
docs/component.html | 301 +--------------------
docs/componentbom.html | 8 +-
docs/ivyModule.html | 246 +++++++++++++++++
docs/sbomLink.html | 98 +++++++
example/ant-cyclonedx-0.2alpha.cdx.diff | 4 +-
example/ant-cyclonedx-0.2alpha.cdx.json | 32 +--
example/ant-cyclonedx-0.2alpha.ivy.cdx.json | 32 +--
src/main/org/apache/ant/cyclonedx/Component.java | 217 +--------------
.../apache/ant/cyclonedx/ComponentResolver.java | 41 +++
.../ant/cyclonedx/IvyModuleComponentResolver.java | 136 ++++++++--
.../ant/cyclonedx/SbomLinkComponentResolver.java | 35 ++-
src/main/org/apache/ant/cyclonedx/antlib.xml | 9 +
src/tests/antunit/component-ivymodule-test.xml | 20 +-
src/tests/antunit/component-sbomlink-test.xml | 28 +-
src/tests/antunit/component-test.xml | 10 +-
17 files changed, 662 insertions(+), 640 deletions(-)
diff --git a/build.xml b/build.xml
index c6fc8b8..b439683 100644
--- a/build.xml
+++ b/build.xml
@@ -100,10 +100,10 @@ under the License.
<target name="define-cyclonedx-components"
depends="define-core-ant-components"
- if="can.use.cyclonedx">
+ if="can.use.cyclonedx"
+ xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<cdx:externalreferenceset
- id="antlib-ext-refs"
- xmlns:cdx="antlib:org.apache.ant.cyclonedx">
+ id="antlib-ext-refs">
<externalReference
type="VCS"
url="https://gitbox.apache.org/repos/asf/ant-antlibs-cyclonedx.git"/>
@@ -118,7 +118,8 @@ under the License.
<target name="create-antlib-sbom-ivy"
depends="define-cyclonedx-components"
- if="can.use.cyclonedx">
+ if="can.use.cyclonedx"
+ xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<uptodate property="antlib-sbom-ok"
targetfile="${build.lib}/${artifact.stub}.ivy.cdx.json">
<srcresources>
@@ -134,13 +135,12 @@ under the License.
useComponentSupplier="true"
useComponentManufacturer="true"
unless:set="antlib-sbom-ok"
- xmlns:unless="ant:unless"
- xmlns:cdx="antlib:org.apache.ant.cyclonedx">
+ xmlns:unless="ant:unless">
<component
description="Apache CycloneDX Antlib"
publisher="The Apache Software Foundation"
supplierIsManufacturer="true">
- <ivymodule conf="default,provided" externalConf="provided">
+ <cdx:ivyModule conf="default,provided" externalConf="provided">
<templateComponent refid="ant"/>
<templateComponent refid="ant-launcher"/>
<templateComponent
@@ -171,7 +171,7 @@ under the License.
type="ADVISORIES"
url="https://ant.apache.org/ivy/security.html"/>
</templateComponent>
- </ivymodule>
+ </cdx:ivyModule>
<file file="${jarname}"/>
<supplier refid="ant-pmc"/>
<license refid="apache-2"/>
@@ -185,7 +185,8 @@ under the License.
<target name="create-antlib-sbom"
depends="define-cyclonedx-components"
- if="can.use.cyclonedx">
+ if="can.use.cyclonedx"
+ xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<uptodate property="antlib-sbom-ok"
targetfile="${build.lib}/${artifact.stub}.cdx.json">
<srcresources>
@@ -201,8 +202,7 @@ under the License.
useComponentSupplier="true"
useComponentManufacturer="true"
unless:set="antlib-sbom-ok"
- xmlns:unless="ant:unless"
- xmlns:cdx="antlib:org.apache.ant.cyclonedx">
+ xmlns:unless="ant:unless">
<component
name="${artifact.name}"
group="org.apache.ant"
@@ -257,27 +257,27 @@ under the License.
<dependency componentRef="json-schema-validator"/>
</additionalComponent>
<additionalComponent id="commons-codec">
- <sbomLink>
+ <cdx:sbomLink>
<url
url="https://repo1.maven.org/maven2/commons-codec/commons-codec/1.22.1/commons-codec-1.22.1-cyclonedx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
<file file="${lib.dir.compile}/commons-codec-1.22.1.jar"/>
</additionalComponent>
<additionalComponent id="commons-io">
- <sbomLink>
+ <cdx:sbomLink>
<url
url="https://repo1.maven.org/maven2/commons-io/commons-io/2.22.0/commons-io-2.22.0-cyclonedx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
<file file="${lib.dir.compile}/commons-io-2.22.0.jar"/>
</additionalComponent>
<additionalComponent id="commons-lang3">
- <sbomLink>
+ <cdx:sbomLink>
<url
url="https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.20.0/commons-lang3-3.20.0-cyclonedx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
<file file="${lib.dir.compile}/commons-lang3-3.20.0.jar"/>
</additionalComponent>
<additionalComponent id="commons-collections4">
- <sbomLink>
+ <cdx:sbomLink>
<url
url="https://repo1.maven.org/maven2/org/apache/commons/commons-collections4/4.5.0/commons-collections4-4.5.0-cyclonedx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
<file file="${lib.dir.compile}/commons-collections4-4.5.0.jar"/>
</additionalComponent>
<additionalComponent
@@ -292,27 +292,27 @@ under the License.
</license>
</additionalComponent>
<additionalComponent id="jackson-dataformat-xml">
- <sbomLink>
+ <cdx:sbomLink>
<url
url="https://repo1.maven.org/maven2/com/fasterxml/jackson/dataformat/jackson-dataformat-xml/2.22.1/jackson-dataformat-xml-2.22.1-sbom-cyclonedx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
<file file="${lib.dir.compile}/jackson-dataformat-xml-2.22.1.jar"/>
</additionalComponent>
<additionalComponent>
- <sbomLink>
+ <cdx:sbomLink>
<url
url="https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.22.1/jackson-core-2.22.1-sbom-cyclonedx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
<file file="${lib.dir.compile}/jackson-core-2.22.1.jar"/>
</additionalComponent>
<additionalComponent>
- <sbomLink>
+ <cdx:sbomLink>
<url
url="https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.22/jackson-annotations-2.22-sbom-cyclonedx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
<file file="${lib.dir.compile}/jackson-annotations-2.22.jar"/>
</additionalComponent>
<additionalComponent>
- <sbomLink>
+ <cdx:sbomLink>
<url
url="https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.22.1/jackson-databind-2.22.1-sbom-cyclonedx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
<file file="${lib.dir.compile}/jackson-databind-2.22.1.jar"/>
</additionalComponent>
<additionalComponent
@@ -345,9 +345,9 @@ under the License.
<license refid="apache-2"/>
</additionalComponent>
<additionalComponent id="apache-ivy">
- <sbomLink>
+ <cdx:sbomLink>
<url
url="https://repo1.maven.org/maven2/org/apache/ivy/ivy/2.6.0/ivy-2.6.0.cdx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
<file file="ivy/ivy.jar"/>
</additionalComponent>
<license refid="apache-2"/>
@@ -444,7 +444,9 @@ under the License.
binarysource="Source Distribution"/>
</target>
- <target name="after-bin-dist" depends="after-dist" if="can.use.cyclonedx">
+ <target name="after-bin-dist" depends="after-dist"
+ if="can.use.cyclonedx"
+ xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<create-tarball-boms
distdir="${bin.dist.dir}"
distbase="${dist.base}"
@@ -452,15 +454,17 @@ under the License.
binsrc="bin"
binarysource="Binary Distribution">
<component>
- <sbomLink createBomExternalReference="false">
+ <cdx:sbomLink createBomExternalReference="false">
<file file="${bin.dist.dir}/${artifact.stub}.cdx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
<file file="${bin.dist.dir}/${artifact.stub}.jar"/>
</component>
</create-tarball-boms>
</target>
- <target name="after-fat-bin-dist" depends="after-dist"
if="can.use.cyclonedx">
+ <target name="after-fat-bin-dist" depends="after-dist"
+ if="can.use.cyclonedx"
+ xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<create-tarball-boms
distdir="${bin.dist.dir}"
distbase="${dist.base}"
@@ -468,9 +472,9 @@ under the License.
binsrc="bin-withdeps"
binarysource="Binary Distribution Including Dependencies">
<component>
- <sbomLink createBomExternalReference="false">
+ <cdx:sbomLink createBomExternalReference="false">
<file file="${bin.dist.dir}/${artifact.stub}.cdx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
<file file="${bin.dist.dir}/${artifact.stub}.jar"/>
</component>
</create-tarball-boms>
diff --git a/changes.xml b/changes.xml
index d35269d..37c4e75 100644
--- a/changes.xml
+++ b/changes.xml
@@ -98,10 +98,15 @@
The default SBOM version now is 1.7 and the isExternal attribute
of component now also sets the attribute in the generated SBOM.
</action>
+ <action type="add" breaks-bwc="true">
+ Generalized sbomLink to a ComponentResolver componentdef. As a
+ side effect the nested sbomLink element of component now must
+ live in the "antlib:org.apache.ant.cyclonedx" XML namespace
+ (i.e. something like cdx:sbomLink).
+ </action>
<action type="add">
- The component type now supports a new nested element "ivymodule"
- which uses Apache Ivy to fill in the details of a component and
- its dependencies.
+ Added a ComponentResolver "ivyModule" which uses Apache Ivy to
+ fill in the details of a component and its dependencies.
This adds Ivy as a new dependency which is only required if you
want to use this feature.
</action>
diff --git a/docs/component.html b/docs/component.html
index a4b2c8a..1716483 100644
--- a/docs/component.html
+++ b/docs/component.html
@@ -151,302 +151,17 @@ <h4>any
describes. This is required if you want to include hashes for
the component in your SBOM.</p>
- <h4 id="sbomLink">sbomLink</h4>
-
- <p>At most one resource can be specified
- as <code>sbomLink</code>. When present the referenced resource is
- read as CycloneDX SBOM and:</p>
-
- <ul>
- <li><code>type</code>, <code>name</code>, <code>group</code>,
<code>version</code>,
- <code>purl</code>, <code>bomRef</code>, <code>scope</code>,
- <code>decription</code>, <code>publisher</code>, <code>copright</code>,
- <code>mimeType</code> and <code>supplier</code> are taken
- from the SBOM's metadata component unless they are explicitly
- specified on the component element itself.</li>
- <li><code>manufacturer</code> is taken from the SBOM's metadata
- component unless it is explicitly specified on the component
- element itself or <code>supplierismanufacturer</code>
- is <code>true</code>.</li>
- <li>Tags are merged with those of the SBOM's metadata
- component.</li>
- <li><code>author</code>s, <code>license</code>s,
<code>externalReference</code>s,
- <code>dependency</code>s and nested <code>components</code>
- are taken from the SBOM's metadata component if and only if
- there is no corresponding element in this component
- element.</li>
- <li>a "bom"-type <code>externalReference</code> is added to the
- enclosing component if the nested resource provides an URL,
- the enclosing component doesn't already
- contain <code>externalReference</code>s, the parsed SBOM
- doesn't already contain such an <code>externalReference</code>
- and this element's <code>createBomExternalReference</code> is
- not <code>false</code>.</li>
- <li>Hashes of the linked SBOM are ignored completely.</li>
- <li>Other components specified in the linked SBOM are also added
- to the SBOM created by the compomentbom task if they are
- direct dependencies of the current component element. And
- their dependencies are set to "unknown" as handling of
- transitive dependencies is beyond the scope of this
- library.<br/>
- Components specified explicitly in the SBOM take precedence
- over those found by parsing an SBOM link. If there already
- exists a component as part of the SBOM with the same name and
- group as one read from the linked SBOM, the linked component
- will be ignored. Here the version is ignored, it is assumed
- the component explicitly specified is the result of a process
- that resolved conflicts in dependency versions. Currently this
- only applies to Components with <code>pkg:maven/</code> Package-URLs
- as bom-ref.
- </li>
- </ul>
-
- <p>The <a hre="https://github.com/CycloneDX/cyclonedx-core-java">CycloneDX
- Core (Java) library</a> is used to read the linked SBOM.</p>
-
- <p>The <code>sbomLink</code> and <code>ivyModule</code> elements
- can not both be used as nested elements of the same
- component.</p>
+ <h4 id="componentResolver">any nested ComponentResolver</h4>
- <h5>Attributes</h5>
-
- <table class="attr">
- <tr>
- <th scope="col">Attribute</th>
- <th scope="col">Description</th>
- <th scope="col">Required</th>
- </tr>
- <tr>
- <td>createBomExternalReference</td>
- <td>Whether to create a bom-Type external reference in the
- resolved compoment based on the nested resource's URI.<br>
- <em>since CycloneDX Antlib 0.2</em></td>
- <td>No, defaults to <code>true</code></td>
- </tr>
- </table>
-
- <h4 id="ivyModule">ivyModule</h4>
-
- <p><em>since CycloneDX Antlib 0.2</em>. The optional Ivy
- dependency is required when using an <code>ivyModule</code>
- element.</p>
-
- <p>Using a nesed <code>ivyModule</code> you can use Apache Ivy to
- fill in fields from an <code>ivy.xml</code> file and have Ivy
- provide all (transitive) dependencies of this module to the
- SBOM.</p>
-
- <p>The <code>ivyModule</code> element is similar to
- a <a
href="https://ant.apache.org/ivy/history/2.6.0/use/postresolvetask.html">post
- resolve task</a> and expects the Ivy module used for the current
- component to be "resolved" already.</p>
-
- <p>When present the Ivy module wll be used and</p>
-
- <ul>
- <li><code>name</code>, <code>group</code>, <code>version</code>,
- <code>decription</code> are directly taken from the Ivy module
- unless the compoment already specifies it explicitly.</li>
- <li><code>license</code> and
- "website"-type <code>externalReference</code> are taken from
- the module's license and homePage if and only if there is no
- corresponding element in this component element.</li>
- <li>Dependencies of the given module that are included because
- of the configurations given by the <code>conf</code> attribute
- are added to the SBOM by the compomentbom task with data taken
- from their module descriptors. This includes transitive
- dependencies. The components will have hashes if an Ivy
- retrieve operation has retrieved them and local files are
- available prior to running the componentbom task.<br/>
- Components specified explicitly in the SBOM take precedence
- over those found by parsing the module. If there already
- exists a component as part of the SBOM with the same name and
- group as one read from the module, the dependencies will be
- ignored. Here the version is ignored, it is assumed the
- component explicitly specified is the result of a process that
- resolved conflicts in dependency versions and is unknown to
- Ivy. Currently this only applies to Components
- with <code>pkg:maven/</code> Package-URLs as bom-ref.
- </li>
- </ul>
-
- <p>Not all parts of an SBOM component you may want to provide are
- part of an Ivy module definition and you may want to provide
- them explicitly. Supplier and manufacturer information, more
- external references or the publisher are missing for
- example. The <code>type</code> defaults to "library" and
- the <code>scope</code> to "required". For the component that
- contains the <code>ivyModule</code> child element itself, you
- can use the "normal" attributes and nested element of the
- component to augment data - for the dependencies identified by
- the Ivy module you can provide extra data
- as <code>templateComponent</code> child elements.</p>
-
- <p>The <code>sbomLink</code> and <code>ivyModule</code> elements
- can not both be used as nested elements of the same
- component.</p>
-
- <h5>Attributes</h5>
-
- <table class="attr">
- <tr>
- <th scope="col">Attribute</th>
- <th scope="col">Description</th>
- <th scope="col">Required</th>
- </tr>
- <tr>
- <td>conf</td>
- <td>comma-separated list of configurations that will be
- consulted for dependencies of this component.</td>
- <td>No, defaults to <code>*</code></td>
- </tr>
- <tr>
- <td>optionalconf</td>
- <td>comma-separated list of configurations. Any dependency
- that is only included because of configurations specified in
- this list will be marked with <code>scope</code>
- optional.</td>
- <td>No, by default no dependency is marked as optional.</td>
- </tr>
- <tr>
- <td>externalconf</td>
- <td>comma-separated list of configurations. Any dependency
- that is only included because of configurations specified in
- this list will have their <code>isExternal</code> flag set
- to true.</td>
- <td>No, by default no dependency is marked as external.</td>
- </tr>
- <tr>
- <td>resolveId</td>
- <td>The id which was used for a previous resolve.</td>
- <td>No, defaults to <code>[org]-[module]</code> of the last
- <code>ivy:resolve</code> task.</td>
- </tr>
- <tr>
- <td>settingsRef</td>
- <td>A reference to Ivy settings that must be used.</td>
- <td>No, defaults to <code>ivy.instance</code>.</td>
- </tr>
- <tr>
- <td>pattern</td>
- <td>The pattern used by the <code>ivy:retrieve</code> task
- that copied the dependencies.</td>
- <td>No, defaults to <code>ivy.retrieve.pattern</code>.</td>
- </tr>
- </table>
-
- <h5>Nested elements</h5>
-
- <h6>templateComponent</h6>
-
- <p>A nested <code>templateComponent</code> element supports all
- attributes and nested elements of a component, but
- neither <code>sbomLink</code> nor <code>ivyModule</code> have
- any effect.</p>
-
- <p>A <code>templateComponent</code> can be used to enrich a
- component detected by Ivy as a dependency of the current
- component. For example by adding more external references or a
- manufacturer. Template components take precedence over a data
- detected by Ivy, they are matched to a detected dependency by
- name and group only, the version is ignored. If
- the <code>templateComponent</code> has a <code>version</code>
- attribute, no hashes will be calculated from the resolved
- file.</p>
-
- <p>The combination
- of <code>ivyModule</code>, <code>templateComponent</code> and
- an <code>additionalComponent</code> specified in
- a <code>compomentbom</code> may be a bit
- confusing. An <code>additionalComponent</code> is always added
- to the generated SBOM and any <code>ivyModule</code> dependency
- or <code>templateComponent</code> that matches the name and
- group of an <code>additionalComponent</code> is ignored. Apart
- from that a <code>templateComponent</code> will only show up in
- the SBOM if a matching dependency is detected
- by <code>ivyModule</code>. <code>templateComponent</code> and
- Ivy module dependencies are merged
- while <code>additionalComponent</code>s completely replace Ivy
- module dependencies.</p>
-
- <p>As an example, assume the <code>ivyModule</code> resolves a
- module with group "org.example", name "module" and version "1"
- which has a dependency on a component with group "com.example",
- name "dependency", version "2" and description "my
- description".</p>
-
- <p>The following snippet adds two components to the SBOM with
- bom-refs "pkg:maven/org.example/module@1?type=jar" and
- "pkg:maven/com.example/dependency@2?type=jar" where the later has a
- description of "my description" and hashes if the dependency has
- been retrieved:</p>
-
- <pre>
- <cdx:componentbom
- <cdx:component>
- <ivyModule/>
- </cdx:component>
- </cdx:componentbom>
- </pre>
-
- <p>The following snippet adds two components to the SBOM with
- bom-refs "pkg:maven/org.example/module@1?type=jar" and
- "pkg:maven/com.example/dependency@3?type=jar" where the later has
- a no description at all and no hashes either.</p>
-
- <pre>
- <cdx:componentbom
- <cdx:component>
- <ivyModule/>
- </cdx:component>
- <cdx:additionalComponent
- name="dependency"
- group="com.example"
- version="3"
- />
- </cdx:componentbom>
- </pre>
+ <p>This library defines a <code>ComponentResolver</code> interface
+ that can be implemented by Ant types to enrich its parent
+ component by reading external data.</p>
- <p>The following snippet adds two components to the SBOM with
- bom-refs "pkg:maven/org.example/module@1?type=jar" and
- "pkg:maven/com.example/dependency@2?type=jar" where the later
- has a description "my description" a publisher "example" and
- hashes if the dependency has been retrieved.</p>
+ <p>Currently the library ships with two
+ implementations: <a href="sbomLink.html">sbomLink</a>
+ and <a href="ivyModule.html">ivyModule</a>.</p>
- <pre>
- <cdx:componentbom
- <cdx:component>
- <ivyModule>
- <cdx:templateComponent
- name="dependency"
- group="com.example"
- publisher="Example"
- />
- </ivyModule>
- </cdx:component>
- </cdx:componentbom>
- </pre>
-
- <p>The following snippet adds two components to the SBOM with
- bom-refs "pkg:maven/org.example/module@1?type=jar" and
- "pkg:maven/com.example/dependency@3?type=jar" where the later has
- a description "another description" but no hashes (as the
- version doesn't match).</p>
-
- <pre>
- <cdx:componentbom
- <cdx:component>
- <ivyModule>
- <cdx:templateComponent
- name="dependency"
- group="com.example"
- version="3"
- description="another description"
- />
- </ivyModule>
- </cdx:component>
- </cdx:componentbom>
- </pre>
+ <p>You must not specify more than one nested ComponentResolver.</p>
<h4 id="manufacturer">manufacturer</h4>
diff --git a/docs/componentbom.html b/docs/componentbom.html
index 4905e50..d80c8d5 100644
--- a/docs/componentbom.html
+++ b/docs/componentbom.html
@@ -33,10 +33,10 @@ <h2 id="componentbom">componentbom Task</h2>
required that specifies the component to create an SBOM
for.</p>
- <p>Components that get "resolved" because they specify
- an <code>sbomLink</code> can add more components to the SBOM than
- are specified explicitly via the child elements of this
- task.</p>
+ <p>Components that get "resolved" because they specify a nested
+ resolver like <code>sbomLink</code> or <code>ivyModule</code>
+ can add more components to the SBOM than are specified
+ explicitly via the child elements of this task.</p>
<p>It is an error if any component specifies a dependency on a
component that is not part of the generated SBOM. The bom-refs
diff --git a/docs/ivyModule.html b/docs/ivyModule.html
new file mode 100644
index 0000000..dfcd652
--- /dev/null
+++ b/docs/ivyModule.html
@@ -0,0 +1,246 @@
+<!--
+ 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
+
+ https://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.
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Language" content="en-us"></meta>
+ <link rel="stylesheet" type="text/css" href="style.css">
+ <title>Apache CycloneDX Ant Library - ivyModule ComponentResolver</title>
+ </head>
+
+ <body>
+ <h2 id="ivyModule">ivyModule ComponentResolver</h2>
+
+ <p><em>since CycloneDX Antlib 0.2</em>. The optional Ivy
+ dependency is required when using an <code>ivyModule</code>
+ element.</p>
+
+ <p>Using a <code>ivyModule</code> ComponentResolver within a
+ component you can use Apache Ivy to fill in fields from
+ an <code>ivy.xml</code> file and have Ivy provide all
+ (transitive) dependencies of this module to the SBOM.</p>
+
+ <p>The <code>ivyModule</code> element is similar to
+ a <a
href="https://ant.apache.org/ivy/history/2.6.0/use/postresolvetask.html">post
+ resolve task</a> and expects the Ivy module used for the current
+ component to be "resolved" already.</p>
+
+ <p>When present the Ivy module will be used to enrich the
+ component it is nested into:</p>
+
+ <ul>
+ <li><code>name</code>, <code>group</code>, <code>version</code>,
+ <code>decription</code> are directly taken from the Ivy module
+ unless the compoment already specifies it explicitly.</li>
+ <li><code>license</code> and
+ "website"-type <code>externalReference</code> are taken from
+ the module's license and homePage if and only if there is no
+ corresponding element in this component element.</li>
+ <li>Dependencies of the given module that are included because
+ of the configurations given by the <code>conf</code> attribute
+ are added to the SBOM by the compomentbom task with data taken
+ from their module descriptors. This includes transitive
+ dependencies. The components will have hashes if an Ivy
+ retrieve operation has retrieved them and local files are
+ available prior to running the componentbom task.<br/>
+ Components specified explicitly in the SBOM take precedence
+ over those found by parsing the module. If there already
+ exists a component as part of the SBOM with the same name and
+ group as one read from the module, the dependencies will be
+ ignored. Here the version is ignored, it is assumed the
+ component explicitly specified is the result of a process that
+ resolved conflicts in dependency versions and is unknown to
+ Ivy. Currently this only applies to Components
+ with <code>pkg:maven/</code> Package-URLs as bom-ref.
+ </li>
+ </ul>
+
+ <p>Not all parts of an SBOM component you may want to provide are
+ part of an Ivy module definition and you may want to provide
+ them explicitly. Supplier and manufacturer information, more
+ external references or the publisher are missing for
+ example. The <code>type</code> defaults to "library" and
+ the <code>scope</code> to "required". For the component that
+ contains the <code>ivyModule</code> child element itself, you
+ can use the "normal" attributes and nested element of the
+ component to augment data - for the dependencies identified by
+ the Ivy module you can provide extra data
+ as <code>templateComponent</code> child elements.</p>
+
+ <h3>Attributes</h3>
+
+ <table class="attr">
+ <tr>
+ <th scope="col">Attribute</th>
+ <th scope="col">Description</th>
+ <th scope="col">Required</th>
+ </tr>
+ <tr>
+ <td>conf</td>
+ <td>comma-separated list of configurations that will be
+ consulted for dependencies of this component.</td>
+ <td>No, defaults to <code>*</code></td>
+ </tr>
+ <tr>
+ <td>optionalconf</td>
+ <td>comma-separated list of configurations. Any dependency
+ that is only included because of configurations specified in
+ this list will be marked with <code>scope</code>
+ optional.</td>
+ <td>No, by default no dependency is marked as optional.</td>
+ </tr>
+ <tr>
+ <td>externalconf</td>
+ <td>comma-separated list of configurations. Any dependency
+ that is only included because of configurations specified in
+ this list will have their <code>isExternal</code> flag set
+ to true.</td>
+ <td>No, by default no dependency is marked as external.</td>
+ </tr>
+ <tr>
+ <td>resolveId</td>
+ <td>The id which was used for a previous resolve.</td>
+ <td>No, defaults to <code>[org]-[module]</code> of the last
+ <code>ivy:resolve</code> task.</td>
+ </tr>
+ <tr>
+ <td>settingsRef</td>
+ <td>A reference to Ivy settings that must be used.</td>
+ <td>No, defaults to <code>ivy.instance</code>.</td>
+ </tr>
+ <tr>
+ <td>pattern</td>
+ <td>The pattern used by the <code>ivy:retrieve</code> task
+ that copied the dependencies.</td>
+ <td>No, defaults to <code>ivy.retrieve.pattern</code>.</td>
+ </tr>
+ </table>
+
+ <h3>Nested elements</h3>
+
+ <h4>templateComponent</h4>
+
+ <p>A nested <code>templateComponent</code> element supports all
+ attributes and nested elements of a component, but
+ neither <code>sbomLink</code> nor <code>ivyModule</code> have
+ any effect.</p>
+
+ <p>A <code>templateComponent</code> can be used to enrich a
+ component detected by Ivy as a dependency of the current
+ component. For example by adding more external references or a
+ manufacturer. Template components take precedence over a data
+ detected by Ivy, they are matched to a detected dependency by
+ name and group only, the version is ignored. If
+ the <code>templateComponent</code> has a <code>version</code>
+ attribute, no hashes will be calculated from the resolved
+ file.</p>
+
+ <p>The combination
+ of <code>ivyModule</code>, <code>templateComponent</code> and
+ an <code>additionalComponent</code> specified in
+ a <code>compomentbom</code> may be a bit
+ confusing. An <code>additionalComponent</code> is always added
+ to the generated SBOM and any <code>ivyModule</code> dependency
+ or <code>templateComponent</code> that matches the name and
+ group of an <code>additionalComponent</code> is ignored. Apart
+ from that a <code>templateComponent</code> will only show up in
+ the SBOM if a matching dependency is detected
+ by <code>ivyModule</code>. <code>templateComponent</code> and
+ Ivy module dependencies are merged
+ while <code>additionalComponent</code>s completely replace Ivy
+ module dependencies.</p>
+
+ <p>As an example, assume the <code>ivyModule</code> resolves a
+ module with group "org.example", name "module" and version "1"
+ which has a dependency on a component with group "com.example",
+ name "dependency", version "2" and description "my
+ description".</p>
+
+ <p>The following snippet adds two components to the SBOM with
+ bom-refs "pkg:maven/org.example/module@1?type=jar" and
+ "pkg:maven/com.example/dependency@2?type=jar" where the later has a
+ description of "my description" and hashes if the dependency has
+ been retrieved:</p>
+
+ <pre>
+ <cdx:componentbom
+ <cdx:component>
+ <cdx:ivyModule/>
+ </cdx:component>
+ </cdx:componentbom>
+ </pre>
+
+ <p>The following snippet adds two components to the SBOM with
+ bom-refs "pkg:maven/org.example/module@1?type=jar" and
+ "pkg:maven/com.example/dependency@3?type=jar" where the later has
+ a no description at all and no hashes either.</p>
+
+ <pre>
+ <cdx:componentbom
+ <cdx:component>
+ <cdx:ivyModule/>
+ </cdx:component>
+ <cdx:additionalComponent
+ name="dependency"
+ group="com.example"
+ version="3"
+ />
+ </cdx:componentbom>
+ </pre>
+
+ <p>The following snippet adds two components to the SBOM with
+ bom-refs "pkg:maven/org.example/module@1?type=jar" and
+ "pkg:maven/com.example/dependency@2?type=jar" where the later
+ has a description "my description" a publisher "example" and
+ hashes if the dependency has been retrieved.</p>
+
+ <pre>
+ <cdx:componentbom
+ <cdx:component>
+ <cdx:ivyModule>
+ <templateComponent
+ name="dependency"
+ group="com.example"
+ publisher="Example"
+ />
+ </cdx:ivyModule>
+ </cdx:component>
+ </cdx:componentbom>
+ </pre>
+
+ <p>The following snippet adds two components to the SBOM with
+ bom-refs "pkg:maven/org.example/module@1?type=jar" and
+ "pkg:maven/com.example/dependency@3?type=jar" where the later has
+ a description "another description" but no hashes (as the
+ version doesn't match).</p>
+
+ <pre>
+ <cdx:componentbom
+ <cdx:component>
+ <cdx:ivyModule>
+ <templateComponent
+ name="dependency"
+ group="com.example"
+ version="3"
+ description="another description"
+ />
+ </cdx:ivyModule>
+ </cdx:component>
+ </cdx:componentbom>
+ </pre>
+ </body>
+</html>
+
diff --git a/docs/sbomLink.html b/docs/sbomLink.html
new file mode 100644
index 0000000..988d5b3
--- /dev/null
+++ b/docs/sbomLink.html
@@ -0,0 +1,98 @@
+<!--
+ 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
+
+ https://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.
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Language" content="en-us"></meta>
+ <link rel="stylesheet" type="text/css" href="style.css">
+ <title>Apache CycloneDX Ant Library - sbomLink ComponentResolver</title>
+ </head>
+
+ <body>
+ <h2 id="sbomLink">sbomLink ComponentResolver</h2>
+
+ <p>Enriches a component by reading an existing CycloneDX SBOM.</p>
+
+ <p>At most one resource can be specified as nested element which
+ is then read as CycloneDX SBOM and enriches the component that
+ contains this ComponentResolver:</p>
+
+ <ul>
+ <li><code>type</code>, <code>name</code>, <code>group</code>,
<code>version</code>,
+ <code>purl</code>, <code>bomRef</code>, <code>scope</code>,
+ <code>decription</code>, <code>publisher</code>, <code>copright</code>,
+ <code>mimeType</code> and <code>supplier</code> are taken
+ from the SBOM's metadata component unless they are explicitly
+ specified on the component element itself.</li>
+ <li><code>manufacturer</code> is taken from the SBOM's metadata
+ component unless it is explicitly specified on the component
+ element itself or <code>supplierismanufacturer</code>
+ is <code>true</code>.</li>
+ <li>Tags are merged with those of the SBOM's metadata
+ component.</li>
+ <li><code>author</code>s, <code>license</code>s,
<code>externalReference</code>s,
+ <code>dependency</code>s and nested <code>components</code>
+ are taken from the SBOM's metadata component if and only if
+ there is no corresponding element in this component
+ element.</li>
+ <li>a "bom"-type <code>externalReference</code> is added to the
+ enclosing component if the nested resource provides an URL,
+ the enclosing component doesn't already
+ contain <code>externalReference</code>s, the parsed SBOM
+ doesn't already contain such an <code>externalReference</code>
+ and this element's <code>createBomExternalReference</code> is
+ not <code>false</code>.</li>
+ <li>Hashes of the linked SBOM are ignored completely.</li>
+ <li>Other components specified in the linked SBOM are also added
+ to the SBOM created by the compomentbom task if they are
+ direct dependencies of the current component element. And
+ their dependencies are set to "unknown" as handling of
+ transitive dependencies is beyond the scope of this
+ library.<br/>
+ Components specified explicitly in the SBOM take precedence
+ over those found by parsing an SBOM link. If there already
+ exists a component as part of the SBOM with the same name and
+ group as one read from the linked SBOM, the linked component
+ will be ignored. Here the version is ignored, it is assumed
+ the component explicitly specified is the result of a process
+ that resolved conflicts in dependency versions. Currently this
+ only applies to Components with <code>pkg:maven/</code> Package-URLs
+ as bom-ref.
+ </li>
+ </ul>
+
+ <p>The <a hre="https://github.com/CycloneDX/cyclonedx-core-java">CycloneDX
+ Core (Java) library</a> is used to read the linked SBOM.</p>
+
+ <h3>Attributes</h3>
+
+ <table class="attr">
+ <tr>
+ <th scope="col">Attribute</th>
+ <th scope="col">Description</th>
+ <th scope="col">Required</th>
+ </tr>
+ <tr>
+ <td>createBomExternalReference</td>
+ <td>Whether to create a bom-Type external reference in the
+ resolved compoment based on the nested resource's URI.<br>
+ <em>since CycloneDX Antlib 0.2</em></td>
+ <td>No, defaults to <code>true</code></td>
+ </tr>
+ </table>
+
+ </body>
+</html>
diff --git a/example/ant-cyclonedx-0.2alpha.cdx.diff
b/example/ant-cyclonedx-0.2alpha.cdx.diff
index 735bb7e..e84f2c0 100644
--- a/example/ant-cyclonedx-0.2alpha.cdx.diff
+++ b/example/ant-cyclonedx-0.2alpha.cdx.diff
@@ -1,5 +1,5 @@
---- ant-cyclonedx-0.2alpha.cdx.json 2026-08-16 12:54:15.035134147 +0200
-+++ ant-cyclonedx-0.2alpha.ivy.cdx.json 2026-08-16 12:54:22.467055136
+0200
+--- ant-cyclonedx-0.2alpha.cdx.json 2026-08-16 16:28:01.254033959 +0200
++++ ant-cyclonedx-0.2alpha.ivy.cdx.json 2026-08-16 16:28:03.535753306
+0200
@@ -253,36 +253,68 @@
"components" : [
{
diff --git a/example/ant-cyclonedx-0.2alpha.cdx.json
b/example/ant-cyclonedx-0.2alpha.cdx.json
index 1c7407b..09603df 100644
--- a/example/ant-cyclonedx-0.2alpha.cdx.json
+++ b/example/ant-cyclonedx-0.2alpha.cdx.json
@@ -34,35 +34,35 @@
"hashes" : [
{
"alg" : "MD5",
- "content" : "de73b2090ed784264d7cdf6b94c40b9f"
+ "content" : "f7e5e0f28ff8599952690ffbcee84cb8"
},
{
"alg" : "SHA-1",
- "content" : "117736e22f1f27217eaf9068b1007fddedef5f8f"
+ "content" : "519987c92a03c45a826479d21a32280e4d319d55"
},
{
"alg" : "SHA-256",
- "content" :
"aed1a008c3ebdbb2908d7dbacebbc1d8d489d08ebba0910217f239412ab36b04"
+ "content" :
"3dc5e114e93941bc125fd46fa63fbb2bdccece34d9c9be8f314940766736bdd4"
},
{
"alg" : "SHA-512",
- "content" :
"add20643bd0e106b27c7200863bf376ea28ee95cd42697820024b2eff5c5bdacc4be0bbbe1138ca8ac35e209df80ce30bd27e1a5eb32d1ae528234936f4ea0ca"
+ "content" :
"8c27052202f363a72e49306a4387e3b7869e51093c8c72f4ec3aa1d04067cc62cb44e2fb765b7035bd553b2320a15568eb2c896f08ce1d489f2c4fe4545211fa"
},
{
"alg" : "SHA3-256",
- "content" :
"192621053a51c43cc73078977487e42ec5b6597c5e95119ba86a283b1aca4470"
+ "content" :
"c90ceaa8a35b26c169c97efa7bbeff6eedc790edf92b21699d5330104159cb88"
},
{
"alg" : "SHA3-512",
- "content" :
"11159291538dd1d7fec1de2214579732e76a1233acbff6887ead1b7520bdf784f47f0f6af1ca66f0096ddbbbf7470febd77369260653781ee4ed1b3a6d465c20"
+ "content" :
"b3acbc1c48365547ff8c3902cf58b82e78ffa8eac2764a66f360b7d6ffaf698d7a7b98fc300efc86e725ea6b850ed8dad04d5faa19acd101776b4a7762d95048"
},
{
"alg" : "SHA-384",
- "content" :
"c65ed1eb81aa20245bab2173bcab863663dec015f220bc5c5353a0d099e71013f85537a41e8fb673dba35f8bf9ada61d"
+ "content" :
"94a64422adff961a4afb215c3f097537edfec4590291920958ea455fc2240783f5b3462dd2fb7a4ed0224748724b6d22"
},
{
"alg" : "SHA3-384",
- "content" :
"031ca0350bcb44f06f57160d0d9bba747f37a403a58b54938758daf84f2b34f07201a6a69052ee8bbbfb15f6df0dec3b"
+ "content" :
"45066279dd52e01fff8c38f1d97c9116ff9be966559a006756000304502f6e5a8d370ed500fc370cb24ac7dda9289902"
}
],
"licenses" : [
@@ -146,35 +146,35 @@
"hashes" : [
{
"alg" : "MD5",
- "content" : "de73b2090ed784264d7cdf6b94c40b9f"
+ "content" : "f7e5e0f28ff8599952690ffbcee84cb8"
},
{
"alg" : "SHA-1",
- "content" : "117736e22f1f27217eaf9068b1007fddedef5f8f"
+ "content" : "519987c92a03c45a826479d21a32280e4d319d55"
},
{
"alg" : "SHA-256",
- "content" :
"aed1a008c3ebdbb2908d7dbacebbc1d8d489d08ebba0910217f239412ab36b04"
+ "content" :
"3dc5e114e93941bc125fd46fa63fbb2bdccece34d9c9be8f314940766736bdd4"
},
{
"alg" : "SHA-512",
- "content" :
"add20643bd0e106b27c7200863bf376ea28ee95cd42697820024b2eff5c5bdacc4be0bbbe1138ca8ac35e209df80ce30bd27e1a5eb32d1ae528234936f4ea0ca"
+ "content" :
"8c27052202f363a72e49306a4387e3b7869e51093c8c72f4ec3aa1d04067cc62cb44e2fb765b7035bd553b2320a15568eb2c896f08ce1d489f2c4fe4545211fa"
},
{
"alg" : "SHA3-256",
- "content" :
"192621053a51c43cc73078977487e42ec5b6597c5e95119ba86a283b1aca4470"
+ "content" :
"c90ceaa8a35b26c169c97efa7bbeff6eedc790edf92b21699d5330104159cb88"
},
{
"alg" : "SHA3-512",
- "content" :
"11159291538dd1d7fec1de2214579732e76a1233acbff6887ead1b7520bdf784f47f0f6af1ca66f0096ddbbbf7470febd77369260653781ee4ed1b3a6d465c20"
+ "content" :
"b3acbc1c48365547ff8c3902cf58b82e78ffa8eac2764a66f360b7d6ffaf698d7a7b98fc300efc86e725ea6b850ed8dad04d5faa19acd101776b4a7762d95048"
},
{
"alg" : "SHA-384",
- "content" :
"c65ed1eb81aa20245bab2173bcab863663dec015f220bc5c5353a0d099e71013f85537a41e8fb673dba35f8bf9ada61d"
+ "content" :
"94a64422adff961a4afb215c3f097537edfec4590291920958ea455fc2240783f5b3462dd2fb7a4ed0224748724b6d22"
},
{
"alg" : "SHA3-384",
- "content" :
"031ca0350bcb44f06f57160d0d9bba747f37a403a58b54938758daf84f2b34f07201a6a69052ee8bbbfb15f6df0dec3b"
+ "content" :
"45066279dd52e01fff8c38f1d97c9116ff9be966559a006756000304502f6e5a8d370ed500fc370cb24ac7dda9289902"
}
],
"licenses" : [
diff --git a/example/ant-cyclonedx-0.2alpha.ivy.cdx.json
b/example/ant-cyclonedx-0.2alpha.ivy.cdx.json
index 667d8e0..cc60152 100644
--- a/example/ant-cyclonedx-0.2alpha.ivy.cdx.json
+++ b/example/ant-cyclonedx-0.2alpha.ivy.cdx.json
@@ -34,35 +34,35 @@
"hashes" : [
{
"alg" : "MD5",
- "content" : "de73b2090ed784264d7cdf6b94c40b9f"
+ "content" : "f7e5e0f28ff8599952690ffbcee84cb8"
},
{
"alg" : "SHA-1",
- "content" : "117736e22f1f27217eaf9068b1007fddedef5f8f"
+ "content" : "519987c92a03c45a826479d21a32280e4d319d55"
},
{
"alg" : "SHA-256",
- "content" :
"aed1a008c3ebdbb2908d7dbacebbc1d8d489d08ebba0910217f239412ab36b04"
+ "content" :
"3dc5e114e93941bc125fd46fa63fbb2bdccece34d9c9be8f314940766736bdd4"
},
{
"alg" : "SHA-512",
- "content" :
"add20643bd0e106b27c7200863bf376ea28ee95cd42697820024b2eff5c5bdacc4be0bbbe1138ca8ac35e209df80ce30bd27e1a5eb32d1ae528234936f4ea0ca"
+ "content" :
"8c27052202f363a72e49306a4387e3b7869e51093c8c72f4ec3aa1d04067cc62cb44e2fb765b7035bd553b2320a15568eb2c896f08ce1d489f2c4fe4545211fa"
},
{
"alg" : "SHA3-256",
- "content" :
"192621053a51c43cc73078977487e42ec5b6597c5e95119ba86a283b1aca4470"
+ "content" :
"c90ceaa8a35b26c169c97efa7bbeff6eedc790edf92b21699d5330104159cb88"
},
{
"alg" : "SHA3-512",
- "content" :
"11159291538dd1d7fec1de2214579732e76a1233acbff6887ead1b7520bdf784f47f0f6af1ca66f0096ddbbbf7470febd77369260653781ee4ed1b3a6d465c20"
+ "content" :
"b3acbc1c48365547ff8c3902cf58b82e78ffa8eac2764a66f360b7d6ffaf698d7a7b98fc300efc86e725ea6b850ed8dad04d5faa19acd101776b4a7762d95048"
},
{
"alg" : "SHA-384",
- "content" :
"c65ed1eb81aa20245bab2173bcab863663dec015f220bc5c5353a0d099e71013f85537a41e8fb673dba35f8bf9ada61d"
+ "content" :
"94a64422adff961a4afb215c3f097537edfec4590291920958ea455fc2240783f5b3462dd2fb7a4ed0224748724b6d22"
},
{
"alg" : "SHA3-384",
- "content" :
"031ca0350bcb44f06f57160d0d9bba747f37a403a58b54938758daf84f2b34f07201a6a69052ee8bbbfb15f6df0dec3b"
+ "content" :
"45066279dd52e01fff8c38f1d97c9116ff9be966559a006756000304502f6e5a8d370ed500fc370cb24ac7dda9289902"
}
],
"licenses" : [
@@ -146,35 +146,35 @@
"hashes" : [
{
"alg" : "MD5",
- "content" : "de73b2090ed784264d7cdf6b94c40b9f"
+ "content" : "f7e5e0f28ff8599952690ffbcee84cb8"
},
{
"alg" : "SHA-1",
- "content" : "117736e22f1f27217eaf9068b1007fddedef5f8f"
+ "content" : "519987c92a03c45a826479d21a32280e4d319d55"
},
{
"alg" : "SHA-256",
- "content" :
"aed1a008c3ebdbb2908d7dbacebbc1d8d489d08ebba0910217f239412ab36b04"
+ "content" :
"3dc5e114e93941bc125fd46fa63fbb2bdccece34d9c9be8f314940766736bdd4"
},
{
"alg" : "SHA-512",
- "content" :
"add20643bd0e106b27c7200863bf376ea28ee95cd42697820024b2eff5c5bdacc4be0bbbe1138ca8ac35e209df80ce30bd27e1a5eb32d1ae528234936f4ea0ca"
+ "content" :
"8c27052202f363a72e49306a4387e3b7869e51093c8c72f4ec3aa1d04067cc62cb44e2fb765b7035bd553b2320a15568eb2c896f08ce1d489f2c4fe4545211fa"
},
{
"alg" : "SHA3-256",
- "content" :
"192621053a51c43cc73078977487e42ec5b6597c5e95119ba86a283b1aca4470"
+ "content" :
"c90ceaa8a35b26c169c97efa7bbeff6eedc790edf92b21699d5330104159cb88"
},
{
"alg" : "SHA3-512",
- "content" :
"11159291538dd1d7fec1de2214579732e76a1233acbff6887ead1b7520bdf784f47f0f6af1ca66f0096ddbbbf7470febd77369260653781ee4ed1b3a6d465c20"
+ "content" :
"b3acbc1c48365547ff8c3902cf58b82e78ffa8eac2764a66f360b7d6ffaf698d7a7b98fc300efc86e725ea6b850ed8dad04d5faa19acd101776b4a7762d95048"
},
{
"alg" : "SHA-384",
- "content" :
"c65ed1eb81aa20245bab2173bcab863663dec015f220bc5c5353a0d099e71013f85537a41e8fb673dba35f8bf9ada61d"
+ "content" :
"94a64422adff961a4afb215c3f097537edfec4590291920958ea455fc2240783f5b3462dd2fb7a4ed0224748724b6d22"
},
{
"alg" : "SHA3-384",
- "content" :
"031ca0350bcb44f06f57160d0d9bba747f37a403a58b54938758daf84f2b34f07201a6a69052ee8bbbfb15f6df0dec3b"
+ "content" :
"45066279dd52e01fff8c38f1d97c9116ff9be966559a006756000304502f6e5a8d370ed500fc370cb24ac7dda9289902"
}
],
"licenses" : [
diff --git a/src/main/org/apache/ant/cyclonedx/Component.java
b/src/main/org/apache/ant/cyclonedx/Component.java
index 9976de4..f2a8c42 100644
--- a/src/main/org/apache/ant/cyclonedx/Component.java
+++ b/src/main/org/apache/ant/cyclonedx/Component.java
@@ -38,7 +38,6 @@ import org.apache.tools.ant.types.DataType;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.resources.FileProvider;
-import org.apache.tools.ant.types.resources.Union;
import org.cyclonedx.Version;
import org.cyclonedx.model.LicenseChoice;
@@ -86,8 +85,7 @@ public class Component extends DataType {
private Set<String> tags = new HashSet<>();
private List<Property> properties = new ArrayList<>();
private String mimeType;
- private SbomLink sbomLink;
- private IvyModule ivyModule;
+ private ComponentResolver resolver;
/**
* Comparator for components.
@@ -166,8 +164,7 @@ public class Component extends DataType {
this.tags = new HashSet<>(other.tags);
this.properties = new ArrayList<>(other.properties);
this.mimeType = other.mimeType;
- this.sbomLink = other.sbomLink;
- this.ivyModule = other.ivyModule;
+ this.resolver = other.resolver;
}
/**
@@ -473,30 +470,16 @@ public class Component extends DataType {
}
/**
- * Container for SBOM link resource.
- *
- * @return container for SBOM link resource
- */
- public SbomLink createSbomLink() {
- checkChildrenAllowed();
- if (ivyModule != null) {
- throw new BuildException("sbomLink and ivyModule are mutually
exclusive");
- }
- return sbomLink == null ? (sbomLink = new SbomLink(getProject())) :
sbomLink;
- }
-
- /**
- * Container for Ivy module configuration.
- *
- * @return container for Ivy module configuration
+ * Resolver that uses external data to enrich this component.
+ * @param resolver the resolver
* @since CycloneDX Antlib 0.2
*/
- public IvyModule createIvyModule() {
+ public void add(ComponentResolver resolver) {
checkChildrenAllowed();
- if (sbomLink != null) {
- throw new BuildException("sbomLink and ivyModule are mutually
exclusive");
+ if (this.resolver != null) {
+ throw new BuildException("only one resolver can be used at a
time");
}
- return ivyModule == null ? (ivyModule = new IvyModule()) : ivyModule;
+ this.resolver = resolver;
}
/**
@@ -866,14 +849,7 @@ public class Component extends DataType {
if (!resolved) {
resolved = true;
- if (sbomLink != null) {
- SbomLinkComponentResolver resolver = new
SbomLinkComponentResolver(getProject(), sbomLink);
- return resolver.resolve(this);
- }
-
- if (ivyModule != null) {
- IvyModuleComponentResolver resolver = new
IvyModuleComponentResolver(ivyModule, getProject());
-
+ if (resolver != null) {
return resolver.resolve(this);
}
}
@@ -1319,179 +1295,4 @@ public class Component extends DataType {
setChecked(true);
}
}
-
- /**
- * @since CycloneDX Antlib 0.2
- */
- public static class SbomLink extends Union {
- private boolean createBomExternalReference = true;
-
- public SbomLink(Project project) {
- super(project);
- }
-
- /**
- * Whether to create a bom-Type external reference in the
- * resolved component based on the nested resource's URI.
- *
- * <p>Will not create an external reference of there are
- * already external references om the component or the
- * resolved SBOM already contains a bom-type reference.</p>
- *
- * <p>Defaults to <code>true</code>.
- *
- * @param create whether to create a bom-Type external reference
- */
- public void setCreateBomExternalReference(boolean create) {
- createBomExternalReference = create;
- }
-
- /**
- * Whether to create a bom-Type external reference in the
- * resolved component based on the nested resource's URI.
- * @return create whether to create a bom-Type external reference
- */
- public boolean getCreateBomExternalReference() {
- return createBomExternalReference;
- }
- }
-
- /**
- * Configuration for Ivy module resolution.
- *
- * <p>This nested element allows a Component to be populated from
- * an Ivy module descriptor. The Ivy file should already be resolved
- * (i.e., ivy:resolve should have been run).</p>
- *
- * @since CycloneDX Antlib 0.2
- */
- public static class IvyModule {
- private String conf;
- private String optionalConf;
- private String externalConf;
- private String resolveId;
- private Reference antIvyEngineRef;
- private String pattern;
- private Map<String, Component> templateComponents = new HashMap<>();
-
- /**
- * Sets the configurations to include in the SBOM.
- *
- * <p>Defaults to the configurations resolved by the last resolve
call, or {@code *} if no resolve was
- * explicitly called</p>
- *
- * @param comma separated list of the configurations to retrieve or
{@code *}.
- */
- public void setConf(String conf) {
- this.conf = conf;
- }
-
- String getConf() {
- return conf;
- }
-
- /**
- * Sets the id which was used for a previous resolve.
- *
- * <p>Defaults to {@code [org].[module]}.</p>
- *
- * @param id which was used for a previous resolve
- */
- public void setResolveId(String resolveId) {
- this.resolveId = resolveId;
- }
-
- String getResolveId() {
- return resolveId;
- }
-
- /**
- * Sets a reference is a different Ivy settings file than the default
shall be used.
- *
- * <p>Defaults to {@code ivy.instance}.</p>
- *
- * @param ref A reference to Ivy settings that must be used by this
component
- */
- public void setSettingsRef(Reference ref) {
- antIvyEngineRef = ref;
- }
-
- Reference getSettingsRef() {
- return antIvyEngineRef;
- }
-
- /**
- * Marks configurations as optional.
- *
- * <p>Any module that is included in the SBOM because it is required
by on of the configurations given in {@link
- * #setConf} and only is included because of configurations listed
here is marked optional. Including
- * configurations that are not part of {@link #setConf} doesn't have
any effect. {@code *} is no supported. The
- * default is to have no optional components.</p>
- *
- * @param comma separated list of the configurations to mark optional.
- */
- public void setOptionalConf(String optionalConf) {
- this.optionalConf = optionalConf;
- }
-
- String getOptionalConf() {
- return optionalConf;
- }
-
- /**
- * Marks configurations as external.
- *
- * <p>Any module that is included in the SBOM because it is required
by on of the configurations given in {@link
- * #setConf} and only is included because of configurations listed
here is marked external. Including
- * configurations that are not part of {@link #setConf} doesn't have
any effect. {@code *} is no supported. The
- * default is to have no external components.</p>
- *
- * @param comma separated list of the configurations to mark external.
- */
- public void setExternalConf(String externalConf) {
- this.externalConf = externalConf;
- }
-
- String getExternalConf() {
- return externalConf;
- }
-
- /**
- * The retrieve pattern used for retrieving the dependency artifacts.
- *
- * <p>Defaults to {@code ${ivy.retrieve.pattern}}.</p>
- */
- public void setPattern(String pattern) {
- this.pattern = pattern;
- }
-
- String getPattern() {
- return pattern;
- }
-
- /**
- * Adds a nested template component.
- *
- * @param c nested template component
- */
- public void addConfiguredTemplateComponent(Component c) {
- templateComponents.put(getTemplateComponentKey(c), c);
- }
-
- Map<String, Component> getTemplateComponents() {
- return templateComponents;
- }
-
- private static String getTemplateComponentKey(Component c) {
- String group = c.getGroup();
- if (group == null) {
- group = "";
- }
- String name = c.getName();
- if (name == null) {
- name = "";
- }
- return group + ":" + name;
- }
- }
}
diff --git a/src/main/org/apache/ant/cyclonedx/ComponentResolver.java
b/src/main/org/apache/ant/cyclonedx/ComponentResolver.java
new file mode 100644
index 0000000..3daace8
--- /dev/null
+++ b/src/main/org/apache/ant/cyclonedx/ComponentResolver.java
@@ -0,0 +1,41 @@
+/*
+ * 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
+ *
+ * https://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.
+ *
+ */
+package org.apache.ant.cyclonedx;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import org.apache.tools.ant.BuildException;
+
+/**
+ * Common interface for "resolvers" that read data of a component form
external sources and enrich an existing component
+ * withe data read - and may even identify additional components.
+ *
+ * <p>Any additional component detected may be added to the SBOM. If another
component already exists with the same
+ * group and name coordinates the additional component detected by this
instance is ignored.</p>
+ */
+public interface ComponentResolver {
+ /**
+ * Resolves the external data and enriches the component with it.
+ *
+ * @param component the component to enrich
+ * @return additional components identified while reading external data
+ * @throws IOException if resolution fails
+ */
+ Collection<Component> resolve(Component component) throws IOException,
BuildException;
+}
diff --git a/src/main/org/apache/ant/cyclonedx/IvyModuleComponentResolver.java
b/src/main/org/apache/ant/cyclonedx/IvyModuleComponentResolver.java
index 58ba715..12a8c28 100644
--- a/src/main/org/apache/ant/cyclonedx/IvyModuleComponentResolver.java
+++ b/src/main/org/apache/ant/cyclonedx/IvyModuleComponentResolver.java
@@ -45,8 +45,10 @@ 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.ProjectComponent;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.types.resources.URLResource;
@@ -64,18 +66,99 @@ import org.cyclonedx.model.Component.Scope;
*
* @since CycloneDX Antlib 0.2
*/
-class IvyModuleComponentResolver {
+public class IvyModuleComponentResolver extends ProjectComponent implements
ComponentResolver {
+
+ private String conf;
+ private String optionalConf;
+ private String externalConf;
+ private String resolveId;
+ private Reference settingRef;
+ private String pattern;
+ private Map<String, Component> templateComponents = new HashMap<>();
- private final Component.IvyModule ivyModule;
- private final Project project;
private boolean includeAllConfigurations;
private Set<String> includedConfigurations;
private Set<String> optionalConfigurations;
private Set<String> externalConfigurations;
- IvyModuleComponentResolver(Component.IvyModule ivyModule, Project project)
{
- this.ivyModule = ivyModule;
- this.project = project;
+ /**
+ * Sets the configurations to include in the SBOM.
+ *
+ * <p>Defaults to the configurations resolved by the last resolve call, or
{@code *} if no resolve was explicitly
+ * called</p>
+ *
+ * @param comma separated list of the configurations to retrieve or {@code
*}.
+ */
+ public void setConf(String conf) {
+ this.conf = conf;
+ }
+
+ /**
+ * Sets the id which was used for a previous resolve.
+ *
+ * <p>Defaults to {@code [org].[module]}.</p>
+ *
+ * @param id which was used for a previous resolve
+ */
+ public void setResolveId(String resolveId) {
+ this.resolveId = resolveId;
+ }
+
+ /**
+ * Sets a reference is a different Ivy settings file than the default
shall be used.
+ *
+ * <p>Defaults to {@code ivy.instance}.</p>
+ *
+ * @param ref A reference to Ivy settings that must be used by this
component
+ */
+ public void setSettingsRef(Reference ref) {
+ settingRef = ref;
+ }
+
+ /**
+ * Marks configurations as optional.
+ *
+ * <p>Any module that is included in the SBOM because it is required by on
of the configurations given in {@link
+ * #setConf} and only is included because of configurations listed here is
marked optional. Including configurations
+ * that are not part of {@link #setConf} doesn't have any effect. {@code
*} is no supported. The default is to have
+ * no optional components.</p>
+ *
+ * @param comma separated list of the configurations to mark optional.
+ */
+ public void setOptionalConf(String optionalConf) {
+ this.optionalConf = optionalConf;
+ }
+
+ /**
+ * Marks configurations as external.
+ *
+ * <p>Any module that is included in the SBOM because it is required by on
of the configurations given in {@link
+ * #setConf} and only is included because of configurations listed here is
marked external. Including configurations
+ * that are not part of {@link #setConf} doesn't have any effect. {@code
*} is no supported. The default is to have
+ * no external components.</p>
+ *
+ * @param comma separated list of the configurations to mark external.
+ */
+ public void setExternalConf(String externalConf) {
+ this.externalConf = externalConf;
+ }
+
+ /**
+ * The retrieve pattern used for retrieving the dependency artifacts.
+ *
+ * <p>Defaults to {@code ${ivy.retrieve.pattern}}.</p>
+ */
+ public void setPattern(String pattern) {
+ this.pattern = pattern;
+ }
+
+ /**
+ * Adds a nested template component.
+ *
+ * @param c nested template component
+ */
+ public void addConfiguredTemplateComponent(Component c) {
+ templateComponents.put(getTemplateComponentKey(c), c);
}
/**
@@ -109,19 +192,18 @@ class IvyModuleComponentResolver {
}
private Ivy createIvyInstance(Component component) {
- Reference settingRef = ivyModule.getSettingsRef();
IvyAntSettings engine;
if (settingRef == null) {
engine = IvyAntSettings.getDefaultInstance(component);
}
else {
- engine = settingRef.getReferencedObject(project);
+ engine = settingRef.getReferencedObject(getProject());
}
return engine.getConfiguredIvyInstance(component);
}
private void parseConfigurations(IvySettings settings) {
- String conf = ivyModule.getConf();
+ String conf = this.conf;
if (conf == null || "*".equals(conf)) {
conf = settings.getVariable("ivy.resolved.configurations");
}
@@ -134,8 +216,8 @@ class IvyModuleComponentResolver {
} else {
includedConfigurations = confAsSet(conf);
}
- optionalConfigurations = confAsSet(ivyModule.getOptionalConf());
- externalConfigurations = confAsSet(ivyModule.getExternalConf());
+ optionalConfigurations = confAsSet(optionalConf);
+ externalConfigurations = confAsSet(externalConf);
}
private ResolveReport loadResolveReport(IvySettings settings) {
@@ -159,15 +241,14 @@ class IvyModuleComponentResolver {
}
private ResolveReport getResolvedReport(String org, String module) {
- String resolveId = ivyModule.getResolveId();
ResolveReport report;
if (resolveId != null) {
- report = project.getReference("ivy.resolved.report." + resolveId);
+ report = getProject().getReference("ivy.resolved.report." +
resolveId);
} else {
- report = project.getReference("ivy.resolved.report." + org + "." +
module);
+ report = getProject().getReference("ivy.resolved.report." + org +
"." + module);
}
if (report == null) {
- report = project.getReference("ivy.resolved.report");
+ report = getProject().getReference("ivy.resolved.report");
}
return report;
}
@@ -178,9 +259,9 @@ class IvyModuleComponentResolver {
Set<ModuleRevisionId> externalModules,
Map<ModuleRevisionId, File> componentFiles) {
ModuleRevisionId mrid = md.getModuleRevisionId();
- Component template =
ivyModule.getTemplateComponents().get(mrid.getOrganisation() + ":" +
mrid.getName());
+ Component template = templateComponents.get(mrid.getOrganisation() +
":" + mrid.getName());
Component c = template == null ? new Component() : new
Component(template);
- c.setProject(project);
+ c.setProject(getProject());
fillFromModuleDescriptor(c, md, dependencyTree);
if (optionalModules.contains(mrid)) {
@@ -328,18 +409,18 @@ class IvyModuleComponentResolver {
private Map<ModuleRevisionId, File> findDownloadedArtifacts(Ivy ivy,
IvySettings
settings,
ModuleRevisionId mrid) {
- String pattern = ivyModule.getPattern();
+ String pattern = this.pattern;
if (pattern == null) {
pattern = settings.getVariable("ivy.retrieve.pattern");
}
if (pattern == null) {
- project.log("no retrieve pattern, won't look for dependency
artifact files");
+ 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");
+ log("no RetrieveEngine, won't look for dependency artifact files");
return Collections.emptyMap();
}
@@ -348,7 +429,6 @@ class IvyModuleComponentResolver {
? new String[] { "*" }
: includedConfigurations.toArray(new
String[includedConfigurations.size()]);
opts.setConfs(confs);
- String resolveId = ivyModule.getResolveId();
if (resolveId != null) {
opts.setResolveId(resolveId);
}
@@ -366,7 +446,7 @@ class IvyModuleComponentResolver {
}
return result;
} catch (ParseException | IOException e) {
- project.log(e.getMessage(), Project.MSG_ERR);
+ log(e.getMessage(), Project.MSG_ERR);
throw new BuildException("syntax errors in ivy file: " + e, e);
}
}
@@ -408,4 +488,16 @@ class IvyModuleComponentResolver {
ModuleRevisionId mrid = n.getId();
return "pkg:maven/" + mrid.getOrganisation() + "/" + mrid.getName() +
"@" + mrid.getRevision() + "?type=jar";
}
+
+ private static String getTemplateComponentKey(Component c) {
+ String group = c.getGroup();
+ if (group == null) {
+ group = "";
+ }
+ String name = c.getName();
+ if (name == null) {
+ name = "";
+ }
+ return group + ":" + name;
+ }
}
diff --git a/src/main/org/apache/ant/cyclonedx/SbomLinkComponentResolver.java
b/src/main/org/apache/ant/cyclonedx/SbomLinkComponentResolver.java
index d6f06f5..a1d877d 100644
--- a/src/main/org/apache/ant/cyclonedx/SbomLinkComponentResolver.java
+++ b/src/main/org/apache/ant/cyclonedx/SbomLinkComponentResolver.java
@@ -30,6 +30,7 @@ import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.resources.FileProvider;
+import org.apache.tools.ant.types.resources.Union;
import org.apache.tools.ant.types.resources.URLProvider;
import org.cyclonedx.exception.ParseException;
@@ -42,13 +43,23 @@ import org.cyclonedx.parsers.Parser;
*
* @since CycloneDX Antlib 0.2
*/
-class SbomLinkComponentResolver {
- private final Project project;
- private final Component.SbomLink sbomLink;
+public class SbomLinkComponentResolver extends Union implements
ComponentResolver {
+ private boolean createBomExternalReference = true;
- SbomLinkComponentResolver(Project project, Component.SbomLink sbomLink) {
- this.project = project;
- this.sbomLink = sbomLink;
+ /**
+ * Whether to create a bom-Type external reference in the
+ * resolved component based on the nested resource's URI.
+ *
+ * <p>Will not create an external reference of there are
+ * already external references om the component or the
+ * resolved SBOM already contains a bom-type reference.</p>
+ *
+ * <p>Defaults to <code>true</code>.
+ *
+ * @param create whether to create a bom-Type external reference
+ */
+ public void setCreateBomExternalReference(boolean create) {
+ createBomExternalReference = create;
}
/**
@@ -58,7 +69,7 @@ class SbomLinkComponentResolver {
* @param parent component the link applies to
* @return Components that are direct dependencies of the parent component
*/
- Collection<Component> resolve(Component parent) throws IOException,
BuildException {
+ public Collection<Component> resolve(Component parent) throws IOException,
BuildException {
Bom bom = readLinkedSbom();
if (bom.getMetadata() == null) {
throw new BuildException("referenced SBOM file lacks metadata");
@@ -78,10 +89,10 @@ class SbomLinkComponentResolver {
parent.fillFrom(real, Collections.emptyList());
}
- if (sbomLink.getCreateBomExternalReference()
+ if (createBomExternalReference
&& !parent.getExternalReferences().stream()
.anyMatch(e ->
e.getType().equals(org.cyclonedx.model.ExternalReference.Type.BOM))) {
- Resource sbom = sbomLink.iterator().next();
+ Resource sbom = iterator().next();
URLProvider up = sbom.as(URLProvider.class);
if (up != null) {
ExternalReference e = new ExternalReference();
@@ -102,10 +113,10 @@ class SbomLinkComponentResolver {
}
private Bom readLinkedSbom() throws IOException {
- if (sbomLink.size() != 1) {
+ if (size() != 1) {
throw new BuildException("sbomLink requires exactly one nested
resource");
}
- Resource sbom = sbomLink.iterator().next();
+ Resource sbom = iterator().next();
logSbom(sbom);
try (InputStream data = sbom.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
@@ -136,7 +147,7 @@ class SbomLinkComponentResolver {
name = up.getURL().toExternalForm();
}
}
- project.log("reading SBOM from " + name, Project.MSG_VERBOSE);
+ log("reading SBOM from " + name, Project.MSG_VERBOSE);
}
private List<Component>
extractComponentsThatAreDirectDependencies(Component parent,
diff --git a/src/main/org/apache/ant/cyclonedx/antlib.xml
b/src/main/org/apache/ant/cyclonedx/antlib.xml
index d773e30..63df8d1 100644
--- a/src/main/org/apache/ant/cyclonedx/antlib.xml
+++ b/src/main/org/apache/ant/cyclonedx/antlib.xml
@@ -83,4 +83,13 @@ under the License.
</cdx:componentbom>
</sequential>
</macrodef>
+
+ <!-- ComponentResolvers -->
+ <componentdef
+ name="sbomLink"
+ classname="org.apache.ant.cyclonedx.SbomLinkComponentResolver"/>
+ <componentdef
+ name="ivyModule"
+ classname="org.apache.ant.cyclonedx.IvyModuleComponentResolver"/>
+
</antlib>
diff --git a/src/tests/antunit/component-ivymodule-test.xml
b/src/tests/antunit/component-ivymodule-test.xml
index 1ffad58..bdb92d0 100644
--- a/src/tests/antunit/component-ivymodule-test.xml
+++ b/src/tests/antunit/component-ivymodule-test.xml
@@ -39,7 +39,7 @@
<cdx:componentbom outputdirectory="${output}" format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <ivymodule/>
+ <cdx:ivyModule/>
</component>
</cdx:componentbom>
</au:expectfailure>
@@ -51,7 +51,7 @@
<cdx:componentbom outputdirectory="${output}" format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <ivymodule/>
+ <cdx:ivyModule/>
</component>
</cdx:componentbom>
<xmlproperty file="${output}/bom.xml"/>
@@ -146,7 +146,7 @@
<cdx:componentbom outputdirectory="${output}" format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <ivymodule conf="default"/>
+ <cdx:ivyModule conf="default"/>
</component>
</cdx:componentbom>
<xmlproperty file="${output}/bom.xml"/>
@@ -168,7 +168,7 @@
<cdx:componentbom outputdirectory="${output}" format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <ivymodule optionalconf="ant"/>
+ <cdx:ivyModule optionalconf="ant"/>
</component>
</cdx:componentbom>
<xmlproperty file="${output}/bom.xml"/>
@@ -188,7 +188,7 @@
<cdx:componentbom outputdirectory="${output}" format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <ivymodule externalconf="ant"/>
+ <cdx:ivyModule externalconf="ant"/>
</component>
</cdx:componentbom>
<xmlproperty file="${output}/bom.xml"/>
@@ -211,7 +211,7 @@
<cdx:componentbom outputdirectory="${output}" format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <ivymodule resolveId="foo-bar-id"/>
+ <cdx:ivyModule resolveId="foo-bar-id"/>
</component>
</cdx:componentbom>
<xmlproperty file="${output}/bom.xml"/>
@@ -227,7 +227,7 @@
<cdx:componentbom outputdirectory="${output}" format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component description="my description">
- <ivymodule/>
+ <cdx:ivyModule/>
<manufacturer name="Example">
<url url="https://example.org/"/>
</manufacturer>
@@ -260,7 +260,7 @@
<cdx:componentbom outputdirectory="${output}" format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <ivymodule/>
+ <cdx:ivyModule/>
</component>
<additionalComponent
name="ant"
@@ -340,7 +340,7 @@
<cdx:componentbom outputdirectory="${output}" format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <ivymodule>
+ <cdx:ivyModule>
<templateComponent
name="ant"
group="org.apache.ant"
@@ -349,7 +349,7 @@
id="ant">
<manufacturer refid="ant-team"/>
</templateComponent>
- </ivymodule>
+ </cdx:ivyModule>
</component>
</cdx:componentbom>
<copy todir="/tmp" file="${output}/bom.xml"/>
diff --git a/src/tests/antunit/component-sbomlink-test.xml
b/src/tests/antunit/component-sbomlink-test.xml
index c75a2a0..d7a6a2e 100644
--- a/src/tests/antunit/component-sbomlink-test.xml
+++ b/src/tests/antunit/component-sbomlink-test.xml
@@ -26,9 +26,9 @@
format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <sbomLink>
+ <cdx:sbomLink>
<file file="${output}/bom.json"/>
- </sbomLink>
+ </cdx:sbomLink>
</component>
</cdx:componentbom>
<xmlproperty file="${output}/merged.xml"/>
@@ -165,9 +165,9 @@
format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <sbomLink>
+ <cdx:sbomLink>
<url
url="https://repo1.maven.org/maven2/org/apache/ant/ant-cyclonedx/0.1/ant-cyclonedx-0.1-cyclonedx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
</component>
</cdx:componentbom>
<xmlproperty file="${output}/merged.xml"/>
@@ -188,9 +188,9 @@
format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <sbomLink createBomExternalReference="false">
+ <cdx:sbomLink createBomExternalReference="false">
<url
url="https://repo1.maven.org/maven2/org/apache/ant/ant-cyclonedx/0.1/ant-cyclonedx-0.1-cyclonedx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
</component>
</cdx:componentbom>
<xmlproperty file="${output}/merged.xml"/>
@@ -207,9 +207,9 @@
format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <sbomLink>
+ <cdx:sbomLink>
<url
url="https://repo1.maven.org/maven2/org/apache/ant/ant-cyclonedx/0.1/ant-cyclonedx-0.1-cyclonedx.json"/>
- </sbomLink>
+ </cdx:sbomLink>
<externalReference type="bom" url="https://example.org/"/>
</component>
</cdx:componentbom>
@@ -233,9 +233,9 @@
format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component supplierIsManufacturer="true">
- <sbomLink>
+ <cdx:sbomLink>
<file file="${output}/bom.json"/>
- </sbomLink>
+ </cdx:sbomLink>
</component>
</cdx:componentbom>
<xmlproperty file="${output}/merged.xml"/>
@@ -290,9 +290,9 @@
<tag>label2</tag>
<property name="xyzzy" value="baz"/>
<dependency bomRef="my-own-dependency"/>
- <sbomLink>
+ <cdx:sbomLink>
<file file="${output}/bom.json"/>
- </sbomLink>
+ </cdx:sbomLink>
</component>
<additionalComponent name="my-own-dependency"
bomRef="my-own-dependency"/>
</cdx:componentbom>
@@ -441,9 +441,9 @@
format="xml"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
<component>
- <sbomLink>
+ <cdx:sbomLink>
<file file="${output}/bom.json"/>
- </sbomLink>
+ </cdx:sbomLink>
</component>
<additionalComponent
name="commons-codec"
diff --git a/src/tests/antunit/component-test.xml
b/src/tests/antunit/component-test.xml
index 75bd7c8..5a757b4 100644
--- a/src/tests/antunit/component-test.xml
+++ b/src/tests/antunit/component-test.xml
@@ -756,7 +756,7 @@
xmlns:au="antlib:org.apache.ant.antunit">
<cdx:component refid="foo"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
- <sbomLink/>
+ <cdx:sbomLink/>
</cdx:component>
</au:expectfailure>
<au:expectfailure
@@ -764,7 +764,7 @@
xmlns:au="antlib:org.apache.ant.antunit">
<cdx:component refid="foo"
xmlns:cdx="antlib:org.apache.ant.cyclonedx">
- <ivymodule/>
+ <cdx:ivyModule/>
</cdx:component>
</au:expectfailure>
</target>
@@ -772,11 +772,11 @@
<target
name="testSbomLinkAndIvyModuleAreMutuallyExclusive">
<au:expectfailure
- expectedMessage='sbomLink and ivyModule are mutually exclusive'
+ expectedMessage='only one resolver can be used at a time'
xmlns:au="antlib:org.apache.ant.antunit">
<cdx:component xmlns:cdx="antlib:org.apache.ant.cyclonedx">
- <sbomLink/>
- <ivymodule/>
+ <cdx:sbomLink/>
+ <cdx:ivyModule/>
</cdx:component>
</au:expectfailure>
</target>