From 9f5b308f44a73a7622b3ed3da988f5b3f967e611 Mon Sep 17 00:00:00 2001
From: Jan Kowalleck <jan.kowalleck@gmail.com>
Date: Mon, 20 Jan 2025 16:38:51 +0100
Subject: [PATCH 1/2] feat: licenses allow mix of multiple SPDX expressions
 AND/OR multiple named/spdx licenses

Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
---
 schema/bom-1.7.proto                          |  8 +-
 schema/bom-1.7.schema.json                    | 30 +++----
 schema/bom-1.7.xsd                            |  9 ++-
 ...id-license-declared-concluded-mix-1.6.json | 79 +++++++++++++++++++
 ...lid-license-declared-concluded-mix-1.6.xml | 46 +++++++++++
 ...id-license-declared-concluded-mix-1.7.json | 79 +++++++++++++++++++
 ...cense-declared-concluded-mix-1.7.textproto | 73 +++++++++++++++++
 ...lid-license-declared-concluded-mix-1.7.xml | 46 +++++++++++
 8 files changed, 343 insertions(+), 27 deletions(-)
 create mode 100644 tools/src/test/resources/1.6/invalid-license-declared-concluded-mix-1.6.json
 create mode 100644 tools/src/test/resources/1.6/invalid-license-declared-concluded-mix-1.6.xml
 create mode 100644 tools/src/test/resources/1.7/valid-license-declared-concluded-mix-1.7.json
 create mode 100644 tools/src/test/resources/1.7/valid-license-declared-concluded-mix-1.7.textproto
 create mode 100644 tools/src/test/resources/1.7/valid-license-declared-concluded-mix-1.7.xml

diff --git a/schema/bom-1.7.proto b/schema/bom-1.7.proto
index 4677eb5b..ec5aaf6a 100644
--- a/schema/bom-1.7.proto
+++ b/schema/bom-1.7.proto
@@ -114,7 +114,7 @@ message Component {
   optional Scope scope = 11;
   // The hashes of the component.
   repeated Hash hashes = 12;
-  // EITHER (list of SPDX licenses and/or named licenses) OR (tuple of one SPDX License Expression)
+  // A list of SPDX licenses and/or named licenses and/or SPDX License Expression.
   repeated LicenseChoice licenses = 13;
   // An optional copyright notice informing users of the underlying claims to copyright ownership in a published work.
   optional string copyright = 14;
@@ -506,7 +506,7 @@ message Metadata {
   // The organization that supplied the component that the BOM describes. The supplier may often be the manufacture, but may also be a distributor or repackager.
   optional OrganizationalEntity supplier = 6;
   // The license information for the BOM document. This may be different from the license(s) of the component(s) that the BOM describes.
-  // EITHER (list of SPDX licenses and/or named licenses) OR (tuple of one SPDX License Expression)
+  // A list of SPDX licenses and/or named licenses and/or SPDX License Expression.
   repeated LicenseChoice licenses = 7;
   // Specifies optional, custom, properties
   repeated Property properties = 8;
@@ -641,7 +641,7 @@ message Service {
   optional bool x_trust_boundary = 9;
   // Specifies information about the data including the directional flow of data and the data classification.
   repeated DataFlow data = 10;
-  // EITHER (list of SPDX licenses and/or named licenses) OR (tuple of one SPDX License Expression)
+  // A list of SPDX licenses and/or named licenses and/or SPDX License Expression.
   repeated LicenseChoice licenses = 11;
   // Provides the ability to document external references related to the service.
   repeated ExternalReference external_references = 12;
@@ -745,7 +745,7 @@ message EvidenceCopyright {
 
 // Provides the ability to document evidence collected through various forms of extraction or analysis.
 message Evidence {
-  // EITHER (list of SPDX licenses and/or named licenses) OR (tuple of one SPDX License Expression)
+  // A list of SPDX licenses and/or named licenses and/or SPDX License Expression.
   repeated LicenseChoice licenses = 1;
   // Copyright evidence captures intellectual property assertions, providing evidence of possible ownership and legal protection.
   repeated EvidenceCopyright copyright = 2;
diff --git a/schema/bom-1.7.schema.json b/schema/bom-1.7.schema.json
index 2a8e13ab..fdbd78ae 100644
--- a/schema/bom-1.7.schema.json
+++ b/schema/bom-1.7.schema.json
@@ -1454,14 +1454,11 @@
     },
     "licenseChoice": {
       "title": "License Choice",
-      "description": "EITHER (list of SPDX licenses and/or named licenses) OR (tuple of one SPDX License Expression)",
+      "description": "A list of SPDX licenses and/or named licenses and/or SPDX License Expression.",
       "type": "array",
-      "oneOf": [
-        {
-          "title": "Multiple licenses",
-          "description": "A list of SPDX licenses and/or named licenses.",
-          "type": "array",
-          "items": {
+      "items": {
+        "oneOf": [
+          {
             "type": "object",
             "title": "License",
             "required": ["license"],
@@ -1469,17 +1466,10 @@
             "properties": {
               "license": {"$ref": "#/definitions/license"}
             }
-          }
-        },
-        {
-          "title": "SPDX License Expression",
-          "description": "A tuple of exactly one SPDX License Expression.",
-          "type": "array",
-          "additionalItems": false,
-          "minItems": 1,
-          "maxItems": 1,
-          "items": [{
+          },
+          {
             "type": "object",
+            "title": "SPDX License Expression",
             "additionalProperties": false,
             "required": ["expression"],
             "properties": {
@@ -1501,9 +1491,9 @@
                 "description": "An optional identifier which can be used to reference the license elsewhere in the BOM. Every bom-ref must be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links."
               }
             }
-          }]
-        }
-      ]
+          }
+        ]
+      }
     },
     "commit": {
       "type": "object",
diff --git a/schema/bom-1.7.xsd b/schema/bom-1.7.xsd
index 173634c9..6b95e54f 100644
--- a/schema/bom-1.7.xsd
+++ b/schema/bom-1.7.xsd
@@ -2297,9 +2297,12 @@ limitations under the License.
     </xs:simpleType>
 
     <xs:complexType name="licenseChoiceType">
-        <xs:choice>
-            <xs:element name="license" type="bom:licenseType" minOccurs="0" maxOccurs="unbounded"/>
-            <xs:element name="expression" minOccurs="0" maxOccurs="1">
+        <xs:annotation>
+            <xs:documentation>A list of SPDX licenses and/or named licenses and/or SPDX License Expression.</xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="license" type="bom:licenseType"/>
+            <xs:element name="expression">
                 <xs:annotation>
                     <xs:documentation>A valid SPDX license expression.
                         Refer to https://spdx.org/specifications for syntax requirements
diff --git a/tools/src/test/resources/1.6/invalid-license-declared-concluded-mix-1.6.json b/tools/src/test/resources/1.6/invalid-license-declared-concluded-mix-1.6.json
new file mode 100644
index 00000000..7c6813c1
--- /dev/null
+++ b/tools/src/test/resources/1.6/invalid-license-declared-concluded-mix-1.6.json
@@ -0,0 +1,79 @@
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.6",
+  "serialNumber": "urn:uuid:df628836-6b9b-41c9-a724-b44743c54d42",
+  "version": 1,
+  "metadata": {
+    "lifecycles": [{"phase": "design"}]
+  },
+  "components": [
+    {
+      "type": "library",
+      "group": "com.example",
+      "name": "situation-A",
+      "version": "1",
+      "description": "Multiple licenses: declared ids/names, and a concluded expression",
+      "licenses": [
+        {
+          "license": {
+            "id": "MIT",
+            "acknowledgement": "declared"
+          }
+        },
+        {
+          "license": {
+            "id": "PostgreSQL",
+            "acknowledgement": "declared"
+          }
+        },
+        {
+          "license": {
+            "name": "Apache Software License",
+            "acknowledgement": "declared"
+          }
+        },
+        {
+          "expression": "(MIT OR PostgreSQL OR Apache-2.0)",
+          "acknowledgement": "concluded"
+        }
+      ]
+    },
+    {
+      "type": "library",
+      "group": "com.example",
+      "name": "situation-B",
+      "version": "1",
+      "description": "Multiple license expressions: one declared, one concluded",
+      "licenses": [
+        {
+          "expression": "MIT OR (GPL-3.0 OR GPL-2.0)",
+          "acknowledgement": "declared"
+        },
+        {
+          "expression": "(GPL-3.0-only AND LGPL-2.0-only)",
+          "acknowledgement": "concluded"
+        }
+      ]
+    },
+    {
+      "type": "library",
+      "group": "com.example",
+      "name": "situation-C",
+      "version": "1",
+      "description": "Multiple license: one declared expression, one concluded id",
+      "licenses": [
+        {
+          "expression": "GPL-3.0-or-later OR GPL-2.0",
+          "acknowledgement": "declared"
+        },
+        {
+          "license": {
+            "id": "GPL-3.0-only",
+            "acknowledgement": "concluded"
+          }
+        }
+      ]
+    }
+  ]
+}
diff --git a/tools/src/test/resources/1.6/invalid-license-declared-concluded-mix-1.6.xml b/tools/src/test/resources/1.6/invalid-license-declared-concluded-mix-1.6.xml
new file mode 100644
index 00000000..849ad97b
--- /dev/null
+++ b/tools/src/test/resources/1.6/invalid-license-declared-concluded-mix-1.6.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<bom xmlns="http://cyclonedx.org/schema/bom/1.6"
+     serialNumber="urn:uuid:df628836-6b9b-41c9-a724-b44743c54d42"
+>
+    <!--
+    All license posture in here is for show-case ony.
+    This is not a real law-case!
+    -->
+    <metadata>
+        <lifecycles><lifecycle><phase>design</phase></lifecycle></lifecycles>
+    </metadata>
+    <components>
+        <component type="library">
+            <group>com.example</group>
+            <name>situation-A</name>
+            <version>1</version>
+            <description>Multiple licenses: declared ids/names, and a concluded expression</description>
+            <licenses>
+                <license acknowledgement="declared"><id>MIT</id></license>
+                <license acknowledgement="declared"><id>PostgreSQL</id></license>
+                <license acknowledgement="declared"><name>Apache Software License</name></license>
+                <expression acknowledgement="concluded">(MIT OR PostgreSQL OR Apache-2.0)</expression>
+            </licenses>
+        </component>
+        <component type="library">
+            <group>com.example</group>
+            <name>situation-B</name>
+            <version>1</version>
+            <description>Multiple license expressions: one declared, one concluded</description>
+            <licenses>
+                <expression acknowledgement="declared">MIT OR (GPL-3.0 OR GPL-2.0)</expression>
+                <expression acknowledgement="concluded">(GPL-3.0-only AND LGPL-2.0-only)</expression>
+            </licenses>
+        </component>
+        <component type="library">
+            <group>com.example</group>
+            <name>situation-C</name>
+            <version>1</version>
+            <description>Multiple license: one declared expression, one concluded id</description>
+            <licenses>
+                <expression acknowledgement="declared">GPL-3.0-or-later OR GPL-2.0</expression>
+                <license acknowledgement="concluded"><id>GPL-3.0-only</id></license>
+            </licenses>
+        </component>
+    </components>
+</bom>
diff --git a/tools/src/test/resources/1.7/valid-license-declared-concluded-mix-1.7.json b/tools/src/test/resources/1.7/valid-license-declared-concluded-mix-1.7.json
new file mode 100644
index 00000000..82af9bf1
--- /dev/null
+++ b/tools/src/test/resources/1.7/valid-license-declared-concluded-mix-1.7.json
@@ -0,0 +1,79 @@
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.7",
+  "serialNumber": "urn:uuid:df628836-6b9b-41c9-a724-b44743c54d42",
+  "version": 1,
+  "metadata": {
+    "lifecycles": [{"phase": "design"}]
+  },
+  "components": [
+    {
+      "type": "library",
+      "group": "com.example",
+      "name": "situation-A",
+      "version": "1",
+      "description": "Multiple licenses: declared ids/names, and a concluded expression",
+      "licenses": [
+        {
+          "license": {
+            "id": "MIT",
+            "acknowledgement": "declared"
+          }
+        },
+        {
+          "license": {
+            "id": "PostgreSQL",
+            "acknowledgement": "declared"
+          }
+        },
+        {
+          "license": {
+            "name": "Apache Software License",
+            "acknowledgement": "declared"
+          }
+        },
+        {
+          "expression": "(MIT OR PostgreSQL OR Apache-2.0)",
+          "acknowledgement": "concluded"
+        }
+      ]
+    },
+    {
+      "type": "library",
+      "group": "com.example",
+      "name": "situation-B",
+      "version": "1",
+      "description": "Multiple license expressions: one declared, one concluded",
+      "licenses": [
+        {
+          "expression": "MIT OR (GPL-3.0 OR GPL-2.0)",
+          "acknowledgement": "declared"
+        },
+        {
+          "expression": "(GPL-3.0-only AND LGPL-2.0-only)",
+          "acknowledgement": "concluded"
+        }
+      ]
+    },
+    {
+      "type": "library",
+      "group": "com.example",
+      "name": "situation-C",
+      "version": "1",
+      "description": "Multiple license: one declared expression, one concluded id",
+      "licenses": [
+        {
+          "expression": "GPL-3.0-or-later OR GPL-2.0",
+          "acknowledgement": "declared"
+        },
+        {
+          "license": {
+            "id": "GPL-3.0-only",
+            "acknowledgement": "concluded"
+          }
+        }
+      ]
+    }
+  ]
+}
diff --git a/tools/src/test/resources/1.7/valid-license-declared-concluded-mix-1.7.textproto b/tools/src/test/resources/1.7/valid-license-declared-concluded-mix-1.7.textproto
new file mode 100644
index 00000000..fb0d57b8
--- /dev/null
+++ b/tools/src/test/resources/1.7/valid-license-declared-concluded-mix-1.7.textproto
@@ -0,0 +1,73 @@
+# proto-file: schema/bom-1.7.proto
+# proto-message: Bom
+
+# All license posture in here is for show-case ony.
+# This is not a real law-case!
+
+spec_version: "1.7"
+version: 1
+serial_number: "urn:uuid:df628836-6b9b-41c9-a724-b44743c54d42"
+metadata: {
+  lifecycles { phase: LIFECYCLE_PHASE_DESIGN }
+}
+components {
+  type: CLASSIFICATION_LIBRARY
+  group: "com.example"
+  name: "situation-A"
+  version: "1"
+  description: "Multiple licenses: declared ids/names, and a concluded expression"
+  licenses {
+    license {
+      id: "MIT"
+      acknowledgement: LICENSE_ACKNOWLEDGEMENT_ENUMERATION_DECLARED
+    }
+  }
+  licenses {
+    license {
+      id: "PostgreSQL"
+      acknowledgement: LICENSE_ACKNOWLEDGEMENT_ENUMERATION_DECLARED
+    }
+  }
+  licenses {
+    license {
+      name: "Apache Software License"
+      acknowledgement: LICENSE_ACKNOWLEDGEMENT_ENUMERATION_DECLARED
+    }
+  }
+  licenses {
+    expression: "(MIT OR PostgreSQL OR Apache-2.0)"
+    acknowledgement: LICENSE_ACKNOWLEDGEMENT_ENUMERATION_CONCLUDED
+  }
+}
+components {
+  type: CLASSIFICATION_LIBRARY
+  group: "com.example"
+  name: "situation-B"
+  version: "1"
+  description: "Multiple license expressions: one declared, one concluded"
+  licenses {
+    expression: "MIT OR (GPL-3.0 OR GPL-2.0)"
+    acknowledgement: LICENSE_ACKNOWLEDGEMENT_ENUMERATION_DECLARED
+  }
+  licenses {
+    expression: "(GPL-3.0-only AND LGPL-2.0-only)"
+    acknowledgement: LICENSE_ACKNOWLEDGEMENT_ENUMERATION_CONCLUDED
+  }
+}
+components {
+  type: CLASSIFICATION_LIBRARY
+  group: "com.example"
+  name: "situation-C"
+  version: "1"
+  description: "Multiple license: one declared expression, one concluded id"
+  licenses {
+    expression: "GPL-3.0-or-later OR GPL-2.0"
+    acknowledgement: LICENSE_ACKNOWLEDGEMENT_ENUMERATION_DECLARED
+  }
+  licenses {
+    license {
+      id: "GPL-3.0-only"
+      acknowledgement: LICENSE_ACKNOWLEDGEMENT_ENUMERATION_CONCLUDED
+    }
+  }
+}
diff --git a/tools/src/test/resources/1.7/valid-license-declared-concluded-mix-1.7.xml b/tools/src/test/resources/1.7/valid-license-declared-concluded-mix-1.7.xml
new file mode 100644
index 00000000..47c16c52
--- /dev/null
+++ b/tools/src/test/resources/1.7/valid-license-declared-concluded-mix-1.7.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<bom xmlns="http://cyclonedx.org/schema/bom/1.7"
+     serialNumber="urn:uuid:df628836-6b9b-41c9-a724-b44743c54d42"
+>
+    <!--
+    All license posture in here is for show-case ony.
+    This is not a real law-case!
+    -->
+    <metadata>
+        <lifecycles><lifecycle><phase>design</phase></lifecycle></lifecycles>
+    </metadata>
+    <components>
+        <component type="library">
+            <group>com.example</group>
+            <name>situation-A</name>
+            <version>1</version>
+            <description>Multiple licenses: declared ids/names, and a concluded expression</description>
+            <licenses>
+                <license acknowledgement="declared"><id>MIT</id></license>
+                <license acknowledgement="declared"><id>PostgreSQL</id></license>
+                <license acknowledgement="declared"><name>Apache Software License</name></license>
+                <expression acknowledgement="concluded">(MIT OR PostgreSQL OR Apache-2.0)</expression>
+            </licenses>
+        </component>
+        <component type="library">
+            <group>com.example</group>
+            <name>situation-B</name>
+            <version>1</version>
+            <description>Multiple license expressions: one declared, one concluded</description>
+            <licenses>
+                <expression acknowledgement="declared">MIT OR (GPL-3.0 OR GPL-2.0)</expression>
+                <expression acknowledgement="concluded">(GPL-3.0-only AND LGPL-2.0-only)</expression>
+            </licenses>
+        </component>
+        <component type="library">
+            <group>com.example</group>
+            <name>situation-C</name>
+            <version>1</version>
+            <description>Multiple license: one declared expression, one concluded id</description>
+            <licenses>
+                <expression acknowledgement="declared">GPL-3.0-or-later OR GPL-2.0</expression>
+                <license acknowledgement="concluded"><id>GPL-3.0-only</id></license>
+            </licenses>
+        </component>
+    </components>
+</bom>

From 4abbe2fce89f4f492ecc96da45cdbbac873f30c3 Mon Sep 17 00:00:00 2001
From: Jan Kowalleck <jan.kowalleck@gmail.com>
Date: Wed, 22 Jan 2025 10:37:51 +0100
Subject: [PATCH 2/2] tests

Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
---
 .../1.7/valid-license-choice-1.7.json         | 36 +++++++++++++++++++
 .../1.7/valid-license-choice-1.7.textproto    | 34 ++++++++++++++++++
 ...e-1.7.xml => valid-license-choice-1.7.xml} | 15 ++++----
 3 files changed, 78 insertions(+), 7 deletions(-)
 create mode 100644 tools/src/test/resources/1.7/valid-license-choice-1.7.json
 create mode 100644 tools/src/test/resources/1.7/valid-license-choice-1.7.textproto
 rename tools/src/test/resources/1.7/{invalid-license-choice-1.7.xml => valid-license-choice-1.7.xml} (53%)

diff --git a/tools/src/test/resources/1.7/valid-license-choice-1.7.json b/tools/src/test/resources/1.7/valid-license-choice-1.7.json
new file mode 100644
index 00000000..a7026109
--- /dev/null
+++ b/tools/src/test/resources/1.7/valid-license-choice-1.7.json
@@ -0,0 +1,36 @@
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.7",
+  "serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
+  "version": 1,
+  "components": [
+    {
+      "type": "application",
+      "publisher": "Acme Inc",
+      "group": "com.acme",
+      "name": "tomcat-catalina",
+      "version": "9.0.14",
+      "description": "Modified version of Apache Catalina",
+      "scope": "required",
+      "licenses": [
+        {
+          "license": {
+            "id": "Apache-2.0"
+          }
+        },
+        {
+          "expression": "EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0"
+        },
+        {
+          "license": {
+            "name": "My Own License",
+            "text": {
+              "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
+            }
+          }
+        }
+      ]
+    }
+  ]
+}
diff --git a/tools/src/test/resources/1.7/valid-license-choice-1.7.textproto b/tools/src/test/resources/1.7/valid-license-choice-1.7.textproto
new file mode 100644
index 00000000..7daa3d30
--- /dev/null
+++ b/tools/src/test/resources/1.7/valid-license-choice-1.7.textproto
@@ -0,0 +1,34 @@
+# proto-file: schema/bom-1.7.proto
+# proto-message: Bom
+
+# All license posture in here is for show-case ony.
+# This is not a real law-case!
+
+spec_version: "1.7"
+serial_number: "urn:uuid:b1ef52c6-7cd8-43d5-9e42-5e69044bbe9e"
+version: 1
+components {
+  type: CLASSIFICATION_APPLICATION
+  publisher: "Acme Inc"
+  group: "com.acme"
+  name: "tomcat-catalina"
+  version: "9.0.14"
+  description: "Modified version of Apache Catalina"
+  scope: SCOPE_REQUIRED
+  licenses {
+    license: {
+      id: "Apache-2.0"
+    }
+  }
+  licenses {
+    expression: "EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0"
+  }
+  licenses {
+    license: {
+      name: "My Own License"
+      text: {
+        value: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
+      }
+    }
+  }
+}
diff --git a/tools/src/test/resources/1.7/invalid-license-choice-1.7.xml b/tools/src/test/resources/1.7/valid-license-choice-1.7.xml
similarity index 53%
rename from tools/src/test/resources/1.7/invalid-license-choice-1.7.xml
rename to tools/src/test/resources/1.7/valid-license-choice-1.7.xml
index fec014d5..1947c9a2 100644
--- a/tools/src/test/resources/1.7/invalid-license-choice-1.7.xml
+++ b/tools/src/test/resources/1.7/valid-license-choice-1.7.xml
@@ -1,5 +1,8 @@
 <?xml version="1.0"?>
-<bom serialNumber="urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" version="1" xmlns="http://cyclonedx.org/schema/bom/1.7">
+<bom xmlns="http://cyclonedx.org/schema/bom/1.7"
+     serialNumber="urn:uuid:b1ef52c6-7cd8-43d5-9e42-5e69044bbe9e"
+     version="1"
+>
     <components>
         <component type="application">
             <publisher>Acme Inc</publisher>
@@ -8,17 +11,15 @@
             <version>9.0.14</version>
             <description>Modified version of Apache Catalina</description>
             <scope>required</scope>
-            <hashes>
-                <hash alg="MD5">3942447fac867ae5cdb3229b658f4d48</hash>
-                <hash alg="SHA-1">e6b1000b94e835ffd37f4c6dcbdad43f4b48a02a</hash>
-                <hash alg="SHA-256">f498a8ff2dd007e29c2074f5e4b01a9a01775c3ff3aeaf6906ea503bc5791b7b</hash>
-                <hash alg="SHA-512">e8f33e424f3f4ed6db76a482fde1a5298970e442c531729119e37991884bdffab4f9426b7ee11fccd074eeda0634d71697d6f88a460dce0ac8d627a29f7d1282</hash>
-            </hashes>
             <licenses>
                 <license>
                     <id>Apache-2.0</id>
                 </license>
                 <expression>EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0</expression>
+                <license>
+                    <name>My Own License</name>
+                    <text><![CDATA[Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.]]></text>
+                </license>
             </licenses>
             <purl>pkg:maven/com.acme/tomcat-catalina@9.0.14?packaging=jar</purl>
         </component>