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">

Reply via email to