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
commit e1a1b317709237322253ad999bf1234b3011ce25 Author: Stefan Bodewig <[email protected]> AuthorDate: Fri May 1 22:24:39 2026 +0200 supplier seems important to some validators --- examples/bom.json | 42 ++++++++++++++---------- examples/bom.xml | 40 ++++++++++++---------- src/main/org/apache/ant/cyclonedx/Component.java | 39 +++++++++++++++++++--- src/main/org/apache/ant/cyclonedx/ToolData.java | 3 +- src/tests/antunit/componentbom-test.xml | 8 +++++ 5 files changed, 90 insertions(+), 42 deletions(-) diff --git a/examples/bom.json b/examples/bom.json index b858f16..3887657 100644 --- a/examples/bom.json +++ b/examples/bom.json @@ -1,10 +1,10 @@ { "bomFormat" : "CycloneDX", "specVersion" : "1.6", - "serialNumber" : "urn:uuid:8cfe0788-fca0-491e-a48c-920ac2b05566", + "serialNumber" : "urn:uuid:9473c08b-477c-4087-9fb9-965d51f6b87b", "version" : 1, "metadata" : { - "timestamp" : "2026-05-01T19:53:39Z", + "timestamp" : "2026-05-01T20:20:09Z", "lifecycles" : [ { "phase" : "build" @@ -14,6 +14,12 @@ "components" : [ { "type" : "library", + "supplier" : { + "name" : "Apache Ant Development Team", + "url" : [ + "https://ant.apache.org/" + ] + }, "manufacturer" : { "name" : "Apache Ant Development Team", "url" : [ @@ -27,35 +33,35 @@ "hashes" : [ { "alg" : "MD5", - "content" : "a30e1771f4376fc5444a0eff34c57f35" + "content" : "8f400c4cf1c0fced3eb9e0bfd5d18485" }, { "alg" : "SHA-1", - "content" : "91174b265156be460602e86dd20456e1b1f3783f" + "content" : "9d6e76799441f34d56b39aca6415a36d510b463c" }, { "alg" : "SHA-256", - "content" : "938be9e478e3134df97d0ae0710d77ebbf39e3916e5f307db99bf131ddd39bb3" + "content" : "0b12ba1c7c6ae24a49581810c7495b92df933c150eddebf94522f5fdb19902d8" }, { "alg" : "SHA-512", - "content" : "be0b34697f1954938c3875ef857341d6e7fd276b083bd92ce904651c109911995db8d8420608734e348d54c45bcf72c5213223b84a8c88efbebb62a99edbfe90" + "content" : "7eb05a92293ead979a82953f4ac2eb560f7414b7d52a6caa651f2d71d95bee8c5deb1e85235ede013497400f005a938d7ce3647396a9f2c7859afaa5e1991102" }, { "alg" : "SHA3-256", - "content" : "d9a03b56538c8eb3531a333b3727c88e84e51255ddbcfcf324027f0cf5863182" + "content" : "18e97fdcdfb34cad170895bf01da95fdc83a77639ca32451bd7dcd3a313dbc47" }, { "alg" : "SHA3-512", - "content" : "a4653e504cb66e18f0629ed3b21ceb2aebf203ba7848bc96593011fc647435d6a2ae2f3ebe21df72413dd4b2a6ed690b2689cb24b4be3f90d3427f0b1111631d" + "content" : "dd80e9505830bcd1381ac41b5fb68f9eec5413c9eca02740bdcd2dcdb28a3dce2480a61da1f61fe1b5e27d5f50f95f46dabbb28fa05015140a34245eafd86e3b" }, { "alg" : "SHA-384", - "content" : "b94ebd288e066eb3663583b576d28abece610be66343db9e1a76145b0fa468f97b96a10f5aa24074d844586c048de6ce" + "content" : "e64ab7365de5350211165f5f1334d5bcd399d5e918a40791122b529f5f81b5200e83b1d62789b062a40671b45e2b7946" }, { "alg" : "SHA3-384", - "content" : "7262084714b890624a731ba65af3ae6b4ffe61bed2d6b6647114f52faa9b15d5a53e77a1f463c36bc5fb2b11e430687d" + "content" : "9a632d33939e993910ae7eedafb383a1ac6786b72e4e36a88f5873a3be8690577becd66cddc7875e97fcc98455c11bb3" } ], "licenses" : [ @@ -91,35 +97,35 @@ "hashes" : [ { "alg" : "MD5", - "content" : "a30e1771f4376fc5444a0eff34c57f35" + "content" : "8f400c4cf1c0fced3eb9e0bfd5d18485" }, { "alg" : "SHA-1", - "content" : "91174b265156be460602e86dd20456e1b1f3783f" + "content" : "9d6e76799441f34d56b39aca6415a36d510b463c" }, { "alg" : "SHA-256", - "content" : "938be9e478e3134df97d0ae0710d77ebbf39e3916e5f307db99bf131ddd39bb3" + "content" : "0b12ba1c7c6ae24a49581810c7495b92df933c150eddebf94522f5fdb19902d8" }, { "alg" : "SHA-512", - "content" : "be0b34697f1954938c3875ef857341d6e7fd276b083bd92ce904651c109911995db8d8420608734e348d54c45bcf72c5213223b84a8c88efbebb62a99edbfe90" + "content" : "7eb05a92293ead979a82953f4ac2eb560f7414b7d52a6caa651f2d71d95bee8c5deb1e85235ede013497400f005a938d7ce3647396a9f2c7859afaa5e1991102" }, { "alg" : "SHA3-256", - "content" : "d9a03b56538c8eb3531a333b3727c88e84e51255ddbcfcf324027f0cf5863182" + "content" : "18e97fdcdfb34cad170895bf01da95fdc83a77639ca32451bd7dcd3a313dbc47" }, { "alg" : "SHA3-512", - "content" : "a4653e504cb66e18f0629ed3b21ceb2aebf203ba7848bc96593011fc647435d6a2ae2f3ebe21df72413dd4b2a6ed690b2689cb24b4be3f90d3427f0b1111631d" + "content" : "dd80e9505830bcd1381ac41b5fb68f9eec5413c9eca02740bdcd2dcdb28a3dce2480a61da1f61fe1b5e27d5f50f95f46dabbb28fa05015140a34245eafd86e3b" }, { "alg" : "SHA-384", - "content" : "b94ebd288e066eb3663583b576d28abece610be66343db9e1a76145b0fa468f97b96a10f5aa24074d844586c048de6ce" + "content" : "e64ab7365de5350211165f5f1334d5bcd399d5e918a40791122b529f5f81b5200e83b1d62789b062a40671b45e2b7946" }, { "alg" : "SHA3-384", - "content" : "7262084714b890624a731ba65af3ae6b4ffe61bed2d6b6647114f52faa9b15d5a53e77a1f463c36bc5fb2b11e430687d" + "content" : "9a632d33939e993910ae7eedafb383a1ac6786b72e4e36a88f5873a3be8690577becd66cddc7875e97fcc98455c11bb3" } ], "licenses" : [ diff --git a/examples/bom.xml b/examples/bom.xml index b882d5b..82404a3 100644 --- a/examples/bom.xml +++ b/examples/bom.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> -<bom serialNumber="urn:uuid:b09e9df9-cc7f-4de4-a61d-489046a4358c" version="1" xmlns="http://cyclonedx.org/schema/bom/1.6"> +<bom serialNumber="urn:uuid:fdd9f10c-e0ba-4971-acdb-7dfe4f3c274d" version="1" xmlns="http://cyclonedx.org/schema/bom/1.6"> <metadata> - <timestamp>2026-05-01T19:53:39Z</timestamp> + <timestamp>2026-05-01T20:20:09Z</timestamp> <lifecycles> <lifecycle> <phase>build</phase> @@ -10,6 +10,10 @@ <tools> <components> <component type="library"> + <supplier> + <name>Apache Ant Development Team</name> + <url>https://ant.apache.org/</url> + </supplier> <manufacturer> <name>Apache Ant Development Team</name> <url>https://ant.apache.org/</url> @@ -19,14 +23,14 @@ <version>0.1alpha</version> <description>Apache CycloneDX Antlib</description> <hashes> - <hash alg="MD5">a30e1771f4376fc5444a0eff34c57f35</hash> - <hash alg="SHA-1">91174b265156be460602e86dd20456e1b1f3783f</hash> - <hash alg="SHA-256">938be9e478e3134df97d0ae0710d77ebbf39e3916e5f307db99bf131ddd39bb3</hash> - <hash alg="SHA-512">be0b34697f1954938c3875ef857341d6e7fd276b083bd92ce904651c109911995db8d8420608734e348d54c45bcf72c5213223b84a8c88efbebb62a99edbfe90</hash> - <hash alg="SHA3-256">d9a03b56538c8eb3531a333b3727c88e84e51255ddbcfcf324027f0cf5863182</hash> - <hash alg="SHA3-512">a4653e504cb66e18f0629ed3b21ceb2aebf203ba7848bc96593011fc647435d6a2ae2f3ebe21df72413dd4b2a6ed690b2689cb24b4be3f90d3427f0b1111631d</hash> - <hash alg="SHA-384">b94ebd288e066eb3663583b576d28abece610be66343db9e1a76145b0fa468f97b96a10f5aa24074d844586c048de6ce</hash> - <hash alg="SHA3-384">7262084714b890624a731ba65af3ae6b4ffe61bed2d6b6647114f52faa9b15d5a53e77a1f463c36bc5fb2b11e430687d</hash> + <hash alg="MD5">8f400c4cf1c0fced3eb9e0bfd5d18485</hash> + <hash alg="SHA-1">9d6e76799441f34d56b39aca6415a36d510b463c</hash> + <hash alg="SHA-256">0b12ba1c7c6ae24a49581810c7495b92df933c150eddebf94522f5fdb19902d8</hash> + <hash alg="SHA-512">7eb05a92293ead979a82953f4ac2eb560f7414b7d52a6caa651f2d71d95bee8c5deb1e85235ede013497400f005a938d7ce3647396a9f2c7859afaa5e1991102</hash> + <hash alg="SHA3-256">18e97fdcdfb34cad170895bf01da95fdc83a77639ca32451bd7dcd3a313dbc47</hash> + <hash alg="SHA3-512">dd80e9505830bcd1381ac41b5fb68f9eec5413c9eca02740bdcd2dcdb28a3dce2480a61da1f61fe1b5e27d5f50f95f46dabbb28fa05015140a34245eafd86e3b</hash> + <hash alg="SHA-384">e64ab7365de5350211165f5f1334d5bcd399d5e918a40791122b529f5f81b5200e83b1d62789b062a40671b45e2b7946</hash> + <hash alg="SHA3-384">9a632d33939e993910ae7eedafb383a1ac6786b72e4e36a88f5873a3be8690577becd66cddc7875e97fcc98455c11bb3</hash> </hashes> <licenses> <license> @@ -52,14 +56,14 @@ <version>0.1alpha</version> <description>Apache CycloneDX Antlib</description> <hashes> - <hash alg="MD5">a30e1771f4376fc5444a0eff34c57f35</hash> - <hash alg="SHA-1">91174b265156be460602e86dd20456e1b1f3783f</hash> - <hash alg="SHA-256">938be9e478e3134df97d0ae0710d77ebbf39e3916e5f307db99bf131ddd39bb3</hash> - <hash alg="SHA-512">be0b34697f1954938c3875ef857341d6e7fd276b083bd92ce904651c109911995db8d8420608734e348d54c45bcf72c5213223b84a8c88efbebb62a99edbfe90</hash> - <hash alg="SHA3-256">d9a03b56538c8eb3531a333b3727c88e84e51255ddbcfcf324027f0cf5863182</hash> - <hash alg="SHA3-512">a4653e504cb66e18f0629ed3b21ceb2aebf203ba7848bc96593011fc647435d6a2ae2f3ebe21df72413dd4b2a6ed690b2689cb24b4be3f90d3427f0b1111631d</hash> - <hash alg="SHA-384">b94ebd288e066eb3663583b576d28abece610be66343db9e1a76145b0fa468f97b96a10f5aa24074d844586c048de6ce</hash> - <hash alg="SHA3-384">7262084714b890624a731ba65af3ae6b4ffe61bed2d6b6647114f52faa9b15d5a53e77a1f463c36bc5fb2b11e430687d</hash> + <hash alg="MD5">8f400c4cf1c0fced3eb9e0bfd5d18485</hash> + <hash alg="SHA-1">9d6e76799441f34d56b39aca6415a36d510b463c</hash> + <hash alg="SHA-256">0b12ba1c7c6ae24a49581810c7495b92df933c150eddebf94522f5fdb19902d8</hash> + <hash alg="SHA-512">7eb05a92293ead979a82953f4ac2eb560f7414b7d52a6caa651f2d71d95bee8c5deb1e85235ede013497400f005a938d7ce3647396a9f2c7859afaa5e1991102</hash> + <hash alg="SHA3-256">18e97fdcdfb34cad170895bf01da95fdc83a77639ca32451bd7dcd3a313dbc47</hash> + <hash alg="SHA3-512">dd80e9505830bcd1381ac41b5fb68f9eec5413c9eca02740bdcd2dcdb28a3dce2480a61da1f61fe1b5e27d5f50f95f46dabbb28fa05015140a34245eafd86e3b</hash> + <hash alg="SHA-384">e64ab7365de5350211165f5f1334d5bcd399d5e918a40791122b529f5f81b5200e83b1d62789b062a40671b45e2b7946</hash> + <hash alg="SHA3-384">9a632d33939e993910ae7eedafb383a1ac6786b72e4e36a88f5873a3be8690577becd66cddc7875e97fcc98455c11bb3</hash> </hashes> <licenses> <license> diff --git a/src/main/org/apache/ant/cyclonedx/Component.java b/src/main/org/apache/ant/cyclonedx/Component.java index 26d3fb5..6813699 100644 --- a/src/main/org/apache/ant/cyclonedx/Component.java +++ b/src/main/org/apache/ant/cyclonedx/Component.java @@ -23,7 +23,9 @@ public class Component { private String group; private String version; private String description; - private Manufacturer manufacturer = null; + private Organization manufacturer = null; + private Organization supplier = null; + private boolean manufacturerIsSupplier = false; private List<org.cyclonedx.model.License> licenses = new ArrayList<>(); private String purl; private String bomRef; @@ -60,14 +62,26 @@ public class Component { this.description = description; } - public Manufacturer createManufacturer() { + public Organization createManufacturer() { if (manufacturer != null) { throw new BuildException("component can only have one manufacturer"); } - manufacturer = new Manufacturer(); + manufacturer = new Organization(); return manufacturer; } + public Organization createSupplier() { + if (supplier != null) { + throw new BuildException("component can only have one supplier"); + } + supplier = new Organization(); + return supplier; + } + + public void setManufacturerIsSupplier(boolean manufacturerIsSupplier) { + this.manufacturerIsSupplier = manufacturerIsSupplier; + } + public void addConfiguredLicense(License l) { licenses.add(l.toCycloneDxLicense()); } @@ -147,6 +161,14 @@ public class Component { if (name == null) { throw new BuildException("component name is required"); } + if (manufacturerIsSupplier) { + if (manufacturer == null) { + throw new BuildException("component without manufacturer can't use manufacturer as supplier"); + } + if (supplier != null) { + throw new BuildException("component with supplier can't use manufacturer as supplier"); + } + } org.cyclonedx.model.Component component = new org.cyclonedx.model.Component(); @@ -162,7 +184,14 @@ public class Component { component.setDescription(description); } if (manufacturer != null) { - component.setManufacturer(manufacturer.toOrganizationalEntity()); + OrganizationalEntity oe = manufacturer.toOrganizationalEntity(); + component.setManufacturer(oe); + if (manufacturerIsSupplier) { + component.setSupplier(oe); + } + } + if (supplier != null) { + component.setSupplier(supplier.toOrganizationalEntity()); } if (!licenses.isEmpty()) { LicenseChoice lc = new LicenseChoice(); @@ -209,7 +238,7 @@ public class Component { component.setHashes(BomUtils.calculateHashes(file, bomVersion)); } - public static class Manufacturer { + public static class Organization { private String name; private List<String> urls = new ArrayList<>(); diff --git a/src/main/org/apache/ant/cyclonedx/ToolData.java b/src/main/org/apache/ant/cyclonedx/ToolData.java index b686206..1894538 100644 --- a/src/main/org/apache/ant/cyclonedx/ToolData.java +++ b/src/main/org/apache/ant/cyclonedx/ToolData.java @@ -38,9 +38,10 @@ public class ToolData { antlibComponent.setVersion(getVersion()); antlibComponent.setDescription("Apache CycloneDX Antlib"); - Component.Manufacturer manufacturer = antlibComponent.createManufacturer(); + Component.Organization manufacturer = antlibComponent.createManufacturer(); manufacturer.setName("Apache Ant Development Team"); manufacturer.addConfiguredUrl(new URLResource("https://ant.apache.org/")); + antlibComponent.setManufacturerIsSupplier(true); Component.License license = new Component.License(); license.setLicenseId("Apache-2.0"); diff --git a/src/tests/antunit/componentbom-test.xml b/src/tests/antunit/componentbom-test.xml index ae48f41..fa3559f 100644 --- a/src/tests/antunit/componentbom-test.xml +++ b/src/tests/antunit/componentbom-test.xml @@ -96,6 +96,14 @@ xmlns:au="antlib:org.apache.ant.antunit" name="bom.metadata.tools.components.component.manufacturer.url" value="https://ant.apache.org/"/> + <au:assertPropertyEquals + xmlns:au="antlib:org.apache.ant.antunit" + name="bom.metadata.tools.components.component.supplier.name" + value="Apache Ant Development Team"/> + <au:assertPropertyEquals + xmlns:au="antlib:org.apache.ant.antunit" + name="bom.metadata.tools.components.component.supplier.url" + value="https://ant.apache.org/"/> <au:assertPropertyEquals xmlns:au="antlib:org.apache.ant.antunit" name="bom.metadata.tools.components.component.licenses.license.id"
