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 d6d518e document attributes of componentbom task
d6d518e is described below
commit d6d518e861d2f47db9712c0fe758661fe03944e1
Author: Stefan Bodewig <[email protected]>
AuthorDate: Sat May 16 22:24:37 2026 +0200
document attributes of componentbom task
---
docs/component.html | 3 +
docs/componentbom.html | 97 ++++++++++++++++++++++
docs/index.html | 14 +++-
.../org/apache/ant/cyclonedx/ComponentBomTask.java | 50 +++++++----
src/tests/antunit/componentbom-test.xml | 53 ++++++++++++
5 files changed, 199 insertions(+), 18 deletions(-)
diff --git a/docs/component.html b/docs/component.html
index fbb402a..0a17123 100644
--- a/docs/component.html
+++ b/docs/component.html
@@ -186,6 +186,9 @@ <h4 id="sbomLink">sbomLink</h4>
library.</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>
+
<h4 id="manufacturer">manufacturer</h4>
<p>At most one nested <a href="organization.html">organization</a>
diff --git a/docs/componentbom.html b/docs/componentbom.html
new file mode 100644
index 0000000..740396a
--- /dev/null
+++ b/docs/componentbom.html
@@ -0,0 +1,97 @@
+<!--
+ 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 - componentbom Task</title>
+ </head>
+
+ <body>
+ <h2 id="componentbom">componentbom Task</h2>
+
+ <p>The <code>compomentbom</code> task creates CycloneDX SBOMs for
+ a component ind the formats supported by
+ the <a href="https://github.com/CycloneDX/cyclonedx-core-java">CycloneDX
+ Core (Java)</a> library.</p>
+
+ <p>As a minimum a single nested <code>component</code> element is
+ required that specifies the component to create an SBOM
+ for.</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>specVersion</td>
+ <td>Version of the CycloneDX specification for the generated
+ SBOM. This can be specified as number (like "1.6") or one of
+ the enum constants of the <code>org.cyclonedx.Version</code>
+ type (i.e. like "VERSION_16").<br/>
+ The supported values depend on the CycloneDX Core (Java)
+ library version used.
+ </td>
+ <td>No, defaults to "1.6" in the current version of the Ant
+ library but this may change in future versions.</td>
+ </tr>
+ <tr>
+ <td>format</td>
+ <td>The format of the SBOM(s) to write. May be "json", "xml"
+ (or rather the enum constants of
+ the <code>org.cyclonedx.Format</code> type and their file
+ extensions) or the special value "all". <br/>
+ For spec version 1.2 and later "all" means both "json" and
+ "xml" (so the task will create two files), for "1.0" and
+ "1.1" it is equivalent to "xml".<br/>
+ The supported values depend on the CycloneDX Core (Java)
+ library version used.
+ </td>
+ <td>No, defaults to "json".</td>
+ </tr>
+ <tr>
+ <td>bomName</td>
+ <td>The base name of the generated SBOM file. The full file
+ name will be <em>bomName</em>.<em>format</em>.</td>
+ <td>No, defaults to "bom".</td>
+ </tr>
+ <tr>
+ <td>outputDirectory</td>
+ <td>Sets the directory where the SBOM file(s) will be written
+ to. Relative paths are relative to the project's base
+ directory</td>
+ <td>No, defaults to the project's <code>basedir</code>.</td>
+ </tr>
+ <tr>
+ <td>useComponentSupplier</td>
+ <td>If set to <code>true</code> the supplier of the SBOM's
+ main component will be used for the SBOM itself.<br/>
+ If this is <code>true</code> the main component must specify
+ a supplier. Also you must not use a
+ nested <code>supplier</code> child for this task if this is
+ <code>true</code>.</td>
+ <td>No, defaults to <code>false</code>.</td>
+ </tr>
+ </table>
+
+ <h3>Nested elements</h3>
+ </body>
+</html>
diff --git a/docs/index.html b/docs/index.html
index b1f58fc..027f215 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
<body>
<h2>Introduction</h2>
- <p>This Ant library provides a layer of Ant types and a task to
+ <p>This Ant library provides Ant types and a task to
create <a href="https://cyclonedx.org/">CycloneDX</a> SBOMs.</p>
<p>The library is meant to be used for projects that manage their
@@ -52,13 +52,23 @@ <h2>Introduction</h2>
certainly welcome.</p>
<p>This manual follows the CycloneDX terminology closely, as do
- the tasks and types. It can not serve as an introduction to
+ the task and types. It can not serve as an introduction to
SBOMs, in particular as the authors understanding of the topic
may be limited or even wrong.</p>
<h2>Tasks and Types provided by this Ant Library</h2>
+ <p>The main entry point to this library is
+ the <a href="componentbom.html">componentbom</a> task that
+ creates CycloneDX SBOMs for a single component. The Ant types
+ provided by this library are mainly there as stand-alone types
+ so they can be reused if you need things in more than one SBOM -
+ because you are publishing multiple components or package them
+ in multiple artifacts for example.</p>
+
+ <p>The types provided by the library are:</p>
<ul>
+ <li><a href="component.html">component</a></li>
<li><a href="externalreferenceset.html">externalreferenceset</a></li>
<li><a href="license.html">license</a></li>
<li><a href="organization.html">organization</a></li>
diff --git a/src/main/org/apache/ant/cyclonedx/ComponentBomTask.java
b/src/main/org/apache/ant/cyclonedx/ComponentBomTask.java
index 887ec44..1edce7f 100644
--- a/src/main/org/apache/ant/cyclonedx/ComponentBomTask.java
+++ b/src/main/org/apache/ant/cyclonedx/ComponentBomTask.java
@@ -10,7 +10,6 @@ import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
-import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
@@ -35,7 +34,7 @@ import org.cyclonedx.model.Metadata;
import org.cyclonedx.model.OrganizationalEntity;
/**
- * Task that creates CycloneDX BOM for a single component.
+ * Task that creates CycloneDX BOMs for a single component.
*/
public class ComponentBomTask extends Task {
@@ -51,20 +50,44 @@ public class ComponentBomTask extends Task {
private Union pureFileComponents = new Union();
private List<org.cyclonedx.model.License> licenses = new ArrayList<>();
- public void setOutputDirectory(File f) {
- outputDirectory = f;
+ /**
+ * Specifies the CycloneDX version to use.
+ *
+ * <p>Defaults to 1.6.</p>
+ */
+ public void setSpecVersion(SpecVersion specVersion) {
+ this.specVersion = specVersion;
}
+ /**
+ * Which serialization format of CycloneDX SBOM to use.
+ */
+ public void setFormat(OutputFormat format) {
+ this.format = format;
+ }
+
+ /**
+ * Sets the base name of the generated BOM.
+ *
+ * <p>The file name will be the base name plus the extension of
+ * the {@see #setFormat format}.
+ */
public void setBomName(String bomName) {
this.bomName = bomName;
}
- public void setFormat(OutputFormat format) {
- this.format = format;
+ /**
+ * Sets the output directory for the generated SBOM.
+ */
+ public void setOutputDirectory(File f) {
+ outputDirectory = f;
}
- public void setSpecVersion(SpecVersion specVersion) {
- this.specVersion = specVersion;
+ /**
+ * Whether to use the supplier of the main component as supplier for the
BOM as well.
+ */
+ public void setUseComponentSupplier(boolean useComponentSupplier) {
+ this.useComponentSupplier = useComponentSupplier;
}
public Component createComponent() {
@@ -95,10 +118,6 @@ public class ComponentBomTask extends Task {
return supplier;
}
- public void setUseComponentSupplier(boolean useComponentSupplier) {
- this.useComponentSupplier = useComponentSupplier;
- }
-
public Union createPureFileComponents() {
return pureFileComponents;
}
@@ -114,7 +133,7 @@ public class ComponentBomTask extends Task {
if (supplier != null && useComponentSupplier) {
throw new BuildException("can't use component's supplier when
there is an explicit supplier");
}
- if (outputDirectory == null || !outputDirectory.isDirectory()) {
+ if (outputDirectory != null && !outputDirectory.isDirectory()) {
throw new BuildException("outputDirectory must point to a
directory");
}
if (pureFileComponents.size() > 0 &&
!pureFileComponents.isFilesystemOnly()) {
@@ -122,11 +141,10 @@ public class ComponentBomTask extends Task {
}
try {
+ File dir = outputDirectory != null ? outputDirectory :
getProject().getBaseDir();
Bom bom = createBom();
for (Format f :
format.getCycloneDxFormats(specVersion.getVersion())) {
- writeBom(bom, f,
- new File(outputDirectory,
- bomName + "." +
f.name().toLowerCase(Locale.ENGLISH)));
+ writeBom(bom, f, new File(dir, bomName + "." +
f.getExtension()));
}
} catch (IOException | GeneratorException ex) {
throw new BuildException("failed to write BOM", ex);
diff --git a/src/tests/antunit/componentbom-test.xml
b/src/tests/antunit/componentbom-test.xml
index 204e180..1912d8b 100644
--- a/src/tests/antunit/componentbom-test.xml
+++ b/src/tests/antunit/componentbom-test.xml
@@ -218,6 +218,59 @@
xmlns:au="antlib:org.apache.ant.antunit"
name="bom.metadata.supplier.url"
value="https://example.com/"/>
+
+ <au:expectfailure expectedMessage="useComponentSupplier is true but
component supplier is null"
+ xmlns:au="antlib:org.apache.ant.antunit">
+ <cdx:componentbom format="xml"
+ useComponentSupplier="true"
+ xmlns:cdx="antlib:org.apache.ant.cyclonedx">
+ <component name="testname"/>
+ </cdx:componentbom>
+ </au:expectfailure>
+
+ <au:expectfailure expectedMessage="can't use component's supplier when
there is an explicit supplier"
+ xmlns:au="antlib:org.apache.ant.antunit">
+ <cdx:componentbom format="xml"
+ useComponentSupplier="true"
+ xmlns:cdx="antlib:org.apache.ant.cyclonedx">
+ <component name="testname">
+ <supplier name="Foo"/>
+ </component>
+ <supplier name="Foo"/>
+ </cdx:componentbom>
+ </au:expectfailure>
+ </target>
+
+ <target name="testOutputDirectoryDefaultsToBaseDir">
+ <cdx:componentbom format="xml" xmlns:cdx="antlib:org.apache.ant.cyclonedx">
+ <component name="testname"/>
+ </cdx:componentbom>
+ <condition property="file-exists">
+ <available file="bom.xml"/>
+ </condition>
+ <delete file="bom.xml" failonerror="false" deleteonexit="true"/>
+ <au:assertPropertySet name="file-exists"
+ xmlns:au="antlib:org.apache.ant.antunit"/>
+ </target>
+
+ <target name="testOutputDirectoryMustExist">
+ <au:expectfailure expectedMessage="outputDirectory must point to a
directory"
+ xmlns:au="antlib:org.apache.ant.antunit">
+ <cdx:componentbom outputdirectory="foo" format="xml"
+ xmlns:cdx="antlib:org.apache.ant.cyclonedx">
+ <component name="testname"/>
+ </cdx:componentbom>
+ </au:expectfailure>
+ </target>
+
+ <target name="testOutputDirectoryMustBeADirectory">
+ <au:expectfailure expectedMessage="outputDirectory must point to a
directory"
+ xmlns:au="antlib:org.apache.ant.antunit">
+ <cdx:componentbom outputdirectory="${ant.file}" format="xml"
+ xmlns:cdx="antlib:org.apache.ant.cyclonedx">
+ <component name="testname"/>
+ </cdx:componentbom>
+ </au:expectfailure>
</target>
<target name="testComponentIsRequired">