1# This file is part of CycloneDX Python Lib
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15# SPDX-License-Identifier: Apache-2.0
16# Copyright (c) OWASP Foundation. All Rights Reserved.
17
18import sys
19
20from packageurl import PackageURL
21
22from cyclonedx.exception import MissingOptionalDependencyException
23from cyclonedx.factory.license import LicenseFactory
24from cyclonedx.model import OrganizationalEntity, XsUri
25from cyclonedx.model.bom import Bom
26from cyclonedx.model.component import Component, ComponentType
27from cyclonedx.output import make_outputter, LATEST_SUPPORTED_SCHEMA_VERSION
28from cyclonedx.output.json import JsonV1Dot4
29from cyclonedx.schema import SchemaVersion, OutputFormat
30from cyclonedx.validation.json import JsonStrictValidator
31from cyclonedx.validation import make_schemabased_validator
32
33from typing import TYPE_CHECKING
34
35if TYPE_CHECKING:
36 from cyclonedx.output.json import Json as JsonOutputter
37 from cyclonedx.output.xml import Xml as XmlOutputter
38 from cyclonedx.validation.xml import XmlValidator
39
40
41lc_factory = LicenseFactory()
42
43# region build the BOM
44
45bom = Bom()
46bom.metadata.component = root_component = Component(
47 name='myApp',
48 type=ComponentType.APPLICATION,
49 licenses=[lc_factory.make_from_string('MIT')],
50 bom_ref='myApp',
51)
52
53component1 = Component(
54 type=ComponentType.LIBRARY,
55 name='some-component',
56 group='acme',
57 version='1.33.7-beta.1',
58 licenses=[lc_factory.make_from_string('(c) 2021 Acme inc.')],
59 supplier=OrganizationalEntity(
60 name='Acme Inc',
61 urls=[XsUri('https://www.acme.org')]
62 ),
63 bom_ref='myComponent@1.33.7-beta.1',
64 purl=PackageURL('generic', 'acme', 'some-component', '1.33.7-beta.1')
65)
66bom.components.add(component1)
67bom.register_dependency(root_component, [component1])
68
69component2 = Component(
70 type=ComponentType.LIBRARY,
71 name='some-library',
72 licenses=[lc_factory.make_from_string('GPL-3.0-only WITH Classpath-exception-2.0')]
73)
74bom.components.add(component2)
75bom.register_dependency(component1, [component2])
76
77# endregion build the BOM
78
79# region JSON
80"""demo with explicit instructions for SchemaVersion, outputter and validator"""
81
82my_json_outputter: 'JsonOutputter' = JsonV1Dot4(bom)
83serialized_json = my_json_outputter.output_as_string(indent=2)
84print(serialized_json)
85my_json_validator = JsonStrictValidator(SchemaVersion.V1_4)
86try:
87 validation_errors = my_json_validator.validate_str(serialized_json)
88 if validation_errors:
89 print('JSON invalid', 'ValidationError:', repr(validation_errors), sep='\n', file=sys.stderr)
90 sys.exit(2)
91 print('JSON valid')
92except MissingOptionalDependencyException as error:
93 print('JSON-validation was skipped due to', error)
94
95print('', '=' * 30, '', sep='\n')
96
97# endregion JSON
98
99# region XML
100"""demo with implicit instructions for SchemaVersion, outputter and validator. TypeCheckers will catch errors."""
101
102my_xml_outputter: 'XmlOutputter' = make_outputter(bom, OutputFormat.XML, LATEST_SUPPORTED_SCHEMA_VERSION)
103serialized_xml = my_xml_outputter.output_as_string(indent=2)
104print(serialized_xml)
105my_xml_validator: 'XmlValidator' = make_schemabased_validator(
106 my_xml_outputter.output_format, my_xml_outputter.schema_version)
107try:
108 validation_errors = my_xml_validator.validate_str(serialized_xml)
109 if validation_errors:
110 print('XML invalid', 'ValidationError:', repr(validation_errors), sep='\n', file=sys.stderr)
111 sys.exit(2)
112 print('XML valid')
113except MissingOptionalDependencyException as error:
114 print('XML-validation was skipped due to', error)
115
116# endregion XML