From 0653620033aaece6934312bea47bc195dbbf2e67 Mon Sep 17 00:00:00 2001 From: Taylor Sasser Date: Thu, 16 Oct 2025 13:40:45 -0400 Subject: [PATCH] cmSbom: Add SPDX object model and serializers Adds definitions for representing software bill of materials (SBOM) information and generating SPDX SBOMs. Issue: #26719 Issue: #27001 --- Source/CMakeLists.txt | 9 +- Source/cmSPDXSerializer.cxx | 1375 ------------------------- Source/cmSPDXSerializer.h | 1008 ------------------ Source/cmSPDXTypes.def | 54 - Source/cmSbomObject.h | 270 +++++ Source/cmSbomSerializer.h | 38 + Source/cmSpdx.cxx | 520 ++++++++++ Source/cmSpdx.h | 390 +++++++ Source/cmSpdxSerializer.cxx | 119 +++ Source/cmSpdxSerializer.h | 52 + Tests/CMakeLib/CMakeLists.txt | 2 +- Tests/CMakeLib/testSPDXSerializer.cxx | 649 ------------ Tests/CMakeLib/testSpdxSerializer.cxx | 84 ++ 13 files changed, 1480 insertions(+), 3090 deletions(-) delete mode 100644 Source/cmSPDXSerializer.cxx delete mode 100644 Source/cmSPDXSerializer.h delete mode 100644 Source/cmSPDXTypes.def create mode 100644 Source/cmSbomObject.h create mode 100644 Source/cmSbomSerializer.h create mode 100644 Source/cmSpdx.cxx create mode 100644 Source/cmSpdx.h create mode 100644 Source/cmSpdxSerializer.cxx create mode 100644 Source/cmSpdxSerializer.h delete mode 100644 Tests/CMakeLib/testSPDXSerializer.cxx create mode 100644 Tests/CMakeLib/testSpdxSerializer.cxx diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 44f87dba80..c76eee4788 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -701,6 +701,8 @@ add_library( cmRemoveDefinitionsCommand.h cmReturnCommand.cxx cmReturnCommand.h + cmSbomObject.h + cmSbomSerializer.h cmSearchPath.cxx cmSearchPath.h cmSeparateArgumentsCommand.cxx @@ -721,9 +723,10 @@ add_library( cmSiteNameCommand.h cmSourceGroupCommand.cxx cmSourceGroupCommand.h - cmSPDXSerializer.cxx - cmSPDXSerializer.h - cmSPDXTypes.def + cmSpdx.cxx + cmSpdx.h + cmSpdxSerializer.cxx + cmSpdxSerializer.h cmString.cxx cmString.hxx cmStringReplaceHelper.cxx diff --git a/Source/cmSPDXSerializer.cxx b/Source/cmSPDXSerializer.cxx deleted file mode 100644 index 7d221036fb..0000000000 --- a/Source/cmSPDXSerializer.cxx +++ /dev/null @@ -1,1375 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file LICENSE.rst or https://cmake.org/licensing for details. */ -#include "cmSPDXSerializer.h" - -#include -#include - -#include - -#include - -// Serialization Utilities - -template -void addVectorSPDXValue(Json::Value& obj, std::string const& key, - std::vector const& vec) -{ - auto& list = obj[key]; - list = Json::Value(Json::arrayValue); - for (auto const& val : vec) { - list.append(val.toJsonLD()); - } -} - -template <> -void addVectorSPDXValue(Json::Value& obj, std::string const& key, - std::vector const& vec) -{ - auto& list = obj[key]; - list = Json::Value(Json::arrayValue); - for (auto const& val : vec) { - list.append(val); - } -} - -template -void addOptionalSPDXValue(Json::Value& obj, std::string const& key, - cm::optional> const& opt) -{ - if (opt) { - addVectorSPDXValue(obj, key, *opt); - } -} - -template -void addOptionalSPDXValue(Json::Value& obj, std::string const& key, - cm::optional const& opt) -{ - if (opt) { - obj[key] = opt->toJsonLD(); - } -} - -template <> -void addOptionalSPDXValue(Json::Value& obj, std::string const& key, - cm::optional const& opt) -{ - if (opt) { - obj[key] = *opt; - } -} - -// Base Class - -cmSPDXSerializationBase::SPDXTypeId cmSPDXSerializationBase::getTypeId() const -{ - return TypeId; -} - -cmSPDXSerializationBase::cmSPDXSerializationBase(SPDXTypeId id) - : TypeId(id) -{ -} - -cmSPDXSerializationBase::cmSPDXSerializationBase(SPDXTypeId id, - std::string nodeId) - : NodeId(std::move(nodeId)) - , TypeId(id) -{ -} - -// Convenience Classes - -cmSPDXIdentifierReference::cmSPDXIdentifierReference() - : cmSPDXSerializationBase(CM_IDENTIFIER_REFERENCE) -{ -} -cmSPDXIdentifierReference::cmSPDXIdentifierReference( - cmSPDXSerializationBase const& ref) - : cmSPDXSerializationBase(CM_IDENTIFIER_REFERENCE, ref.NodeId) -{ -} -cmSPDXIdentifierReference::cmSPDXIdentifierReference(std::string const& ref) - : cmSPDXSerializationBase(CM_IDENTIFIER_REFERENCE, ref) -{ -} - -Json::Value cmSPDXIdentifierReference::toJsonLD() const -{ - return NodeId; -} - -cmSPDXNonElementBase::cmSPDXNonElementBase(SPDXTypeId id) - : cmSPDXSerializationBase(id) -{ -} - -Json::Value cmSPDXNonElementBase::toJsonLD() const -{ - Json::Value obj(Json::objectValue); - obj["@id"] = NodeId; - return obj; -} - -// SPDX Core Enums - -cmSPDXAnnotationType::cmSPDXAnnotationType(cmSPDXAnnotationTypeId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXAnnotationType::toJsonLD() const -{ - switch (TypeId) { - case OTHER: - return "other"; - case REVIEW: - return "review"; - default: - return "INVALID_ANNOTATION_TYPE_ID"; - } -} - -cmSPDXExternalIdentifierType::cmSPDXExternalIdentifierType( - cmSPDXExternalIdentifierTypeId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXExternalIdentifierType::toJsonLD() const -{ - switch (TypeId) { - case CPE22: - return "cpe22"; - case CPE23: - return "cpe23"; - case CVE: - return "cve"; - case EMAIL: - return "email"; - case GITOID: - return "gitoid"; - case OTHER: - return "other"; - case PACKAGE_URL: - return "packageUrl"; - case SECURITY_OTHER: - return "securityOther"; - case SWHID: - return "swhid"; - case SWID: - return "swid"; - case URL_SCHEME: - return "urlScheme"; - default: - return "INVALID_EXTERNAL_IDENTIFIER_TYPE_ID"; - } -} - -cmSPDXExternalRefType::cmSPDXExternalRefType(cmSPDXExternalRefTypeId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXExternalRefType::toJsonLD() const -{ - switch (TypeId) { - case ALT_DOWNLOAD_LOCATION: - return "altDownloadLocation:"; - case ALT_WEB_PAGE: - return "altWebPage"; - case BINARY_ARTIFACT: - return "binaryArtifact"; - case BOWER: - return "bower"; - case BUILD_META: - return "buildMeta"; - case BUILD_SYSTEM: - return "buildSystem"; - case CERTIFICATION_REPORT: - return "certificationReport"; - case CHAT: - return "chat"; - case COMPONENT_ANALYSIS_REPORT: - return "componentAnalysisReport"; - case CWE: - return "cwe"; - case DOCUMENTATION: - return "documentation"; - case DYNAMIC_ANALYSIS_REPORT: - return "dynamicAnalysisReport"; - case EOL_NOTICE: - return "eolNotice"; - case EXPORT_CONTROL_ASSESSMENT: - return "exportControlAssessment"; - case FUNDING: - return "funding"; - case ISSUE_TRACKER: - return "issueTracker"; - case LICENSE: - return "license"; - case MAILING_LIST: - return "mailingList"; - case MAVEN_CENTRAL: - return "mavenCentral"; - case METRICS: - return "metrics"; - case NPM: - return "npm"; - case NUGET: - return "nuget"; - case OTHER: - return "other"; - case PRIVACY_ASSESSMENT: - return "privacyAssessment"; - case PRODUCT_METADATA: - return "productMetadata"; - case PURCHASE_ORDER: - return "purchaseOrder"; - case QUALITY_ASSESSMENT_REPORT: - return "qualityAssessmentReport"; - case RELEASE_HISTORY: - return "releaseHistory"; - case RELEASE_NOTES: - return "releaseNotes"; - case RISK_ASSESSMENT: - return "riskAssessment"; - case RUNTIME_ANALYSIS_REPORT: - return "runtimeAnalysisReport"; - case SECURE_SOFTWARE_ATTESTATION: - return "secureSoftwareAttestation"; - case SECURITY_ADVERSARY_MODEL: - return "securityAdversaryModel"; - case SECURITY_ADVISORY: - return "securityAdvisory"; - case SECURITY_FIX: - return "securityFix"; - case SECURITY_OTHER: - return "securityOther"; - case SECURITY_PEN_TEST_REPORT: - return "securityPenTestReport"; - case SECURITY_POLICY: - return "securityPolicy"; - case SECURITY_THREAT_MODEL: - return "securityThreatModel"; - case SOCIAL_MEDIA: - return "socialMedia"; - case SOURCE_ARTIFACT: - return "sourceArtifact"; - case STATIC_ANALYSIS_REPORT: - return "staticAnalysisReport"; - case SUPPORT: - return "support"; - case VCS: - return "vcs"; - case VULNERABILITY_DISCLOSURE_REPORT: - return "vulnerabilityDisclosureReport"; - case VULNERABILITY_EXPLOITABILITY_ASSESSMENT: - return "vulnerabilityExploitabilityAssessment"; - default: - return "INVALID_EXTERNAL_REF_TYPE_ID"; - } -} - -cmSPDXHashAlgorithm::cmSPDXHashAlgorithm(cmSPDXHashAlgorithmId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXHashAlgorithm::toJsonLD() const -{ - switch (TypeId) { - case ADLER32: - return "adler32"; - case BLAKE2B256: - return "blake2b256"; - case BLAKE2B384: - return "blake2b384"; - case BLAKE2B512: - return "blake2b512"; - case BLAKE3: - return "blake3"; - case CRYSTALS_DILITHIUM: - return "crystalsDilithium"; - case CRYSTALS_KYBER: - return "crystalsLyber"; - case FALCON: - return "falcon"; - case MD2: - return "md2"; - case MD4: - return "md4"; - case MD5: - return "md5"; - case MD6: - return "md6"; - case OTHER: - return "other"; - case SHA1: - return "sha1"; - case SHA224: - return "sha224"; - case SHA256: - return "sha256"; - case SHA384: - return "sha384"; - case SHA3_224: - return "sha3_224"; - case SHA3_256: - return "sha3_256"; - case SHA3_384: - return "sha3_384"; - case SHA3_512: - return "sha3_512"; - case SHA512: - return "sha512"; - default: - return "INVALID_HASH_TYPE_ID"; - } -} - -cmSPDXLifecycleScopeType::cmSPDXLifecycleScopeType( - cmSPDXLifecycleScopeTypeId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXLifecycleScopeType::toJsonLD() const -{ - switch (TypeId) { - case BUILD: - return "build"; - case DESIGN: - return "design"; - case DEVELOPMENT: - return "development"; - case OTHER: - return "other"; - case RUNTIME: - return "runtime"; - case TEST: - return "test"; - default: - return "INVALID_LIFECYCLE_SCOPE_TYPE_ID"; - } -} - -cmSPDXProfileIdentifierType::cmSPDXProfileIdentifierType( - cmSPDXProfileIdentifierTypeId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXProfileIdentifierType::toJsonLD() const -{ - switch (TypeId) { - case AI: - return "ai"; - case BUILD: - return "build"; - case CORE: - return "code"; - case DATASET: - return "dataset"; - case EXPANDED_LICENSING: - return "expandedLicensing"; - case EXTENSION: - return "extension"; - case LITE: - return "lite"; - case SECURITY: - return "security"; - case SIMPLE_LICENSING: - return "simpleLicensing"; - case SOFTWARE: - return "software"; - default: - return "INVALID_PROFILE_IDENTIFIER_TYPE_ID"; - } -} - -cmSPDXRelationshipCompletenessType::cmSPDXRelationshipCompletenessType( - cmSPDXRelationshipCompletenessTypeId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXRelationshipCompletenessType::toJsonLD() const -{ - switch (TypeId) { - case COMPLETE: - return "complete"; - case INCOMPLETE: - return "incomplete"; - case NO_ASSERTION: - return "noAssertion"; - default: - return "INVALID_RELATIONSHIP_COMPLETENESS_TYPE_ID"; - } -} - -cmSPDXRelationshipType::cmSPDXRelationshipType(cmSPDXRelationshipTypeId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXRelationshipType::toJsonLD() const -{ - switch (TypeId) { - case AFFECTS: - return "affects"; - case AMENDED_BY: - return "amendedBy"; - case ANCESTOR_OF: - return "ancestorOf"; - case AVAILABLE_FROM: - return "availableFrom"; - case CONFIGURES: - return "configures"; - case CONTAINS: - return "contains"; - case COORDINATED_BY: - return "coordinatedBy"; - case COPIED_TO: - return "copiedTo"; - case DELEGATED_TO: - return "delegatedTo"; - case DEPENDS_ON: - return "dependsOn"; - case DESCENDANT_OF: - return "descendantOf"; - case DESCRIBES: - return "describes"; - case DOES_NOT_AFFECT: - return "doesNotAffect"; - case EXPANDS_TO: - return "expandsTo"; - case EXPLOIT_CREATED_BY: - return "exploitCreatedBy"; - case FIXED_BY: - return "fixedBy"; - case FIXED_IN: - return "fixedIn"; - case FOUND_BY: - return "foundBy"; - case GENERATES: - return "generates"; - case HAS_ADDED_FILE: - return "hasAddedFile"; - case HAS_ASSESSMENT_FOR: - return "hasAssessmentFor"; - case HAS_ASSOCIATED_VULNERABILITY: - return "hasAssociatedVulnerability"; - case HAS_CONCLUDED_LICENSE: - return "hasConcludedLicense"; - case HAS_DATA_FILE: - return "hasDataFile"; - case HAS_DECLARED_LICENSE: - return "hasDeclaredLicense"; - case HAS_DELETED_FILE: - return "hasDeletedFile"; - case HAS_DEPENDENCY_MANIFEST: - return "hasDependencyManifest"; - case HAS_DISTRIBUTION_ARTIFACT: - return "hasDistributionArtifact"; - case HAS_DOCUMENTATION: - return "hasDocumentation"; - case HAS_DYNAMIC_LINK: - return "hasDynamicLink"; - case HAS_EVIDENCE: - return "hasEvidence"; - case HAS_EXAMPLE: - return "hasExample"; - case HAS_HOST: - return "hasHost"; - case HAS_INPUT: - return "hasInput"; - case HAS_METADATA: - return "hasMetadata"; - case HAS_OPTIONAL_COMPONENT: - return "hasOptionalComponent"; - case HAS_OPTIONAL_DEPENDENCY: - return "hasOptionalDependency"; - case HAS_OUTPUT: - return "hasOutput"; - case HAS_PREREQUISITE: - return "hasPrerequisite"; - case HAS_PROVIDED_DEPENDENCY: - return "hasProvidedDependency"; - case HAS_REQUIREMENT: - return "hasRequirement"; - case HAS_SPECIFICATION: - return "hasSpecification"; - case HAS_STATIC_LINK: - return "hasStaticLink"; - case HAS_TEST: - return "hasTest"; - case HAS_TEST_CASE: - return "hasTestCase"; - case HAS_VARIANT: - return "hasVariant"; - case INVOKED_BY: - return "invokedBy"; - case MODIFIED_BY: - return "modifiedBy"; - case OTHER: - return "other"; - case PACKAGED_BY: - return "packagedBy"; - case PATCHED_BY: - return "patchedBy"; - case PUBLISHED_BY: - return "publishedBy"; - case REPORTED_BY: - return "reportedBy"; - case REPUBLISHED_BY: - return "republishedBy"; - case SERIALIZED_IN_ARTIFACT: - return "serializedInArtifact"; - case TESTED_ON: - return "testedOn"; - case TRAINED_ON: - return "trainedOn"; - case UNDER_INVESTIGATION_FOR: - return "underInvestigationFor"; - case USES_TOOL: - return "usesTool"; - default: - return "INVALID_RELATIONSHIP_TYPE_ID"; - } -} - -cmSPDXSupportType::cmSPDXSupportType(cmSPDXSupportTypeId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXSupportType::toJsonLD() const -{ - switch (TypeId) { - case DEPLOYED: - return "deployed"; - case DEVELOPMENT: - return "development"; - case END_OF_SUPPORT: - return "endOfSupport"; - case LIMITED_SUPPORT: - return "limitedSupport"; - case NO_ASSERTION: - return "noAssertion"; - case NO_SUPPORT: - return "noSupport"; - case SUPPORT: - return "support"; - default: - return "INVALID_SUPPORT_TYPE_ID"; - } -} - -// SPDX Core NonElement Classes, Abstract - -cmSPDXIntegrityMethod::cmSPDXIntegrityMethod(SPDXTypeId id) - : cmSPDXNonElementBase(id) -{ -} - -Json::Value cmSPDXIntegrityMethod::toJsonLD() const -{ - auto obj = cmSPDXNonElementBase::toJsonLD(); - addOptionalSPDXValue(obj, "comment", Comment); - return obj; -} - -// SPDX Core NonElement Classes, Concrete - -cmSPDXCreationInfo::cmSPDXCreationInfo() - : cmSPDXNonElementBase(CORE_CREATION_INFO) -{ -} - -Json::Value cmSPDXCreationInfo::toJsonLD() const -{ - auto obj = cmSPDXNonElementBase::toJsonLD(); - obj["type"] = "CreationInfo"; - addOptionalSPDXValue(obj, "Comment", Comment); - obj["created"] = Created; - addVectorSPDXValue(obj, "createdBy", CreatedBy); - addOptionalSPDXValue(obj, "createdUsing", CreatedUsing); - return obj; -} - -cmSPDXDictionaryEntry::cmSPDXDictionaryEntry() - : cmSPDXNonElementBase(CORE_DICTIONARY_ENTRY) -{ -} -cmSPDXDictionaryEntry::cmSPDXDictionaryEntry(std::string key) - : cmSPDXNonElementBase(CORE_DICTIONARY_ENTRY) - , Key(std::move(key)) -{ -} -cmSPDXDictionaryEntry::cmSPDXDictionaryEntry(std::string key, std::string val) - : cmSPDXNonElementBase(CORE_DICTIONARY_ENTRY) - , Key(std::move(key)) - , Value(std::move(val)) -{ -} - -Json::Value cmSPDXDictionaryEntry::toJsonLD() const -{ - auto obj = cmSPDXNonElementBase::toJsonLD(); - obj["type"] = "DictionaryEntry"; - obj["key"] = Key; - addOptionalSPDXValue(obj, "value", Value); - return obj; -} - -cmSPDXExternalIdentifier::cmSPDXExternalIdentifier() - : cmSPDXNonElementBase(CORE_EXTERNAL_IDENTIFIER) -{ -} - -Json::Value cmSPDXExternalIdentifier::toJsonLD() const -{ - auto obj = cmSPDXNonElementBase::toJsonLD(); - obj["type"] = "ExternalIdentifier"; - addOptionalSPDXValue(obj, "comment", Comment); - obj["externalIdentifierType"] = ExternalIdentifierType.toJsonLD(); - obj["identifier"] = Identifier; - addOptionalSPDXValue(obj, "identifierLocator", IdentifierLocator); - addOptionalSPDXValue(obj, "issuingAuthority", IssuingAuthority); - return obj; -} - -cmSPDXExternalMap::cmSPDXExternalMap() - : cmSPDXNonElementBase(CORE_EXTERNAL_MAP) -{ -} - -Json::Value cmSPDXExternalMap::toJsonLD() const -{ - auto obj = cmSPDXNonElementBase::toJsonLD(); - obj["type"] = "ExternalMap"; - addOptionalSPDXValue(obj, "definingArtifact", DefiningArtifact); - obj["externalSpdxId"] = ExternalSpdxId; - addOptionalSPDXValue(obj, "locationHint", LocationHint); - addOptionalSPDXValue(obj, "integrityMethod", IntegrityMethod); - return obj; -} - -cmSPDXExternalRef::cmSPDXExternalRef() - : cmSPDXNonElementBase(CORE_EXTERNAL_REF) -{ -} - -Json::Value cmSPDXExternalRef::toJsonLD() const -{ - auto obj = cmSPDXNonElementBase::toJsonLD(); - obj["type"] = "ExternalRef"; - addOptionalSPDXValue(obj, "comment", Comment); - addOptionalSPDXValue(obj, "contentType", ContentType); - addOptionalSPDXValue(obj, "externalRefType", ExternalRefType); - addOptionalSPDXValue(obj, "locator", Locator); - return obj; -} - -cmSPDXHash::cmSPDXHash() - : cmSPDXIntegrityMethod(CORE_HASH) -{ -} - -Json::Value cmSPDXHash::toJsonLD() const -{ - auto obj = cmSPDXIntegrityMethod::toJsonLD(); - obj["type"] = "Hash"; - obj["algorithm"] = Algorithm.toJsonLD(); - obj["hashValue"] = HashValue; - return obj; -} - -cmSPDXNamespaceMap::cmSPDXNamespaceMap() - : cmSPDXNonElementBase(CORE_NAMESPACE_MAP) -{ -} - -Json::Value cmSPDXNamespaceMap::toJsonLD() const -{ - auto obj = cmSPDXNonElementBase::toJsonLD(); - obj["type"] = "NamespaceMap"; - obj["namespace"] = Namespace; - obj["prefix"] = Namespace; - return obj; -} - -cmSPDXPackageVerificationCode::cmSPDXPackageVerificationCode() - : cmSPDXIntegrityMethod(CORE_PACKAGE_VERIFICATION_CODE) -{ -} - -Json::Value cmSPDXPackageVerificationCode::toJsonLD() const -{ - auto obj = cmSPDXIntegrityMethod::toJsonLD(); - obj["type"] = "PackageVerificationCode"; - obj["algorithm"] = Algorithm.toJsonLD(); - obj["hashValue"] = HashValue; - return obj; -} - -cmSPDXPositiveIntegerRange::cmSPDXPositiveIntegerRange( - unsigned int beingIntegerRange, unsigned int endIntegerRange) - : cmSPDXNonElementBase(CORE_POSITIVE_INTEGER_RANGE) - , BeginIntegerRange(beingIntegerRange) - , EndIntegerRange(endIntegerRange) -{ -} - -Json::Value cmSPDXPositiveIntegerRange::toJsonLD() const -{ - auto obj = cmSPDXNonElementBase::toJsonLD(); - obj["type"] = "PositiveIntegerRange"; - obj["beginIntegerRange"] = BeginIntegerRange; - obj["endIntegerRange"] = EndIntegerRange; - return obj; -} - -// SPDX Core Element Classes, Abstract - -cmSPDXElement::cmSPDXElement(SPDXTypeId id, - cmSPDXCreationInfo const& creationInfo) - : cmSPDXSerializationBase(id) - , CreationInfo(creationInfo) -{ -} - -Json::Value cmSPDXElement::toJsonLD() const -{ - Json::Value obj(Json::objectValue); - addOptionalSPDXValue(obj, "comment", Comment); - obj["creationInfo"] = CreationInfo.toJsonLD(); - addOptionalSPDXValue(obj, "description", Description); - addOptionalSPDXValue(obj, "extension", Extension); - addOptionalSPDXValue(obj, "externalIdentifier", ExternalIdentifier); - addOptionalSPDXValue(obj, "externalRef", ExternalRef); - addOptionalSPDXValue(obj, "name", Name); - obj["spdxId"] = NodeId; - addOptionalSPDXValue(obj, "summary", Summary); - addOptionalSPDXValue(obj, "verifiedUsing", VerifiedUsing); - return obj; -} - -cmSPDXArtifact::cmSPDXArtifact(SPDXTypeId id, - cmSPDXCreationInfo const& creationInfo) - : cmSPDXElement(id, creationInfo) -{ -} - -Json::Value cmSPDXArtifact::toJsonLD() const -{ - auto obj = cmSPDXElement::toJsonLD(); - addOptionalSPDXValue(obj, "builtTime", BuiltTime); - addOptionalSPDXValue(obj, "originateBy", OriginatedBy); - addOptionalSPDXValue(obj, "releaseTime", ReleaseTime); - addOptionalSPDXValue(obj, "standardName", StandardName); - addOptionalSPDXValue(obj, "suppliedBy", SuppliedBy); - addOptionalSPDXValue(obj, "supportType", SupportType); - addOptionalSPDXValue(obj, "validUntilTime", ValidUntilTime); - return obj; -} - -cmSPDXElementCollection::cmSPDXElementCollection( - SPDXTypeId id, cmSPDXCreationInfo const& creationInfo) - : cmSPDXElement(id, creationInfo) -{ -} - -Json::Value cmSPDXElementCollection::toJsonLD() const -{ - auto obj = cmSPDXElement::toJsonLD(); - addOptionalSPDXValue(obj, "element", Element); - addOptionalSPDXValue(obj, "profileConformance", ProfileConformance); - addOptionalSPDXValue(obj, "rootElement", RootElement); - return obj; -} - -// SPDX Implicit Core Element Classes, Abstract - -// Nominally an inheritable class, but adds nothing to Element -using cmSPDXAgentAbstract = cmSPDXElement; - -cmSPDXBundleAbstract::cmSPDXBundleAbstract( - SPDXTypeId id, cmSPDXCreationInfo const& creationInfo) - : cmSPDXElementCollection(id, creationInfo) -{ -} - -Json::Value cmSPDXBundleAbstract::toJsonLD() const -{ - auto obj = cmSPDXElementCollection::toJsonLD(); - obj["context"] = Context; - return obj; -} - -// Nominally an inheritable class, but adds nothing to Bundle -using cmSPDXBomAbstract = cmSPDXBundleAbstract; - -cmSPDXRelationshipAbstract::cmSPDXRelationshipAbstract( - SPDXTypeId id, cmSPDXCreationInfo const& creationInfo) - : cmSPDXElement(id, creationInfo) -{ -} - -Json::Value cmSPDXRelationshipAbstract::toJsonLD() const -{ - auto obj = cmSPDXElement::toJsonLD(); - addOptionalSPDXValue(obj, "completeness", Completeness); - addOptionalSPDXValue(obj, "endTime", EndTime); - obj["from"] = From.toJsonLD(); - obj["relationshipType"] = RelationshipType.toJsonLD(); - addOptionalSPDXValue(obj, "startTime", StartTime); - addVectorSPDXValue(obj, "to", To); - return obj; -} - -// SPDX Core Element Classes, Concrete - -cmSPDXAgent::cmSPDXAgent(cmSPDXCreationInfo const& creationInfo) - : cmSPDXAgentAbstract(CORE_AGENT, creationInfo) -{ -} - -Json::Value cmSPDXAgent::toJsonLD() const -{ - auto obj = cmSPDXAgentAbstract::toJsonLD(); - obj["type"] = "Agent"; - return obj; -} - -cmSPDXAnnotation::cmSPDXAnnotation(cmSPDXCreationInfo const& creationInfo, - cmSPDXIdentifierReference subject) - : cmSPDXElement(CORE_ANNOTATION, creationInfo) - , Subject(std::move(subject)) -{ -} - -Json::Value cmSPDXAnnotation::toJsonLD() const -{ - auto obj = cmSPDXElement::toJsonLD(); - obj["type"] = "Annotation"; - obj["annotationType"] = AnnotationType.toJsonLD(); - addOptionalSPDXValue(obj, "contentType", ContentType); - addOptionalSPDXValue(obj, "statement", Statement); - obj["subject"] = Subject.toJsonLD(); - return obj; -} - -cmSPDXBom::cmSPDXBom(cmSPDXCreationInfo const& creationInfo) - : cmSPDXBomAbstract(CORE_BOM, creationInfo) -{ -} - -Json::Value cmSPDXBom::toJsonLD() const -{ - auto obj = cmSPDXBomAbstract::toJsonLD(); - obj["type"] = "Bom"; - return obj; -} - -cmSPDXBundle::cmSPDXBundle(cmSPDXCreationInfo const& creationInfo) - : cmSPDXBundleAbstract(CORE_BUNDLE, creationInfo) -{ -} - -Json::Value cmSPDXBundle::toJsonLD() const -{ - auto obj = cmSPDXBundleAbstract::toJsonLD(); - obj["type"] = "Bundle"; - return obj; -} - -cmSPDXIndividualElement::cmSPDXIndividualElement( - cmSPDXCreationInfo const& creationInfo) - : cmSPDXElement(CORE_INDIVIDUAL_ELEMENT, creationInfo) -{ -} - -Json::Value cmSPDXIndividualElement::toJsonLD() const -{ - auto obj = cmSPDXElement::toJsonLD(); - obj["type"] = "IndividualElement"; - return obj; -} - -cmSPDXLifecycleScopedRelationship::cmSPDXLifecycleScopedRelationship( - cmSPDXCreationInfo const& creationInfo) - : cmSPDXRelationshipAbstract(CORE_LIFECYCLE_SCOPED_RELATIONSHIP, - creationInfo) -{ -} - -Json::Value cmSPDXLifecycleScopedRelationship::toJsonLD() const -{ - auto obj = cmSPDXRelationshipAbstract::toJsonLD(); - obj["type"] = "LifecycleScopedRelationship"; - addOptionalSPDXValue(obj, "scope", Scope); - return obj; -} - -cmSPDXOrganization::cmSPDXOrganization(cmSPDXCreationInfo const& creationInfo) - : cmSPDXAgentAbstract(CORE_ORGANIZATION, creationInfo) -{ -} - -Json::Value cmSPDXOrganization::toJsonLD() const -{ - auto obj = cmSPDXAgentAbstract::toJsonLD(); - obj["type"] = "Organization"; - return obj; -} - -cmSPDXPerson::cmSPDXPerson(cmSPDXCreationInfo const& creationInfo) - : cmSPDXAgentAbstract(CORE_PERSON, creationInfo) -{ -} - -Json::Value cmSPDXPerson::toJsonLD() const -{ - auto obj = cmSPDXAgentAbstract::toJsonLD(); - obj["type"] = "Person"; - return obj; -} - -cmSPDXRelationship::cmSPDXRelationship(cmSPDXCreationInfo const& creationInfo) - : cmSPDXRelationshipAbstract(CORE_RELATIONSHIP, creationInfo) -{ -} - -Json::Value cmSPDXRelationship::toJsonLD() const -{ - auto obj = cmSPDXRelationshipAbstract::toJsonLD(); - obj["type"] = "Relationship"; - return obj; -} - -cmSPDXSoftwareAgent::cmSPDXSoftwareAgent( - cmSPDXCreationInfo const& creationInfo) - : cmSPDXAgentAbstract(CORE_SOFTWARE_AGENT, creationInfo) -{ -} - -Json::Value cmSPDXSoftwareAgent::toJsonLD() const -{ - auto obj = cmSPDXAgentAbstract::toJsonLD(); - obj["type"] = "SoftwareAgent"; - return obj; -} - -cmSPDXSpdxDocument::cmSPDXSpdxDocument(cmSPDXCreationInfo const& creationInfo) - : cmSPDXElementCollection(CORE_SPDX_DOCUMENT, creationInfo) -{ -} - -Json::Value cmSPDXSpdxDocument::toJsonLD() const -{ - auto obj = cmSPDXElementCollection::toJsonLD(); - obj["type"] = "SpdxDocument"; - addOptionalSPDXValue(obj, "dataLicense", DataLicense); - addOptionalSPDXValue(obj, "externalMap", ExternalMap); - addOptionalSPDXValue(obj, "namespaceMap", NamespaceMap); - return obj; -} - -cmSPDXTool::cmSPDXTool(cmSPDXCreationInfo const& creationInfo) - : cmSPDXElement(CORE_TOOL, creationInfo) -{ -} - -Json::Value cmSPDXTool::toJsonLD() const -{ - auto obj = cmSPDXElement::toJsonLD(); - obj["type"] = "Tool"; - return obj; -} - -// SPDX Software Enums - -cmSPDXContentIdentifierType::cmSPDXContentIdentifierType( - cmSPDXContentIdentifierTypeId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXContentIdentifierType::toJsonLD() const -{ - switch (TypeId) { - case GITOID: - return "gitoid"; - case SWHID: - return "swhid"; - default: - return "INVALID_CONTENT_IDENTIFIER_TYPE_ID"; - } -} - -cmSPDXFileKindType::cmSPDXFileKindType(cmSPDXFileKindTypeId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXFileKindType::toJsonLD() const -{ - switch (TypeId) { - case DIRECTORY: - return "directory"; - case FILE: - return "file"; - default: - return "INVALID_FILE_KIND_TYPE_ID"; - } -} - -cmSPDXSbomType::cmSPDXSbomType(cmSPDXSbomTypeId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXSbomType::toJsonLD() const -{ - switch (TypeId) { - case ANALYZED: - return "analyzed"; - case BUILD: - return "build"; - case DEPLOYED: - return "deployed"; - case DESIGN: - return "design"; - case RUNTIME: - return "runtime"; - case SOURCE: - return "source"; - default: - return "INVALID_SBOM_TYPE_ID"; - } -} - -cmSPDXSoftwarePurpose::cmSPDXSoftwarePurpose(cmSPDXSoftwarePurposeId typeId) - : TypeId(typeId) -{ -} - -Json::Value cmSPDXSoftwarePurpose::toJsonLD() const -{ - switch (TypeId) { - case APPLICATION: - return "application"; - case ARCHIVE: - return "archive"; - case BOM: - return "bom"; - case CONFIGURATION: - return "configuration"; - case CONTAINER: - return "container"; - case DATA: - return "data"; - case DEVICE: - return "device"; - case DEVICE_DRIVER: - return "deviceDriver"; - case DISK_IMAGE: - return "diskImage"; - case DOCUMENTATION: - return "documentation"; - case EVIDENCE: - return "evidence"; - case EXECUTABLE: - return "executable"; - case FILE: - return "file"; - case FILESYSTEM_IMAGE: - return "filesystemImage"; - case FIRMWARE: - return "firmware"; - case FRAMEWORK: - return "framework"; - case INSTALL: - return "install"; - case LIBRARY: - return "library"; - case MANIFEST: - return "manifest"; - case MODEL: - return "model"; - case MODULE: - return "module"; - case OPERATING_SYSTEM: - return "operatingSystem"; - case OTHER: - return "other"; - case PATCH: - return "patch"; - case PLATFORM: - return "platform"; - case REQUIREMENT: - return "requirement"; - case SOURCE: - return "source"; - case SPECIFICATION: - return "specification"; - case TEST: - return "test"; - default: - return "INVALID_SOFTWARE_PURPOSE_ID"; - } -} - -// SPDX Software NonElement Classes, Concrete - -cmSPDXContentIdentifier::cmSPDXContentIdentifier() - : cmSPDXIntegrityMethod(SOFTWARE_CONTENT_IDENTIFIER) -{ -} - -Json::Value cmSPDXContentIdentifier::toJsonLD() const -{ - auto obj = cmSPDXIntegrityMethod::toJsonLD(); - obj["type"] = "ContentIdentifier"; - obj["contentIdentifierType"] = ContentIdentifierType.toJsonLD(); - obj["contentIdentifierValue"] = ContentIdentifierValue; - return obj; -} - -// SPDX Software Element Classes, Abstract - -cmSPDXSoftwareArtifact::cmSPDXSoftwareArtifact( - SPDXTypeId id, cmSPDXCreationInfo const& creationInfo) - : cmSPDXArtifact(id, creationInfo) -{ -} - -Json::Value cmSPDXSoftwareArtifact::toJsonLD() const -{ - auto obj = cmSPDXArtifact::toJsonLD(); - addOptionalSPDXValue(obj, "additionalPurpose", AdditionalPurpose); - addOptionalSPDXValue(obj, "attributionText", AttributionText); - addOptionalSPDXValue(obj, "contentIdentifier", ContentIdentifier); - addOptionalSPDXValue(obj, "copyrightText", CopyrightText); - addOptionalSPDXValue(obj, "primaryPurpose", PrimaryPurpose); - return obj; -} - -// SPDX Software Element Classes, Concrete - -cmSPDXFile::cmSPDXFile(cmSPDXCreationInfo const& creationInfo) - : cmSPDXSoftwareArtifact(SOFTWARE_FILE, creationInfo) -{ -} - -Json::Value cmSPDXFile::toJsonLD() const -{ - auto obj = cmSPDXSoftwareArtifact::toJsonLD(); - obj["type"] = "File"; - addOptionalSPDXValue(obj, "contentType", ContentType); - addOptionalSPDXValue(obj, "fileKind", FileKind); - return obj; -} - -cmSPDXPackage::cmSPDXPackage(cmSPDXCreationInfo const& creationInfo) - : cmSPDXSoftwareArtifact(SOFTWARE_PACKAGE, creationInfo) -{ -} - -Json::Value cmSPDXPackage::toJsonLD() const -{ - auto obj = cmSPDXSoftwareArtifact::toJsonLD(); - obj["type"] = "Package"; - addOptionalSPDXValue(obj, "downloadLocation", DownloadLocation); - addOptionalSPDXValue(obj, "homePage", HomePage); - addOptionalSPDXValue(obj, "packageUrl", PackageUrl); - addOptionalSPDXValue(obj, "packageVersion", PackageVersion); - addOptionalSPDXValue(obj, "sourceInfo", SourceInfo); - return obj; -} - -cmSPDXSbom::cmSPDXSbom(cmSPDXCreationInfo const& creationInfo) - : cmSPDXBomAbstract(SOFTWARE_SBOM, creationInfo) -{ -} - -Json::Value cmSPDXSbom::toJsonLD() const -{ - auto obj = cmSPDXBomAbstract::toJsonLD(); - obj["type"] = "Sbom"; - addOptionalSPDXValue(obj, "sbomType", SbomType); - return obj; -} - -cmSPDXSnippet::cmSPDXSnippet(cmSPDXCreationInfo const& creationInfo) - : cmSPDXSoftwareArtifact(SOFTWARE_SNIPPET, creationInfo) -{ -} - -Json::Value cmSPDXSnippet::toJsonLD() const -{ - auto obj = cmSPDXSoftwareArtifact::toJsonLD(); - obj["type"] = "Snippet"; - addOptionalSPDXValue(obj, "byteRange", ByteRange); - addOptionalSPDXValue(obj, "lineRange", LineRange); - obj["snippetFromFile"] = SnippetFromFile.toJsonLD(); - return obj; -} - -// SPDX SimpleLicensing Element Classes, Concrete - -cmSPDXLicenseExpression::cmSPDXLicenseExpression( - cmSPDXCreationInfo const& creationInfo) - : cmSPDXAnyLicenseInfo(SIMPLE_LICENSING_LICENSE_EXPRESSION, creationInfo) -{ -} - -Json::Value cmSPDXLicenseExpression::toJsonLD() const -{ - auto obj = cmSPDXAnyLicenseInfo::toJsonLD(); - obj["type"] = "LicenseExpression"; - addOptionalSPDXValue(obj, "customIdToUri", CustomIdToUri); - obj["licenseExpression"] = LicenseExpression; - addOptionalSPDXValue(obj, "licenseListVersion", LicenseListVersion); - return obj; -} - -cmSPDXSimpleLicensingText::cmSPDXSimpleLicensingText( - cmSPDXCreationInfo const& creationInfo) - : cmSPDXElement(SIMPLE_LICENSING_SIMPLE_LICENSING_TEXT, creationInfo) -{ -} - -Json::Value cmSPDXSimpleLicensingText::toJsonLD() const -{ - auto obj = cmSPDXElement::toJsonLD(); - obj["type"] = "SimpleLicensingText"; - obj["licenseText"] = LicenseText; - return obj; -} - -// Graph Manipulation - -#define X_SPDX(classtype, enumid, member, camel) \ - template <> \ - cmSPDXSerializationBase::SPDXTypeId cmSPDXGetTypeId() \ - { \ - return cmSPDXSerializationBase::enumid; \ - } \ - \ - template <> \ - std::string cmSPDXGetTypeName() \ - { \ - return #camel; \ - } \ - \ - cmSPDXObject::cmSPDXObject(classtype val) \ - : member(std::move(val)) {}; \ - \ - void cmSPDXObject::get(classtype** ptr) \ - { \ - *ptr = SerializationBase.getTypeId() == cmSPDXSerializationBase::enumid \ - ? &member \ - : nullptr; \ - } -#include "cmSPDXTypes.def" - -cmSPDXObject::cmSPDXObject() - : IdentifierReference("UNINITIALIZED_SPDX_OBJECT") -{ -} - -cmSPDXObject::cmSPDXObject(cmSPDXObject const& other) -{ - switch (other.SerializationBase.getTypeId()) { -#define X_SPDX(classtype, enumid, member, camel) \ - case cmSPDXSerializationBase::enumid: \ - new (&member) classtype(other.member); \ - break; -#include "cmSPDXTypes.def" - default: - new (&IdentifierReference) - cmSPDXIdentifierReference("UNINITIALIZED_SPDX_OBJECT"); - } -} - -cmSPDXObject::cmSPDXObject(cmSPDXObject&& other) noexcept -{ - switch (other.SerializationBase.getTypeId()) { -#define X_SPDX(classtype, enumid, member, camel) \ - case cmSPDXSerializationBase::enumid: \ - new (&member) classtype(std::move(other.member)); \ - break; -#include "cmSPDXTypes.def" - default: - new (&IdentifierReference) - cmSPDXIdentifierReference("UNINITIALIZED_SPDX_OBJECT"); - } -} - -cmSPDXObject& cmSPDXObject::operator=(cmSPDXObject const& other) -{ - this->~cmSPDXObject(); - new (this) cmSPDXObject(other); - return *this; -} - -cmSPDXObject& cmSPDXObject::operator=(cmSPDXObject&& other) noexcept -{ - this->~cmSPDXObject(); - new (this) cmSPDXObject(std::move(other)); - return *this; -} - -cmSPDXObject::~cmSPDXObject() -{ - switch (SerializationBase.getTypeId()) { -#define X_SPDX(classtype, enumid, member, camel) \ - case cmSPDXSerializationBase::enumid: \ - member.~classtype(); \ - break; -#include "cmSPDXTypes.def" - default: - break; - } -} - -Json::Value cmSPDXObject::toJsonLD() const -{ - switch (SerializationBase.getTypeId()) { -#define X_SPDX(classtype, enumid, member, camel) \ - case cmSPDXSerializationBase::enumid: \ - return member.toJsonLD(); -#include "cmSPDXTypes.def" - default: - return "INVALID_SPDX_OBJECT_TYPE_ID"; - } -} - -cmSPDXSimpleGraph::cmSPDXSimpleGraph(std::string iriBase, - cmSPDXCreationInfo creationInfo) - : IRIBase(std::move(iriBase)) - , CreationInfo(&insert(std::move(creationInfo))) -{ -} - -cmSPDXCreationInfo& cmSPDXSimpleGraph::getCreationInfo() -{ - return *CreationInfo; -} - -Json::Value cmSPDXSimpleGraph::toJsonLD() -{ - Json::Value obj(Json::objectValue); - obj["@context"] = "https://spdx.org/rdf/3.0.1/spdx-context.jsonld"; - - auto& graph = obj["@graph"]; - for (auto const& it : Graph) { - graph.append(it.second.toJsonLD()); - } - - return obj; -} diff --git a/Source/cmSPDXSerializer.h b/Source/cmSPDXSerializer.h deleted file mode 100644 index 65bf2144ad..0000000000 --- a/Source/cmSPDXSerializer.h +++ /dev/null @@ -1,1008 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file LICENSE.rst or https://cmake.org/licensing for details. */ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "cmStringAlgorithms.h" - -// Base Class - -struct cmSPDXSerializationBase -{ - enum SPDXTypeId - { - INVALID = -1, - NULL_ID = 0, - -#define X_SPDX(classtype, enumid, title, camel) enumid, -#include "cmSPDXTypes.def" - - SPDX_TYPE_ID_MAX, - }; - - SPDXTypeId getTypeId() const; - - std::string NodeId; - -protected: - cmSPDXSerializationBase(SPDXTypeId id); - cmSPDXSerializationBase(SPDXTypeId id, std::string nodeId); - -private: - SPDXTypeId TypeId; -}; - -// Convenience Classes - -struct cmSPDXIdentifierReference : cmSPDXSerializationBase -{ - cmSPDXIdentifierReference(); - cmSPDXIdentifierReference(cmSPDXSerializationBase const& ref); - cmSPDXIdentifierReference(std::string const& ref); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXNonElementBase : cmSPDXSerializationBase -{ -protected: - cmSPDXNonElementBase(SPDXTypeId id); - - Json::Value toJsonLD() const; -}; - -// SPDX Core Data Types - -// Nominally these are supposed to be validated strings -using cmSPDXDateTime = std::string; -using cmSPDXMediaType = std::string; -using cmSPDXSemVer = std::string; - -// SPDX Core Enums - -struct cmSPDXAnnotationType -{ - enum cmSPDXAnnotationTypeId - { - INVALID = -1, - NULL_ID = 0, - OTHER, - REVIEW, - }; - - cmSPDXAnnotationTypeId TypeId; - - cmSPDXAnnotationType(cmSPDXAnnotationTypeId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXExternalIdentifierType -{ - enum cmSPDXExternalIdentifierTypeId - { - INVALID = -1, - NULL_ID = 0, - CPE22, - CPE23, - CVE, - EMAIL, - GITOID, - OTHER, - PACKAGE_URL, - SECURITY_OTHER, - SWHID, - SWID, - URL_SCHEME, - }; - - cmSPDXExternalIdentifierTypeId TypeId; - - cmSPDXExternalIdentifierType( - cmSPDXExternalIdentifierTypeId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXExternalRefType -{ - enum cmSPDXExternalRefTypeId - { - INVALID = -1, - NULL_ID = 0, - ALT_DOWNLOAD_LOCATION, - ALT_WEB_PAGE, - BINARY_ARTIFACT, - BOWER, - BUILD_META, - BUILD_SYSTEM, - CERTIFICATION_REPORT, - CHAT, - COMPONENT_ANALYSIS_REPORT, - CWE, - DOCUMENTATION, - DYNAMIC_ANALYSIS_REPORT, - EOL_NOTICE, - EXPORT_CONTROL_ASSESSMENT, - FUNDING, - ISSUE_TRACKER, - LICENSE, - MAILING_LIST, - MAVEN_CENTRAL, - METRICS, - NPM, - NUGET, - OTHER, - PRIVACY_ASSESSMENT, - PRODUCT_METADATA, - PURCHASE_ORDER, - QUALITY_ASSESSMENT_REPORT, - RELEASE_HISTORY, - RELEASE_NOTES, - RISK_ASSESSMENT, - RUNTIME_ANALYSIS_REPORT, - SECURE_SOFTWARE_ATTESTATION, - SECURITY_ADVERSARY_MODEL, - SECURITY_ADVISORY, - SECURITY_FIX, - SECURITY_OTHER, - SECURITY_PEN_TEST_REPORT, - SECURITY_POLICY, - SECURITY_THREAT_MODEL, - SOCIAL_MEDIA, - SOURCE_ARTIFACT, - STATIC_ANALYSIS_REPORT, - SUPPORT, - VCS, - VULNERABILITY_DISCLOSURE_REPORT, - VULNERABILITY_EXPLOITABILITY_ASSESSMENT, - }; - - cmSPDXExternalRefTypeId TypeId; - - cmSPDXExternalRefType(cmSPDXExternalRefTypeId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXHashAlgorithm -{ - enum cmSPDXHashAlgorithmId - { - INVALID = -1, - NULL_ID = 0, - ADLER32, - BLAKE2B256, - BLAKE2B384, - BLAKE2B512, - BLAKE3, - CRYSTALS_DILITHIUM, - CRYSTALS_KYBER, - FALCON, - MD2, - MD4, - MD5, - MD6, - OTHER, - SHA1, - SHA224, - SHA256, - SHA384, - SHA3_224, - SHA3_256, - SHA3_384, - SHA3_512, - SHA512, - }; - - cmSPDXHashAlgorithmId TypeId; - - cmSPDXHashAlgorithm(cmSPDXHashAlgorithmId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXLifecycleScopeType -{ - enum cmSPDXLifecycleScopeTypeId - { - INVALID = -1, - NULL_ID = 0, - BUILD, - DESIGN, - DEVELOPMENT, - OTHER, - RUNTIME, - TEST, - }; - - cmSPDXLifecycleScopeTypeId TypeId; - - cmSPDXLifecycleScopeType(cmSPDXLifecycleScopeTypeId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXProfileIdentifierType -{ - enum cmSPDXProfileIdentifierTypeId - { - INVALID = -1, - NULL_ID = 0, - AI, - BUILD, - CORE, - DATASET, - EXPANDED_LICENSING, - EXTENSION, - LITE, - SECURITY, - SIMPLE_LICENSING, - SOFTWARE, - }; - - cmSPDXProfileIdentifierTypeId TypeId; - - cmSPDXProfileIdentifierType(cmSPDXProfileIdentifierTypeId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXRelationshipCompletenessType -{ - enum cmSPDXRelationshipCompletenessTypeId - { - INVALID = -1, - NULL_ID = 0, - COMPLETE, - INCOMPLETE, - NO_ASSERTION, - }; - - cmSPDXRelationshipCompletenessTypeId TypeId; - - cmSPDXRelationshipCompletenessType( - cmSPDXRelationshipCompletenessTypeId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXRelationshipType -{ - enum cmSPDXRelationshipTypeId - { - INVALID = -1, - NULL_ID = 0, - AFFECTS, - AMENDED_BY, - ANCESTOR_OF, - AVAILABLE_FROM, - CONFIGURES, - CONTAINS, - COORDINATED_BY, - COPIED_TO, - DELEGATED_TO, - DEPENDS_ON, - DESCENDANT_OF, - DESCRIBES, - DOES_NOT_AFFECT, - EXPANDS_TO, - EXPLOIT_CREATED_BY, - FIXED_BY, - FIXED_IN, - FOUND_BY, - GENERATES, - HAS_ADDED_FILE, - HAS_ASSESSMENT_FOR, - HAS_ASSOCIATED_VULNERABILITY, - HAS_CONCLUDED_LICENSE, - HAS_DATA_FILE, - HAS_DECLARED_LICENSE, - HAS_DELETED_FILE, - HAS_DEPENDENCY_MANIFEST, - HAS_DISTRIBUTION_ARTIFACT, - HAS_DOCUMENTATION, - HAS_DYNAMIC_LINK, - HAS_EVIDENCE, - HAS_EXAMPLE, - HAS_HOST, - HAS_INPUT, - HAS_METADATA, - HAS_OPTIONAL_COMPONENT, - HAS_OPTIONAL_DEPENDENCY, - HAS_OUTPUT, - HAS_PREREQUISITE, - HAS_PROVIDED_DEPENDENCY, - HAS_REQUIREMENT, - HAS_SPECIFICATION, - HAS_STATIC_LINK, - HAS_TEST, - HAS_TEST_CASE, - HAS_VARIANT, - INVOKED_BY, - MODIFIED_BY, - OTHER, - PACKAGED_BY, - PATCHED_BY, - PUBLISHED_BY, - REPORTED_BY, - REPUBLISHED_BY, - SERIALIZED_IN_ARTIFACT, - TESTED_ON, - TRAINED_ON, - UNDER_INVESTIGATION_FOR, - USES_TOOL, - }; - - cmSPDXRelationshipTypeId TypeId; - - cmSPDXRelationshipType(cmSPDXRelationshipTypeId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXSupportType -{ - enum cmSPDXSupportTypeId - { - INVALID = -1, - NULL_ID = 0, - DEPLOYED, - DEVELOPMENT, - END_OF_SUPPORT, - LIMITED_SUPPORT, - NO_ASSERTION, - NO_SUPPORT, - SUPPORT, - }; - - cmSPDXSupportTypeId TypeId; - - cmSPDXSupportType(cmSPDXSupportTypeId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -// SPDX Core NonElement Classes, Abstract - -struct cmSPDXIntegrityMethod : cmSPDXNonElementBase -{ - - cm::optional Comment; - -protected: - cmSPDXIntegrityMethod(SPDXTypeId id); - - Json::Value toJsonLD() const; -}; - -// SPDX Core NonElement Classes, Concrete - -struct cmSPDXCreationInfo : cmSPDXNonElementBase -{ - cm::optional Comment; - cmSPDXDateTime Created; - std::vector CreatedBy; - cm::optional> CreatedUsing; - - cmSPDXCreationInfo(); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXDictionaryEntry : cmSPDXNonElementBase -{ - std::string Key; - cm::optional Value; - - cmSPDXDictionaryEntry(); - cmSPDXDictionaryEntry(std::string key); - cmSPDXDictionaryEntry(std::string key, std::string val); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXExternalIdentifier : cmSPDXNonElementBase -{ - cm::optional Comment; - cmSPDXExternalIdentifierType ExternalIdentifierType; - std::string Identifier; - cm::optional> IdentifierLocator; - cm::optional IssuingAuthority; - - cmSPDXExternalIdentifier(); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXExternalMap : cmSPDXNonElementBase -{ - cm::optional DefiningArtifact; - std::string ExternalSpdxId; - cm::optional LocationHint; - cm::optional> IntegrityMethod; - - cmSPDXExternalMap(); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXExternalRef : cmSPDXNonElementBase -{ - cm::optional Comment; - cm::optional ContentType; - cm::optional ExternalRefType; - cm::optional> Locator; - - cmSPDXExternalRef(); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXHash : cmSPDXIntegrityMethod -{ - cmSPDXHashAlgorithm Algorithm; - std::string HashValue; - - cmSPDXHash(); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXNamespaceMap : cmSPDXNonElementBase -{ - std::string Namespace; - std::string Prefix; - - cmSPDXNamespaceMap(); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXPackageVerificationCode : cmSPDXIntegrityMethod -{ - cmSPDXHashAlgorithm Algorithm; - std::string HashValue; - cm::optional> PackageVerificationCodeExcludedFile; - - cmSPDXPackageVerificationCode(); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXPositiveIntegerRange : cmSPDXNonElementBase -{ - unsigned int BeginIntegerRange; - unsigned int EndIntegerRange; - - cmSPDXPositiveIntegerRange(unsigned int beingIntegerRange = 0, - unsigned int endIntegerRange = 0); - - Json::Value toJsonLD() const; -}; - -// SPDX Core Element Classes, Abstract - -struct cmSPDXElement : cmSPDXSerializationBase -{ - cm::optional Comment; - cmSPDXIdentifierReference CreationInfo; - cm::optional Description; - cm::optional> Extension; - cm::optional> ExternalIdentifier; - cm::optional> ExternalRef; - cm::optional Name; - // SpdxId is the NodeId - cm::optional Summary; - cm::optional> VerifiedUsing; - -protected: - cmSPDXElement(SPDXTypeId id, cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXArtifact : cmSPDXElement -{ - cm::optional BuiltTime; - cm::optional> OriginatedBy; - cm::optional ReleaseTime; - cm::optional> StandardName; - cm::optional SuppliedBy; - cm::optional> SupportType; - cm::optional ValidUntilTime; - -protected: - cmSPDXArtifact(SPDXTypeId id, cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXElementCollection : cmSPDXElement -{ - cm::optional> Element; - cm::optional> ProfileConformance; - cm::optional> RootElement; - -protected: - cmSPDXElementCollection(SPDXTypeId id, - cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -// SPDX Implicit Core Element Classes, Abstract - -// Nominally an inheritable class, but adds nothing to Element -using cmSPDXAgentAbstract = cmSPDXElement; - -struct cmSPDXBundleAbstract : cmSPDXElementCollection -{ - std::string Context; - -protected: - cmSPDXBundleAbstract(SPDXTypeId id, cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -// Nominally an inheritable class, but adds nothing to Bundle -using cmSPDXBomAbstract = cmSPDXBundleAbstract; - -struct cmSPDXRelationshipAbstract : cmSPDXElement -{ - cm::optional Completeness; - cm::optional EndTime; - cmSPDXIdentifierReference From; - cmSPDXRelationshipType RelationshipType; - cm::optional StartTime; - std::vector To; - -protected: - cmSPDXRelationshipAbstract(SPDXTypeId id, - cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -// SPDX Core Element Classes, Concrete - -struct cmSPDXAgent : cmSPDXAgentAbstract -{ - cmSPDXAgent(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXAnnotation : cmSPDXElement -{ - cmSPDXAnnotationType AnnotationType; - cm::optional ContentType; - cm::optional Statement; - cmSPDXIdentifierReference Subject; - - cmSPDXAnnotation(cmSPDXCreationInfo const& creationInfo, - cmSPDXIdentifierReference subject = {}); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXBom : cmSPDXBomAbstract -{ - cmSPDXBom(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXBundle : cmSPDXBundleAbstract -{ - cmSPDXBundle(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXIndividualElement : cmSPDXElement -{ - cmSPDXIndividualElement(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXLifecycleScopedRelationship : cmSPDXRelationshipAbstract -{ - cm::optional Scope; - - cmSPDXLifecycleScopedRelationship(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXOrganization : cmSPDXAgentAbstract -{ - cmSPDXOrganization(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXPerson : cmSPDXAgentAbstract -{ - cmSPDXPerson(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXRelationship : cmSPDXRelationshipAbstract -{ - cmSPDXRelationship(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXSoftwareAgent : cmSPDXAgentAbstract -{ - cmSPDXSoftwareAgent(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXSpdxDocument : cmSPDXElementCollection -{ - cm::optional DataLicense; - cm::optional ExternalMap; - cm::optional NamespaceMap; - - cmSPDXSpdxDocument(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXTool : cmSPDXElement -{ - cmSPDXTool(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -// SPDX Software Enums - -struct cmSPDXContentIdentifierType -{ - enum cmSPDXContentIdentifierTypeId - { - INVALID = -1, - NULL_ID = 0, - GITOID, - SWHID, - }; - - cmSPDXContentIdentifierTypeId TypeId; - - cmSPDXContentIdentifierType(cmSPDXContentIdentifierTypeId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXFileKindType -{ - enum cmSPDXFileKindTypeId - { - INVALID = -1, - NULL_ID = 0, - DIRECTORY, - FILE, - }; - - cmSPDXFileKindTypeId TypeId; - - cmSPDXFileKindType(cmSPDXFileKindTypeId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXSbomType -{ - enum cmSPDXSbomTypeId - { - INVALID = -1, - NULL_ID = 0, - ANALYZED, - BUILD, - DEPLOYED, - DESIGN, - RUNTIME, - SOURCE, - }; - - cmSPDXSbomTypeId TypeId; - - cmSPDXSbomType(cmSPDXSbomTypeId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXSoftwarePurpose -{ - enum cmSPDXSoftwarePurposeId - { - INVALID = -1, - NULL_ID = 0, - APPLICATION, - ARCHIVE, - BOM, - CONFIGURATION, - CONTAINER, - DATA, - DEVICE, - DEVICE_DRIVER, - DISK_IMAGE, - DOCUMENTATION, - EVIDENCE, - EXECUTABLE, - FILE, - FILESYSTEM_IMAGE, - FIRMWARE, - FRAMEWORK, - INSTALL, - LIBRARY, - MANIFEST, - MODEL, - MODULE, - OPERATING_SYSTEM, - OTHER, - PATCH, - PLATFORM, - REQUIREMENT, - SOURCE, - SPECIFICATION, - TEST, - }; - - cmSPDXSoftwarePurposeId TypeId; - - cmSPDXSoftwarePurpose(cmSPDXSoftwarePurposeId typeId = NULL_ID); - - Json::Value toJsonLD() const; -}; - -// SPDX Software NonElement Classes, Concrete - -struct cmSPDXContentIdentifier : cmSPDXIntegrityMethod -{ - cmSPDXContentIdentifierType ContentIdentifierType; - std::string ContentIdentifierValue; - - cmSPDXContentIdentifier(); - - Json::Value toJsonLD() const; -}; - -// SPDX Software Element Classes, Abstract - -struct cmSPDXSoftwareArtifact : cmSPDXArtifact -{ - cm::optional> AdditionalPurpose; - cm::optional AttributionText; - cm::optional ContentIdentifier; - cm::optional CopyrightText; - cm::optional PrimaryPurpose; - -protected: - cmSPDXSoftwareArtifact(SPDXTypeId id, - cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -// SPDX Software Element Classes, Concrete - -struct cmSPDXFile : cmSPDXSoftwareArtifact -{ - cm::optional ContentType; - cm::optional FileKind; - - cmSPDXFile(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXPackage : cmSPDXSoftwareArtifact -{ - cm::optional DownloadLocation; - cm::optional HomePage; - cm::optional PackageUrl; - cm::optional PackageVersion; - cm::optional SourceInfo; - - cmSPDXPackage(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXSbom : cmSPDXBomAbstract -{ - cm::optional> SbomType; - - cmSPDXSbom(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXSnippet : cmSPDXSoftwareArtifact -{ - cm::optional ByteRange; - cm::optional LineRange; - cmSPDXIdentifierReference SnippetFromFile; - - cmSPDXSnippet(cmSPDXCreationInfo const& creationInfo); - - Json::Value toJsonLD() const; -}; - -// SPDX SimpleLicensing Element Classes, Abstract - -// Nominally an inheritable class, but adds nothing to Element -using cmSPDXAnyLicenseInfo = cmSPDXElement; - -// SPDX SimpleLicensing Element Classes, Concrete - -struct cmSPDXLicenseExpression : cmSPDXAnyLicenseInfo -{ - cm::optional> CustomIdToUri; - std::string LicenseExpression; - cm::optional LicenseListVersion; - - cmSPDXLicenseExpression(cmSPDXCreationInfo const& CreationInfo); - - Json::Value toJsonLD() const; -}; - -struct cmSPDXSimpleLicensingText : cmSPDXElement -{ - std::string LicenseText; - - cmSPDXSimpleLicensingText(cmSPDXCreationInfo const& CreationInfo); - - Json::Value toJsonLD() const; -}; - -// Graph Manipulation - -template -cmSPDXSerializationBase::SPDXTypeId cmSPDXGetTypeId(); - -template -std::string cmSPDXGetTypeName(); - -#define X_SPDX(classtype, enumid, member, camel) \ - template <> \ - cmSPDXSerializationBase::SPDXTypeId cmSPDXGetTypeId(); \ - \ - template <> \ - std::string cmSPDXGetTypeName(); -#include "cmSPDXTypes.def" - -template -struct cmSPDXTag -{ - using type = T; -}; - -union cmSPDXObject -{ - - cmSPDXSerializationBase SerializationBase; - - cmSPDXObject(); - cmSPDXObject(cmSPDXObject const& other); - cmSPDXObject(cmSPDXObject&& other) noexcept; - -#define X_SPDX(classtype, enumid, member, camel) \ - classtype member; \ - cmSPDXObject(classtype val); \ - \ - template \ - cmSPDXObject(cmSPDXTag, Args&&... args) \ - { \ - new (&member) classtype(std::forward(args)...); \ - } -#include "cmSPDXTypes.def" - - cmSPDXObject& operator=(cmSPDXObject const& other); - cmSPDXObject& operator=(cmSPDXObject&& other) noexcept; - - ~cmSPDXObject(); - - template - T* get() - { - T* ptr; - get(&ptr); - return ptr; - } - - Json::Value toJsonLD() const; - -private: -#define X_SPDX(classtype, enumid, member, camel) void get(classtype** ptr); -#include "cmSPDXTypes.def" -}; - -struct cmSPDXSimpleGraph -{ - cmSPDXSimpleGraph(std::string iriBase, cmSPDXCreationInfo creationInfo = {}); - - template - cm::enable_if_t::value, T>& insert( - Args&&... args) - { - std::string nodeId = cmStrCat(IRIBase, IRICount++); - auto const& it = - Graph.emplace(std::piecewise_construct, std::forward_as_tuple(nodeId), - std::forward_as_tuple(cmSPDXTag{}, *CreationInfo, - std::forward(args)...)); - auto& node = *it.first->second.template get(); - node.NodeId = std::move(nodeId); - return node; - } - - cmSPDXCreationInfo& getCreationInfo(); - - template - cm::enable_if_t::value, T>& insert( - Args&&... args) - { - std::size_t nodeCount = BlankCounts[cmSPDXGetTypeId()]++; - std::string nodeId = - cmStrCat("_:", cmSPDXGetTypeName(), "_", nodeCount); - auto const& it = Graph.emplace( - std::piecewise_construct, std::forward_as_tuple(nodeId), - std::forward_as_tuple(cmSPDXTag{}, std::forward(args)...)); - auto& node = *it.first->second.template get(); - node.NodeId = std::move(nodeId); - return node; - } - - template - T* get(std::string const& key) - { - auto it = Graph.find(key); - if (it == Graph.end()) { - return nullptr; - } - return it->second.get(); - } - - template - T* get(cmSPDXIdentifierReference const& key) - { - auto it = Graph.find(key.NodeId); - if (it == Graph.end()) { - return nullptr; - } - return it->second.get(); - } - - Json::Value toJsonLD(); - -private: - std::string IRIBase; - std::size_t IRICount{ 0 }; - std::array - BlankCounts{}; - - std::map Graph; - cmSPDXCreationInfo* CreationInfo; -}; diff --git a/Source/cmSPDXTypes.def b/Source/cmSPDXTypes.def deleted file mode 100644 index 88d8043d7f..0000000000 --- a/Source/cmSPDXTypes.def +++ /dev/null @@ -1,54 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file LICENSE.rst or https://cmake.org/licensing for details. */ -#ifndef X_SPDX -# define X_SPDX(classtype, enumid, member, camel) -#endif - -// Convenience -X_SPDX(cmSPDXIdentifierReference, CM_IDENTIFIER_REFERENCE, IdentifierReference, - identifierReference) - -// Core -X_SPDX(cmSPDXAgent, CORE_AGENT, Agent, agent) -X_SPDX(cmSPDXAnnotation, CORE_ANNOTATION, Annotation, annotation) -X_SPDX(cmSPDXBom, CORE_BOM, Bom, bom) -X_SPDX(cmSPDXBundle, CORE_BUNDLE, Bundle, bundle) -X_SPDX(cmSPDXCreationInfo, CORE_CREATION_INFO, CreationInfo, creationInfo) -X_SPDX(cmSPDXDictionaryEntry, CORE_DICTIONARY_ENTRY, DictionaryEntry, - dictionaryEntry) -X_SPDX(cmSPDXExternalIdentifier, CORE_EXTERNAL_IDENTIFIER, ExternalIdentifier, - externalIdentifier) -X_SPDX(cmSPDXExternalMap, CORE_EXTERNAL_MAP, ExternalMap, externalMap) -X_SPDX(cmSPDXExternalRef, CORE_EXTERNAL_REF, ExternalRef, externalRef) -X_SPDX(cmSPDXHash, CORE_HASH, Hash, hash) -X_SPDX(cmSPDXIndividualElement, CORE_INDIVIDUAL_ELEMENT, IndividualElement, - individualElement) -X_SPDX(cmSPDXLifecycleScopedRelationship, CORE_LIFECYCLE_SCOPED_RELATIONSHIP, - LifecycleScopedRelationship, lifecycleScopedRelationship) -X_SPDX(cmSPDXNamespaceMap, CORE_NAMESPACE_MAP, NamespaceMap, namespaceMap) -X_SPDX(cmSPDXOrganization, CORE_ORGANIZATION, Organization, organization) -X_SPDX(cmSPDXPackageVerificationCode, CORE_PACKAGE_VERIFICATION_CODE, - PackageVerificationCode, packageVerificationCode) -X_SPDX(cmSPDXPerson, CORE_PERSON, Person, person) -X_SPDX(cmSPDXPositiveIntegerRange, CORE_POSITIVE_INTEGER_RANGE, - PositiveIntegerRange, positiveIntegerRange) -X_SPDX(cmSPDXRelationship, CORE_RELATIONSHIP, Relationship, relationship) -X_SPDX(cmSPDXSoftwareAgent, CORE_SOFTWARE_AGENT, SoftwareAgent, softwareAgent) -X_SPDX(cmSPDXSpdxDocument, CORE_SPDX_DOCUMENT, SpdxDocument, spdxDocument) -X_SPDX(cmSPDXTool, CORE_TOOL, Tool, tool) - -// Software -X_SPDX(cmSPDXContentIdentifier, SOFTWARE_CONTENT_IDENTIFIER, ContentIdentifier, - contentIdentifier) -X_SPDX(cmSPDXFile, SOFTWARE_FILE, File, file) -X_SPDX(cmSPDXPackage, SOFTWARE_PACKAGE, Package, package) -X_SPDX(cmSPDXSbom, SOFTWARE_SBOM, Sbom, sbom) -X_SPDX(cmSPDXSnippet, SOFTWARE_SNIPPET, Snippet, snippet) - -// SimpleLicensing -X_SPDX(cmSPDXLicenseExpression, SIMPLE_LICENSING_LICENSE_EXPRESSION, - LicenseExpression, licenseExpression) -X_SPDX(cmSPDXSimpleLicensingText, SIMPLE_LICENSING_SIMPLE_LICENSING_TEXT, - SimpleLicensingText, simpleLicensingText) - -#undef X_SPDX diff --git a/Source/cmSbomObject.h b/Source/cmSbomObject.h new file mode 100644 index 0000000000..3f42cfbd50 --- /dev/null +++ b/Source/cmSbomObject.h @@ -0,0 +1,270 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#pragma once + +#include +#include +#include +#include + +#include + +#include "cmSbomSerializer.h" + +class cmSbomObject; + +template +inline void SerializeDispatch(T const& t, cmSbomSerializer& serializer) +{ + serializer.BeginObject(); + t.Serialize(serializer); + serializer.EndObject(); +} + +template +inline void SerializeDispatch(T* p, cmSbomSerializer& serializer) +{ + if (p->SpdxId) { + serializer.AddReference(*p->SpdxId); + } +} + +inline void SerializeDispatch(std::nullptr_t, cmSbomSerializer&) +{ +} + +struct ObjectInterface +{ + virtual ObjectInterface* Copy(void* storage) const = 0; + virtual ObjectInterface* Move(void* storage) = 0; + virtual void* Addr() noexcept = 0; + virtual void const* Addr() const noexcept = 0; + virtual void SerializeImpl(cmSbomSerializer& os) const = 0; + virtual ~ObjectInterface() = default; + + ObjectInterface() = default; + ObjectInterface(ObjectInterface const&) = default; + ObjectInterface& operator=(ObjectInterface const&) = default; + ObjectInterface(ObjectInterface&&) noexcept = default; + ObjectInterface& operator=(ObjectInterface&&) noexcept = default; +}; + +namespace impl { + +#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20150623 +using max_align_t = ::max_align_t; +#else +using max_align_t = std::max_align_t; +#endif + +enum class StorageKind +{ + Stack, + Heap +}; + +template +struct Storage +{ +}; + +template +struct Storage : ObjectInterface +{ + using ValueType = cm::decay_t; + + explicit Storage(T x) + : Value(std::move(x)) + { + } + + Storage(Storage&&) noexcept( + std::is_nothrow_move_constructible::value) = default; + ~Storage() override = default; + + void* Addr() noexcept override { return std::addressof(Value); } + void const* Addr() const noexcept override { return std::addressof(Value); } + + ValueType& get() { return Value; } + ValueType const& get() const { return Value; } + +private: + ValueType Value; +}; + +template +struct Storage : ObjectInterface +{ + using ValueType = cm::decay_t; + + explicit Storage(T x) + : Ptr(new T(std::move(x))) + { + } + + Storage(Storage&&) noexcept = default; + ~Storage() override = default; + + void* Addr() noexcept override { return Ptr.get(); } + void const* Addr() const noexcept override { return Ptr.get(); } + + ValueType& get() { return *Ptr; } + ValueType const& get() const { return *Ptr; } + +private: + std::unique_ptr Ptr; +}; + +template <> +struct Storage : ObjectInterface +{ + explicit Storage(std::nullptr_t) {} + + Storage(Storage&&) noexcept = default; + ~Storage() override = default; + + void* Addr() noexcept override { return nullptr; } + void const* Addr() const noexcept override { return nullptr; } + + void SerializeImpl(cmSbomSerializer&) const override {} + + std::nullptr_t get() { return nullptr; } + std::nullptr_t get() const { return nullptr; } +}; + +} + +struct ObjectStorage +{ + template + using Stack = impl::Storage; + template + using Heap = impl::Storage; + + static constexpr std::size_t BufferSize = 128u; + + static constexpr std::size_t Size = sizeof(Heap) > BufferSize + ? sizeof(Heap) + : BufferSize; + static constexpr std::size_t Align = alignof(impl::max_align_t); + + struct Buffer + { + alignas(Align) unsigned char Data[Size]; + }; + + template + using Model = cm::conditional_t) <= Size && + alignof(Stack) <= Align, + Stack, Heap>; +}; + +class cmSbomObject +{ +public: + template + struct Instance : ObjectStorage::Model + { + using Base = ObjectStorage::Model; + using Base::Base; + Instance(Instance&&) noexcept = default; + + ObjectInterface* Copy(void* storage) const override + { + return ::new (storage) Instance(this->get()); + } + + ObjectInterface* Move(void* storage) override + { + return ::new (storage) Instance(std::move(*this)); + } + + void SerializeImpl(cmSbomSerializer& os) const override + { + SerializeDispatch(this->get(), os); + } + }; + + cmSbomObject() { ::new (Storage()) Instance(nullptr); } + cmSbomObject(std::nullptr_t) + : cmSbomObject() + { + } + + template < + typename T, typename Decayed = cm::remove_cv_t>, + typename = cm::enable_if_t::value>> + cmSbomObject(T&& x) + { + ::new (Storage()) Instance(std::forward(x)); + } + + cmSbomObject(cmSbomObject const& other) + { + other.Interface().Copy(Storage()); + } + cmSbomObject(cmSbomObject&& other) noexcept + { + other.Interface().Move(Storage()); + } + + ~cmSbomObject() noexcept { Interface().~ObjectInterface(); } + + cmSbomObject& operator=(cmSbomObject rhs) + { + Interface().~ObjectInterface(); + rhs.Interface().Move(Storage()); + return *this; + } + + bool IsNull() const noexcept { return Interface().Addr() == nullptr; } + explicit operator bool() const noexcept { return !IsNull(); } + + void Serialize(cmSbomSerializer& os) const { Interface().SerializeImpl(os); } + + template + T& CastUnchecked() + { + return *static_cast(Interface().Addr()); + } + + template + T const& CastUnchecked() const + { + return *static_cast(Interface().Addr()); + } + + ObjectInterface& Interface() + { + return *static_cast(Storage()); + } + ObjectInterface const& Interface() const + { + return *static_cast(Storage()); + } + + void* Storage() { return &Data.Data; } + void const* Storage() const { return &Data.Data; } + + template + U* ptr() noexcept + { + return std::addressof(this->template CastUnchecked()); + } + + template + U const* ptr() const noexcept + { + return std::addressof(this->template CastUnchecked()); + } + +private: + ObjectStorage::Buffer Data{}; +}; + +template > +U* insert_back(std::vector& vec, T&& obj) noexcept +{ + vec.emplace_back(std::forward(obj)); + return std::addressof(vec.back().CastUnchecked()); +} diff --git a/Source/cmSbomSerializer.h b/Source/cmSbomSerializer.h new file mode 100644 index 0000000000..019a1c76d0 --- /dev/null +++ b/Source/cmSbomSerializer.h @@ -0,0 +1,38 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#pragma once + +#include +#include + +#include + +class cmSbomObject; +class cmSbomSerializer +{ +public: + cmSbomSerializer() = default; + cmSbomSerializer(cmSbomSerializer const&) = default; + cmSbomSerializer(cmSbomSerializer&&) = default; + cmSbomSerializer& operator=(cmSbomSerializer const&) = default; + cmSbomSerializer& operator=(cmSbomSerializer&&) = default; + + virtual void BeginObject() {} + virtual void EndObject() {} + virtual void BeginArray() {} + virtual void EndArray() {} + + virtual void AddReference(std::string const& id) = 0; + + virtual void AddString(std::string const& key, std::string const& value) = 0; + virtual void AddVisitable(std::string const& key, + cmSbomObject const& visitable) = 0; + + virtual void AddVectorIfPresent(std::string const& key, + std::vector const& vec) = 0; + virtual void AddVectorIfPresent(std::string const& key, + std::vector const& vec) = 0; + + virtual bool WriteSbom(std::ostream& os, cmSbomObject const& document) = 0; + virtual ~cmSbomSerializer() = default; +}; diff --git a/Source/cmSpdx.cxx b/Source/cmSpdx.cxx new file mode 100644 index 0000000000..6bd37ce3b8 --- /dev/null +++ b/Source/cmSpdx.cxx @@ -0,0 +1,520 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#include "cmSpdx.h" + +#include +#include + +#include "cmSbomSerializer.h" + +inline void SerializeIfPresent(cmSbomSerializer& s, std::string const& key, + cm::optional const& v) +{ + if (v) { + s.AddString(key, *v); + } +} + +std::string to_string(cmSpdxIntegrityMethod::HashAlgorithmId id) +{ + switch (id) { + case cmSpdxIntegrityMethod::HashAlgorithmId::ADLER32: + return "ADLER32"; + case cmSpdxIntegrityMethod::HashAlgorithmId::BLAKE2B256: + return "BLAKE2B256"; + case cmSpdxIntegrityMethod::HashAlgorithmId::BLAKE2B384: + return "BLAKE2B384"; + case cmSpdxIntegrityMethod::HashAlgorithmId::BLAKE2B512: + return "BLAKE2B512"; + case cmSpdxIntegrityMethod::HashAlgorithmId::BLAKE3: + return "BLAKE3"; + case cmSpdxIntegrityMethod::HashAlgorithmId::MD2: + return "MD2"; + case cmSpdxIntegrityMethod::HashAlgorithmId::MD4: + return "MD4"; + case cmSpdxIntegrityMethod::HashAlgorithmId::MD5: + return "MD5"; + case cmSpdxIntegrityMethod::HashAlgorithmId::MD6: + return "MD6"; + case cmSpdxIntegrityMethod::HashAlgorithmId::SHA1: + return "SHA1"; + case cmSpdxIntegrityMethod::HashAlgorithmId::SHA224: + return "SHA224"; + case cmSpdxIntegrityMethod::HashAlgorithmId::SHA256: + return "SHA256"; + case cmSpdxIntegrityMethod::HashAlgorithmId::SHA384: + return "SHA384"; + case cmSpdxIntegrityMethod::HashAlgorithmId::SHA512: + return "SHA512"; + case cmSpdxIntegrityMethod::HashAlgorithmId::SHA3_256: + return "SHA3_256"; + case cmSpdxIntegrityMethod::HashAlgorithmId::SHA3_384: + return "SHA3_384"; + case cmSpdxIntegrityMethod::HashAlgorithmId::SHA3_512: + return "SHA3_512"; + } + throw std::invalid_argument("Unknown HashAlgorithmId"); +} + +std::string to_string(cmSpdxSoftwareArtifact::PurposeId id) +{ + switch (id) { + case cmSpdxSoftwareArtifact::PurposeId::APPLICATION: + return "APPLICATION"; + case cmSpdxSoftwareArtifact::PurposeId::ARCHIVE: + return "ARCHIVE"; + case cmSpdxSoftwareArtifact::PurposeId::CONTAINER: + return "CONTAINER"; + case cmSpdxSoftwareArtifact::PurposeId::DATA: + return "DATA"; + case cmSpdxSoftwareArtifact::PurposeId::DEVICE: + return "DEVICE"; + case cmSpdxSoftwareArtifact::PurposeId::FIRMWARE: + return "FIRMWARE"; + case cmSpdxSoftwareArtifact::PurposeId::FILE: + return "FILE"; + case cmSpdxSoftwareArtifact::PurposeId::INSTALL: + return "INSTALL"; + case cmSpdxSoftwareArtifact::PurposeId::LIBRARY: + return "LIBRARY"; + case cmSpdxSoftwareArtifact::PurposeId::MODULE: + return "MODULE"; + case cmSpdxSoftwareArtifact::PurposeId::OPERATING_SYSTEM: + return "OPERATING_SYSTEM"; + case cmSpdxSoftwareArtifact::PurposeId::SOURCE: + return "SOURCE"; + } + throw std::invalid_argument("Unknown PurposeId"); +} + +std::string to_string(cmSpdxSbom::TypeId id) +{ + switch (id) { + case cmSpdxSbom::TypeId::ANALYZED: + return "ANALYZED"; + case cmSpdxSbom::TypeId::BUILD: + return "BUILD"; + case cmSpdxSbom::TypeId::DEPLOYED: + return "DEPLOYED"; + case cmSpdxSbom::TypeId::DESIGN: + return "DESIGN"; + case cmSpdxSbom::TypeId::RUNTIME: + return "RUNTIME"; + case cmSpdxSbom::TypeId::SOURCE: + return "SOURCE"; + case cmSpdxSbom::TypeId::TEST: + return "TEST"; + } + throw std::invalid_argument("Unknown Sbom::TypeId"); +} + +std::string to_string(cmSpdxFile::FileKindId id) +{ + switch (id) { + case cmSpdxFile::FileKindId::DIRECTORY: + return "DIRECTORY"; + case cmSpdxFile::FileKindId::FILE: + return "FILE"; + } + throw std::invalid_argument("Unknown File::FileKindId"); +} + +std::string to_string(cmSpdxRelationship::RelationshipTypeId id) +{ + switch (id) { + case cmSpdxRelationship::RelationshipTypeId::DESCRIBES: + return "DESCRIBES"; + case cmSpdxRelationship::RelationshipTypeId::CONTAINS: + return "CONTAINS"; + case cmSpdxRelationship::RelationshipTypeId::DEPENDS_ON: + return "DEPENDS_ON"; + case cmSpdxRelationship::RelationshipTypeId::OTHER: + return "OTHER"; + } + throw std::invalid_argument("Unknown RelationshipTypeId"); +} + +std::string to_string(cmSpdxLifecycleScopedRelationship::ScopeId id) +{ + switch (id) { + case cmSpdxLifecycleScopedRelationship::ScopeId::BUILD: + return "BUILD"; + case cmSpdxLifecycleScopedRelationship::ScopeId::DESIGN: + return "DESIGN"; + case cmSpdxLifecycleScopedRelationship::ScopeId::RUNTIME: + return "RUNTIME"; + case cmSpdxLifecycleScopedRelationship::ScopeId::TEST: + return "TEST"; + } + throw std::invalid_argument("Unknown Lifecycle ScopeId"); +} + +std::string to_string(cmSpdxAnnotation::AnnotationTypeId id) +{ + switch (id) { + case cmSpdxAnnotation::AnnotationTypeId::REVIEW: + return "REVIEW"; + case cmSpdxAnnotation::AnnotationTypeId::OTHER: + return "OTHER"; + } + throw std::invalid_argument("Unknown AnnotationTypeId"); +} + +std::string to_string(cmSpdxArtifact::SupportTypeId id) +{ + switch (id) { + case cmSpdxArtifact::SupportTypeId::COMMUNITY: + return "COMMUNITY"; + case cmSpdxArtifact::SupportTypeId::COMMERCIAL: + return "COMMERCIAL"; + case cmSpdxArtifact::SupportTypeId::NONE: + return "NONE"; + } + throw std::invalid_argument("Unknown SupportTypeId"); +} + +void cmSpdxExternalIdentifier::Serialize(cmSbomSerializer& serializer) const +{ + serializer.AddString("type", "ExternalIdentifier"); + SerializeIfPresent(serializer, "externalIdentifierType", + ExternalIdentifierType); + SerializeIfPresent(serializer, "identifier", Identifier); + SerializeIfPresent(serializer, "comment", Comment); + SerializeIfPresent(serializer, "identifierLocation", IdentifierLocation); + SerializeIfPresent(serializer, "issuingAuthority", IssuingAuthority); +} + +void cmSpdxExternalRef::Serialize(cmSbomSerializer& serializer) const +{ + serializer.AddString("type", "ExternalRef"); + SerializeIfPresent(serializer, "externalRefType", ExternalRefType); + SerializeIfPresent(serializer, "locator", Locator); + SerializeIfPresent(serializer, "contentType", ContentType); + SerializeIfPresent(serializer, "comment", Comment); +} + +void cmSpdxChecksum::Serialize(cmSbomSerializer& serializer) const +{ + serializer.AddString("type", "Checksum"); + serializer.AddString("algorithm", to_string(Algorithm)); + serializer.AddString("checksumValue", ChecksumValue); +} + +void cmSpdxCreationInfo::Serialize(cmSbomSerializer& serializer) const +{ + serializer.AddString("type", "CreationInfo"); + SerializeIfPresent(serializer, "@id", SpdxId); + if (SpecVersion) { + serializer.AddString("specVersion", *SpecVersion); + } + SerializeIfPresent(serializer, "comment", Comment); + SerializeIfPresent(serializer, "created", Created); + if (!CreatedBy.empty()) { + serializer.AddVectorIfPresent("createdBy", CreatedBy); + } + if (!CreatedUsing.empty()) { + serializer.AddVectorIfPresent("createdUsing", CreatedUsing); + } +} + +void cmSpdxIntegrityMethod::Serialize(cmSbomSerializer& serializer) const +{ + serializer.AddString("type", "IntegrityMethod"); + SerializeIfPresent(serializer, "comment", Comment); +} + +void cmSpdxElement::Serialize(cmSbomSerializer& serializer) const +{ + serializer.AddString("type", "Element"); + SerializeIfPresent(serializer, "@id", SpdxId); + SerializeIfPresent(serializer, "name", Name); + SerializeIfPresent(serializer, "summary", Summary); + SerializeIfPresent(serializer, "description", Description); + SerializeIfPresent(serializer, "comment", Comment); + if (CreationInfo) { + serializer.AddVisitable("creationInfo", *CreationInfo); + } + if (VerifiedUsing) { + serializer.AddVisitable("verifiedUsing", *VerifiedUsing); + } + if (!ExternalRef.empty()) { + serializer.AddVectorIfPresent("externalRef", ExternalRef); + } + if (!ExternalIdentifier.empty()) { + serializer.AddVectorIfPresent("externalIdentifier", ExternalIdentifier); + } + if (Extension) { + serializer.AddVisitable("extension", *Extension); + } +} + +void cmSpdxTool::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxElement::Serialize(serializer); + serializer.AddString("type", "Tool"); +} + +void cmSpdxAgent::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxElement::Serialize(serializer); + serializer.AddString("type", "Agent"); +} + +void cmSpdxOrganization::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxAgent::Serialize(serializer); + serializer.AddString("type", "Organization"); +} + +void cmSpdxPerson::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxAgent::Serialize(serializer); + serializer.AddString("type", "Person"); +} + +void cmSpdxSoftwareAgent::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxAgent::Serialize(serializer); + serializer.AddString("type", "SoftwareAgent"); +} + +void cmSpdxPositiveIntegerRange::Serialize(cmSbomSerializer& serializer) const +{ + serializer.AddString("type", "PositiveIntegerRange"); + SerializeIfPresent(serializer, "beginIntegerRange", BeginIntegerRange); + SerializeIfPresent(serializer, "endIntegerRange", EndIntegerRange); +} + +void cmSpdxRelationship::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxElement::Serialize(serializer); + serializer.AddString("type", "Relationship"); + if (From) { + serializer.AddVisitable("from", *From); + } + if (!To.empty()) { + serializer.AddVectorIfPresent("to", To); + } + if (RelationshipType) { + serializer.AddString("relationshipType", to_string(*RelationshipType)); + } + SerializeIfPresent(serializer, "startTime", StartTime); + SerializeIfPresent(serializer, "endTime", EndTime); +} + +void cmSpdxLifecycleScopedRelationship::Serialize( + cmSbomSerializer& serializer) const +{ + cmSpdxRelationship::Serialize(serializer); + serializer.AddString("type", "LifecycleScopedRelationship"); + if (Scope) { + serializer.AddString("scope", to_string(*Scope)); + } +} + +void cmSpdxArtifact::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxElement::Serialize(serializer); + serializer.AddString("type", "Artifact"); + if (!OriginatedBy.empty()) { + serializer.AddVectorIfPresent("originatedBy", OriginatedBy); + } + if (SuppliedBy) { + serializer.AddVisitable("suppliedBy", *SuppliedBy); + } + SerializeIfPresent(serializer, "builtTime", BuiltTime); + SerializeIfPresent(serializer, "releaseTime", ReleaseTime); + SerializeIfPresent(serializer, "validUntilTime", ValidUntilTime); + SerializeIfPresent(serializer, "standardName", StandardName); + if (Support) { + serializer.AddString("support", to_string(*Support)); + } +} + +void cmSpdxIndividualElement::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxElement::Serialize(serializer); + serializer.AddString("type", "IndividualElement"); +} + +void cmSpdxAnnotation::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxElement::Serialize(serializer); + serializer.AddString("type", "Annotation"); + if (AnnotationType) { + serializer.AddString("annotationType", to_string(*AnnotationType)); + } + SerializeIfPresent(serializer, "contentType", ContentType); + SerializeIfPresent(serializer, "statement", Statement); + if (Element) { + serializer.AddVisitable("element", *Element); + } +} + +void cmSpdxExternalMap::Serialize(cmSbomSerializer& serializer) const +{ + serializer.AddString("type", "ExternalMap"); + SerializeIfPresent(serializer, "externalSpdxId", ExternalSpdxId); + if (VerifiedUsing) { + serializer.AddVisitable("verifiedUsing", *VerifiedUsing); + } + SerializeIfPresent(serializer, "locationHistory", LocationHistory); + if (DefiningArtifact) { + serializer.AddVisitable("definingArtifact", *DefiningArtifact); + } +} + +void cmSpdxNamespaceMap::Serialize(cmSbomSerializer& serializer) const +{ + serializer.AddString("type", "NamespaceMap"); + SerializeIfPresent(serializer, "prefix", Prefix); + SerializeIfPresent(serializer, "namespace", Namespace); +} + +void cmSpdxElementCollection::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxElement::Serialize(serializer); + serializer.AddString("type", "ElementCollection"); + if (!Elements.empty()) { + serializer.AddVectorIfPresent("element", Elements); + } + if (!RootElements.empty()) { + serializer.AddVectorIfPresent("rootElement", RootElements); + } + if (!ProfileConformance.empty()) { + serializer.AddVectorIfPresent("profileConformance", ProfileConformance); + } +} + +void cmSpdxPackageVerificationCode::Serialize( + cmSbomSerializer& serializer) const +{ + serializer.AddString("type", "PackageVerificationCode"); + if (Algorithm) { + serializer.AddString("algorithm", to_string(*Algorithm)); + } + SerializeIfPresent(serializer, "hashValue", HashValue); + SerializeIfPresent(serializer, "packageVerificationCodeExcludedFile", + PackageVerificationCodeExcludedFile); +} + +void cmSpdxHash::Serialize(cmSbomSerializer& serializer) const +{ + serializer.AddString("type", "Hash"); + serializer.AddString("hashAlgorithm", to_string(HashAlgorithm)); + serializer.AddString("hashValue", HashValue); +} + +void cmSpdxBundle::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxElementCollection::Serialize(serializer); + serializer.AddString("type", "Bundle"); + SerializeIfPresent(serializer, "context", Context); +} + +void cmSpdxBom::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxBundle::Serialize(serializer); + serializer.AddString("type", "Bom"); +} + +void cmSpdxSbom::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxBom::Serialize(serializer); + serializer.AddString("type", "software_Sbom"); + if (Types) { + for (auto const& t : *Types) { + serializer.AddString("sbomType", to_string(t)); + } + } + if (LifecycleScope) { + serializer.AddString("lifecycleScope", to_string(*LifecycleScope)); + } +} + +void cmSpdxSoftwareArtifact::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxArtifact::Serialize(serializer); + serializer.AddString("type", "software_SoftwareArtifact"); + if (PrimaryPurpose) { + serializer.AddString("primaryPurpose", to_string(*PrimaryPurpose)); + } + if (AdditionalPurpose) { + for (auto const& p : *AdditionalPurpose) { + serializer.AddString("additionalPurpose", to_string(p)); + } + } + SerializeIfPresent(serializer, "copyrightText", CopyrightText); + SerializeIfPresent(serializer, "attributionText", AttributionText); + if (ContentIdentifier) { + serializer.AddVisitable("contentIdentifier", *ContentIdentifier); + } + SerializeIfPresent(serializer, "artifactSize", ArtifactSize); +} + +void cmSpdxPackage::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxSoftwareArtifact::Serialize(serializer); + serializer.AddString("type", "software_Package"); + SerializeIfPresent(serializer, "downloadLocation", DownloadLocation); + SerializeIfPresent(serializer, "homePage", Homepage); + SerializeIfPresent(serializer, "packageVersion", PackageVersion); + SerializeIfPresent(serializer, "packageUrl", PackageUrl); + SerializeIfPresent(serializer, "sourceInfo", SourceInfo); +} + +void cmSpdxFile::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxArtifact::Serialize(serializer); + serializer.AddString("type", "software_File"); + if (ContentType) { + serializer.AddString("contentType", *ContentType); + } + if (FileType) { + serializer.AddString("fileType", to_string(*FileType)); + } +} + +void cmSpdxContentIdentifier::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxIntegrityMethod::Serialize(serializer); + serializer.AddString("type", "software_ContentIdentifier"); + SerializeIfPresent(serializer, "contentIdentifierType", + ContentIdentifierType); + SerializeIfPresent(serializer, "contentValue", ContentValue); +} + +void cmSpdxSnippet::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxSoftwareArtifact::Serialize(serializer); + serializer.AddString("type", "software_Snippet"); + SerializeIfPresent(serializer, "byteRange", ByteRange); + SerializeIfPresent(serializer, "lineRange", LineRange); + if (SnippetFromFile) { + serializer.AddVisitable("snippetFromFile", *SnippetFromFile); + } +} + +void cmSpdxDocument::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxElementCollection::Serialize(serializer); + + serializer.AddString("type", "SpdxDocument"); + if (ExternalMap) { + serializer.AddVisitable("externalMap", *ExternalMap); + } + if (NamespaceMap) { + serializer.AddVisitable("namespaceMap", *NamespaceMap); + } + SerializeIfPresent(serializer, "dataLicense", DataLicense); +} + +void cmSbomDocument::Serialize(cmSbomSerializer& serializer) const +{ + serializer.AddString( + "@context", + Context.value_or("https://spdx.org/rdf/3.0.1/spdx-context.jsonld")); + if (!Graph.empty()) { + serializer.AddVectorIfPresent("@graph", Graph); + } +} diff --git a/Source/cmSpdx.h b/Source/cmSpdx.h new file mode 100644 index 0000000000..9b37828b32 --- /dev/null +++ b/Source/cmSpdx.h @@ -0,0 +1,390 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#pragma once +#include +#include + +#include + +#include "cmSbomObject.h" + +class cmSbomSerializer; + +using Datetime = std::string; +using MediaType = std::string; +using SemVer = std::string; + +struct cmSpdxExternalIdentifier +{ + cm::optional SpdxId; + cm::optional ExternalIdentifierType; + cm::optional Identifier; + cm::optional Comment; + cm::optional IdentifierLocation; + cm::optional IssuingAuthority; + + void Serialize(cmSbomSerializer&) const; +}; + +struct cmSpdxExternalRef +{ + cm::optional SpdxId; + cm::optional ExternalRefType; + cm::optional Locator; + cm::optional ContentType; + cm::optional Comment; + + void Serialize(cmSbomSerializer&) const; +}; + +struct cmSpdxCreationInfo +{ + cm::optional SpdxId; + cm::optional SpecVersion; + cm::optional Comment; + cm::optional Created; + std::vector CreatedBy; + std::vector CreatedUsing; + + void Serialize(cmSbomSerializer&) const; +}; + +struct cmSpdxIntegrityMethod +{ + cm::optional SpdxId; + cm::optional Comment; + + enum HashAlgorithmId + { + ADLER32, + BLAKE2B256, + BLAKE2B384, + BLAKE2B512, + BLAKE3, + MD2, + MD4, + MD5, + MD6, + SHA1, + SHA224, + SHA256, + SHA384, + SHA512, + SHA3_256, + SHA3_384, + SHA3_512, + }; + + cmSpdxIntegrityMethod() = default; + cmSpdxIntegrityMethod(cmSpdxIntegrityMethod const&) = default; + cmSpdxIntegrityMethod(cmSpdxIntegrityMethod&&) = default; + cmSpdxIntegrityMethod& operator=(cmSpdxIntegrityMethod const&) = default; + cmSpdxIntegrityMethod& operator=(cmSpdxIntegrityMethod&&) = default; + + virtual void Serialize(cmSbomSerializer&) const; + virtual ~cmSpdxIntegrityMethod() = default; +}; + +struct cmSpdxChecksum +{ + cm::optional SpdxId; + cmSpdxIntegrityMethod::HashAlgorithmId Algorithm; + std::string ChecksumValue; + + void Serialize(cmSbomSerializer&) const; +}; + +struct cmSpdxElement +{ + cm::optional SpdxId; + cm::optional Name; + cm::optional Summary; + cm::optional Description; + cm::optional Comment; + cm::optional CreationInfo; + cm::optional VerifiedUsing; + std::vector ExternalRef; + std::vector ExternalIdentifier; + cm::optional Extension; + + cmSpdxElement() = default; + cmSpdxElement(cmSpdxElement const&) = default; + cmSpdxElement(cmSpdxElement&&) = default; + cmSpdxElement& operator=(cmSpdxElement const&) = default; + cmSpdxElement& operator=(cmSpdxElement&&) = default; + + virtual ~cmSpdxElement() = default; + virtual void Serialize(cmSbomSerializer&) const; +}; + +struct cmSpdxTool final : cmSpdxElement +{ + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxAgent : cmSpdxElement +{ + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxOrganization final : cmSpdxAgent +{ + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxPerson final : cmSpdxAgent +{ + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxSoftwareAgent final : cmSpdxAgent +{ + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxPositiveIntegerRange +{ + cm::optional SpdxId; + cm::optional BeginIntegerRange; + cm::optional EndIntegerRange; + + void Serialize(cmSbomSerializer&) const; +}; + +struct cmSpdxRelationship : cmSpdxElement +{ + enum RelationshipTypeId + { + DESCRIBES, + CONTAINS, + DEPENDS_ON, + OTHER + }; + + cm::optional From; + std::vector To; + cm::optional RelationshipType; + cm::optional StartTime; + cm::optional EndTime; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxLifecycleScopedRelationship final : cmSpdxRelationship +{ + enum ScopeId + { + BUILD, + DESIGN, + RUNTIME, + TEST + }; + + cm::optional Scope; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxArtifact : cmSpdxElement +{ + enum SupportTypeId + { + COMMUNITY, + COMMERCIAL, + NONE + }; + + std::vector OriginatedBy; + cm::optional SuppliedBy; + cm::optional BuiltTime; + cm::optional ReleaseTime; + cm::optional ValidUntilTime; + cm::optional StandardName; + cm::optional Support; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxIndividualElement final : cmSpdxElement +{ + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxAnnotation final : cmSpdxElement +{ + enum AnnotationTypeId + { + REVIEW, + OTHER + }; + + cm::optional AnnotationType; + cm::optional ContentType; + cm::optional Statement; + cm::optional Element; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxExternalMap +{ + cm::optional SpdxId; + cm::optional ExternalSpdxId; + cm::optional VerifiedUsing; + cm::optional LocationHistory; + cm::optional DefiningArtifact; + + void Serialize(cmSbomSerializer&) const; +}; + +struct cmSpdxNamespaceMap +{ + cm::optional SpdxId; + cm::optional Prefix; + cm::optional Namespace; + + void Serialize(cmSbomSerializer&) const; +}; + +struct cmSpdxElementCollection : cmSpdxElement +{ + std::vector Elements; + std::vector RootElements; + std::vector ProfileConformance; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxPackageVerificationCode final : cmSpdxIntegrityMethod +{ + cm::optional Algorithm; + cm::optional HashValue; + cm::optional PackageVerificationCodeExcludedFile; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxHash final : cmSpdxIntegrityMethod +{ + HashAlgorithmId HashAlgorithm; + std::string HashValue; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxBundle : cmSpdxElementCollection +{ + cm::optional Context; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxBom : cmSpdxBundle +{ + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxSbom final : cmSpdxBom +{ + enum TypeId + { + ANALYZED, + BUILD, + DEPLOYED, + DESIGN, + RUNTIME, + SOURCE, + TEST + }; + + cm::optional> Types; + cm::optional LifecycleScope; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxSoftwareArtifact : cmSpdxArtifact +{ + enum PurposeId + { + APPLICATION, + ARCHIVE, + CONTAINER, + DATA, + DEVICE, + FIRMWARE, + FILE, + INSTALL, + LIBRARY, + MODULE, + OPERATING_SYSTEM, + SOURCE + }; + + cm::optional PrimaryPurpose; + cm::optional> AdditionalPurpose; + cm::optional CopyrightText; + cm::optional AttributionText; + cm::optional ContentIdentifier; + cm::optional ArtifactSize; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxPackage final : cmSpdxSoftwareArtifact +{ + cm::optional DownloadLocation; + cm::optional Homepage; + cm::optional PackageVersion; + cm::optional PackageUrl; + cm::optional SourceInfo; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxDocument final : cmSpdxElementCollection +{ + cm::optional ExternalMap; + cm::optional NamespaceMap; + std::string DataLicense; + + void Serialize(cmSbomSerializer& serializer) const override; +}; + +struct cmSpdxContentIdentifier final : cmSpdxIntegrityMethod +{ + cm::optional ContentIdentifierType; + cm::optional ContentValue; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxFile final : cmSpdxArtifact +{ + enum FileKindId + { + DIRECTORY, + FILE + }; + cm::optional ContentType; + cm::optional FileType; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxSnippet final : cmSpdxSoftwareArtifact +{ + cm::optional ByteRange; + cm::optional LineRange; + cm::optional SnippetFromFile; + + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSbomDocument +{ + cm::optional Context; + std::vector Graph; + + void Serialize(cmSbomSerializer&) const; +}; diff --git a/Source/cmSpdxSerializer.cxx b/Source/cmSpdxSerializer.cxx new file mode 100644 index 0000000000..47c22fdb10 --- /dev/null +++ b/Source/cmSpdxSerializer.cxx @@ -0,0 +1,119 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#include "cmSpdxSerializer.h" + +#include + +#include + +#include "cmSbomObject.h" + +cmSpdxSerializer::cmSpdxSerializer() +{ + Json::StreamWriterBuilder builder = Json::StreamWriterBuilder(); + builder["indentation"] = " "; + Writer.reset(builder.newStreamWriter()); +} + +void cmSpdxSerializer::BeginObject() +{ + CurrentValue = Json::objectValue; +} + +void cmSpdxSerializer::BeginArray() +{ + CurrentValue = Json::arrayValue; +} + +void cmSpdxSerializer::EndObject() +{ +} + +void cmSpdxSerializer::EndArray() +{ +} + +void cmSpdxSerializer::AddReference(std::string const& id) +{ + CurrentValue = id; +} + +void cmSpdxSerializer::AddString(std::string const& key, + std::string const& value) +{ + if (!value.empty()) { + CurrentValue[key] = value; + } +} + +void cmSpdxSerializer::AddVisitable(std::string const& key, + cmSbomObject const& visitable) +{ + if (visitable.IsNull()) { + return; + } + + Json::Value parentValue = std::move(CurrentValue); + visitable.Serialize(*this); + Json::Value childValue = std::move(CurrentValue); + + CurrentValue = std::move(parentValue); + CurrentValue[key] = std::move(childValue); +} + +void cmSpdxSerializer::AddVectorIfPresent(std::string const& key, + std::vector const& vec) +{ + if (vec.empty()) { + return; + } + Json::Value parentValue = std::move(CurrentValue); + Json::Value childValue(Json::arrayValue); + + for (auto const& item : vec) { + if (item.IsNull()) { + continue; + } + + item.Serialize(*this); + + if (!CurrentValue.isNull()) { + childValue.append(std::move(CurrentValue)); + } + } + + CurrentValue = std::move(parentValue); + CurrentValue[key] = std::move(childValue); +} + +void cmSpdxSerializer::AddVectorIfPresent(std::string const& key, + std::vector const& vec) +{ + if (vec.empty()) { + return; + } + Json::Value parentValue = std::move(CurrentValue); + Json::Value childValue(Json::arrayValue); + + for (auto const& item : vec) { + if (item.empty()) { + continue; + } + childValue.append(item); + } + + CurrentValue = std::move(parentValue); + CurrentValue[key] = std::move(childValue); +} + +bool cmSpdxSerializer::WriteSbom(std::ostream& os, + cmSbomObject const& document) +{ + if (document.IsNull()) { + return false; + } + + document.Serialize(*this); + Writer->write(CurrentValue, &os); + return os.good(); +} diff --git a/Source/cmSpdxSerializer.h b/Source/cmSpdxSerializer.h new file mode 100644 index 0000000000..50ece9adcc --- /dev/null +++ b/Source/cmSpdxSerializer.h @@ -0,0 +1,52 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include "cmSbomSerializer.h" + +class cmSbomObject; + +struct cmSpdxSerializer final : cmSbomSerializer +{ + cmSpdxSerializer(); + + ~cmSpdxSerializer() override = default; + + void BeginObject() override; + + void BeginArray() override; + + void EndObject() override; + + void EndArray() override; + + void AddReference(std::string const& id) override; + + void AddString(std::string const& key, std::string const& value) override; + + void AddVisitable(std::string const& key, + cmSbomObject const& visitable) override; + + void AddVectorIfPresent(std::string const& key, + std::vector const& vec) override; + + void AddVectorIfPresent(std::string const& key, + std::vector const& vec) override; + + bool WriteSbom(std::ostream& os, cmSbomObject const& document) override; + + Json::Value GetJson() { return CurrentValue; } + +private: + Json::Value CurrentValue; + std::string CurrentKey; + std::unique_ptr Writer; +}; diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index a50936e7c5..dee4731914 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -25,7 +25,7 @@ set(CMakeLib_TESTS testRange.cxx testOptional.cxx testPathResolver.cxx - testSPDXSerializer.cxx + testSpdxSerializer.cxx testStdIo.cxx testString.cxx testStringAlgorithms.cxx diff --git a/Tests/CMakeLib/testSPDXSerializer.cxx b/Tests/CMakeLib/testSPDXSerializer.cxx deleted file mode 100644 index b8ab923b7b..0000000000 --- a/Tests/CMakeLib/testSPDXSerializer.cxx +++ /dev/null @@ -1,649 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file LICENSE.rst or https://cmake.org/licensing for details. */ -#include -#include -#include - -#include -#include - -#include -#include - -#include "cmSPDXSerializer.h" - -namespace { - -std::string const nonOptional(R"================({ - "@context": "https://spdx.org/rdf/3.0.1/spdx-context.jsonld", - "@graph": [ - { - "@id": "_:contentIdentifier_0", - "contentIdentifierType": "INVALID_CONTENT_IDENTIFIER_TYPE_ID", - "contentIdentifierValue": "", - "type": "ContentIdentifier" - }, - { - "@id": "_:creationInfo_0", - "created": "", - "createdBy": [], - "type": "CreationInfo" - }, - { - "@id": "_:creationInfo_1", - "created": "", - "createdBy": [], - "type": "CreationInfo" - }, - { - "@id": "_:dictionaryEntry_0", - "key": "", - "type": "DictionaryEntry" - }, - { - "@id": "_:externalIdentifier_0", - "externalIdentifierType": "INVALID_EXTERNAL_IDENTIFIER_TYPE_ID", - "identifier": "", - "type": "ExternalIdentifier" - }, - { - "@id": "_:externalMap_0", - "externalSpdxId": "", - "type": "ExternalMap" - }, - { - "@id": "_:externalRef_0", - "type": "ExternalRef" - }, - { - "@id": "_:hash_0", - "algorithm": "INVALID_HASH_TYPE_ID", - "hashValue": "", - "type": "Hash" - }, - { - "@id": "_:namespaceMap_0", - "namespace": "", - "prefix": "", - "type": "NamespaceMap" - }, - { - "@id": "_:packageVerificationCode_0", - "algorithm": "INVALID_HASH_TYPE_ID", - "hashValue": "", - "type": "PackageVerificationCode" - }, - { - "@id": "_:positiveIntegerRange_0", - "beginIntegerRange": 0, - "endIntegerRange": 0, - "type": "PositiveIntegerRange" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd0", - "type": "Agent" - }, - { - "annotationType": "INVALID_ANNOTATION_TYPE_ID", - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd1", - "subject": "", - "type": "Annotation" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd10", - "type": "SpdxDocument" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd11", - "type": "Tool" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd12", - "type": "File" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd13", - "type": "Package" - }, - { - "context": "", - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd14", - "type": "Sbom" - }, - { - "creationInfo": "_:creationInfo_0", - "snippetFromFile": "", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd15", - "type": "Snippet" - }, - { - "creationInfo": "_:creationInfo_0", - "licenseExpression": "", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd16", - "type": "LicenseExpression" - }, - { - "creationInfo": "_:creationInfo_0", - "licenseText": "", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd17", - "type": "SimpleLicensingText" - }, - { - "context": "", - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd2", - "type": "Bom" - }, - { - "context": "", - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd3", - "type": "Bundle" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd4", - "type": "IndividualElement" - }, - { - "creationInfo": "_:creationInfo_0", - "from": "", - "relationshipType": "INVALID_RELATIONSHIP_TYPE_ID", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd5", - "to": [], - "type": "LifecycleScopedRelationship" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd6", - "type": "Organization" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd7", - "type": "Person" - }, - { - "creationInfo": "_:creationInfo_0", - "from": "", - "relationshipType": "INVALID_RELATIONSHIP_TYPE_ID", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd8", - "to": [], - "type": "Relationship" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd9", - "type": "SoftwareAgent" - } - ] -})================"); - -std::string const Optional(R"================({ - "@context": "https://spdx.org/rdf/3.0.1/spdx-context.jsonld", - "@graph": [ - { - "@id": "_:contentIdentifier_0", - "contentIdentifierType": "gitoid", - "contentIdentifierValue": "ContentIdentifierValue", - "type": "ContentIdentifier" - }, - { - "@id": "_:creationInfo_0", - "created": "", - "createdBy": [], - "type": "CreationInfo" - }, - { - "@id": "_:creationInfo_1", - "Comment": "Comment", - "created": "Created", - "createdBy": [ - "testRef" - ], - "createdUsing": [ - "testRef" - ], - "type": "CreationInfo" - }, - { - "@id": "_:dictionaryEntry_0", - "key": "Key", - "type": "DictionaryEntry", - "value": "Value" - }, - { - "@id": "_:externalIdentifier_0", - "comment": "Comment", - "externalIdentifierType": "other", - "identifier": "Identifier", - "identifierLocator": [ - "IdentifierLocator" - ], - "issuingAuthority": "IssuingAuthority", - "type": "ExternalIdentifier" - }, - { - "@id": "_:externalMap_0", - "definingArtifact": "testRef", - "externalSpdxId": "ExternalSpdxId", - "integrityMethod": [ - "testRef" - ], - "locationHint": "LocationHint", - "type": "ExternalMap" - }, - { - "@id": "_:externalRef_0", - "comment": "Comment", - "contentType": "ContentType", - "externalRefType": "other", - "locator": [ - "Locator" - ], - "type": "ExternalRef" - }, - { - "@id": "_:hash_0", - "algorithm": "other", - "hashValue": "HashValue", - "type": "Hash" - }, - { - "@id": "_:namespaceMap_0", - "namespace": "Namespace", - "prefix": "Namespace", - "type": "NamespaceMap" - }, - { - "@id": "_:packageVerificationCode_0", - "algorithm": "other", - "hashValue": "HashValue", - "type": "PackageVerificationCode" - }, - { - "@id": "_:positiveIntegerRange_0", - "beginIntegerRange": 1, - "endIntegerRange": 2, - "type": "PositiveIntegerRange" - }, - { - "comment": "Comment", - "creationInfo": "_:creationInfo_0", - "description": "Description", - "extension": [ - "testRef" - ], - "externalIdentifier": [ - "testRef" - ], - "externalRef": [ - "testRef" - ], - "name": "Name", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd0", - "summary": "Summary", - "type": "Agent", - "verifiedUsing": [ - "testRef" - ] - }, - { - "annotationType": "other", - "contentType": "ContentType", - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd1", - "statement": "Statement", - "subject": "testRef", - "type": "Annotation" - }, - { - "creationInfo": "_:creationInfo_0", - "dataLicense": "testRef", - "externalMap": "testRef", - "namespaceMap": "testRef", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd10", - "type": "SpdxDocument" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd11", - "type": "Tool" - }, - { - "additionalPurpose": [ - "other" - ], - "attributionText": "AttributionText", - "contentIdentifier": "testRef", - "contentType": "ContentType", - "copyrightText": "CopyrightText", - "creationInfo": "_:creationInfo_0", - "fileKind": "file", - "primaryPurpose": "file", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd12", - "type": "File" - }, - { - "creationInfo": "_:creationInfo_0", - "downloadLocation": "DownloadLocation", - "homePage": "HomePage", - "packageUrl": "PackageUrl", - "packageVersion": "PackageVersion", - "sourceInfo": "SourceInfo", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd13", - "type": "Package" - }, - { - "context": "", - "creationInfo": "_:creationInfo_0", - "sbomType": [ - "build" - ], - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd14", - "type": "Sbom" - }, - { - "byteRange": "testRef", - "creationInfo": "_:creationInfo_0", - "lineRange": "testRef", - "snippetFromFile": "testRef", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd15", - "type": "Snippet" - }, - { - "creationInfo": "_:creationInfo_0", - "customIdToUri": [ - "testRef" - ], - "licenseExpression": "LicenseExpression", - "licenseListVersion": "LicenseListVersion", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd16", - "type": "LicenseExpression" - }, - { - "creationInfo": "_:creationInfo_0", - "licenseText": "LicenseText", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd17", - "type": "SimpleLicensingText" - }, - { - "context": "Context", - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd2", - "type": "Bom" - }, - { - "context": "", - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd3", - "type": "Bundle" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd4", - "type": "IndividualElement" - }, - { - "completeness": "noAssertion", - "creationInfo": "_:creationInfo_0", - "endTime": "EndTime", - "from": "testRef", - "relationshipType": "other", - "scope": "other", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd5", - "startTime": "StartTime", - "to": [ - "testRef" - ], - "type": "LifecycleScopedRelationship" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd6", - "type": "Organization" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd7", - "type": "Person" - }, - { - "creationInfo": "_:creationInfo_0", - "from": "", - "relationshipType": "INVALID_RELATIONSHIP_TYPE_ID", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd8", - "to": [], - "type": "Relationship" - }, - { - "creationInfo": "_:creationInfo_0", - "spdxId": "https://cmake.org/testSPDXSerialization-gnrtd9", - "type": "SoftwareAgent" - } - ] -})================"); -} - -int testNonOptional() -{ - cmSPDXSimpleGraph graph("https://cmake.org/testSPDXSerialization-gnrtd"); - - // Core - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - - // Software - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - graph.insert(); - - // SimpleLicensing - graph.insert(); - graph.insert(); - - Json::Value root; - Json::Reader().parse(nonOptional.c_str(), root); - - std::cout << "NonOptional SPDX:"; - std::cout << "\nConstructed Graph: " << graph.toJsonLD().toStyledString(); - std::cout << "\nComparison Graph:" << root.toStyledString() << "\n"; - - // Convert to string to disregard differences in number signedness - return root.toStyledString() == graph.toJsonLD().toStyledString(); -}; - -int testOptional() -{ - cmSPDXSimpleGraph graph("https://cmake.org/testSPDXSerialization-gnrtd"); - - cmSPDXIdentifierReference ident("testRef"); - - // Core - auto& agent = graph.insert(); - agent.Comment = "Comment"; - agent.Description = "Description"; - agent.Extension.emplace().push_back(ident); - agent.ExternalIdentifier.emplace().push_back(ident); - agent.ExternalRef.emplace().push_back(ident); - agent.Name = "Name"; - agent.Summary = "Summary"; - agent.VerifiedUsing.emplace().push_back(ident); - - auto& annotation = graph.insert(); - annotation.AnnotationType = cmSPDXAnnotationType::OTHER; - annotation.ContentType = "ContentType"; - annotation.Statement = "Statement"; - annotation.Subject = ident; - - auto& bom = graph.insert(); - bom.Context = "Context"; - - graph.insert(); - - auto& creationInfo = graph.insert(); - creationInfo.Comment = "Comment"; - creationInfo.Created = "Created"; - creationInfo.CreatedBy.push_back(ident); - creationInfo.CreatedUsing.emplace().push_back(ident); - - auto& dictionaryEntry = graph.insert(); - dictionaryEntry.Key = "Key"; - dictionaryEntry.Value = "Value"; - - auto& externalIdentifier = graph.insert(); - externalIdentifier.Comment = "Comment"; - externalIdentifier.ExternalIdentifierType = - cmSPDXExternalIdentifierType::OTHER; - externalIdentifier.Identifier = "Identifier"; - externalIdentifier.IdentifierLocator.emplace().push_back( - "IdentifierLocator"); - externalIdentifier.IssuingAuthority = "IssuingAuthority"; - - auto& externalMap = graph.insert(); - externalMap.DefiningArtifact = ident; - externalMap.ExternalSpdxId = "ExternalSpdxId"; - externalMap.LocationHint = "LocationHint"; - externalMap.IntegrityMethod.emplace().push_back(ident); - - auto& externalRef = graph.insert(); - externalRef.Comment = "Comment"; - externalRef.ContentType = "ContentType"; - externalRef.ExternalRefType = cmSPDXExternalRefType::OTHER; - externalRef.Locator.emplace().push_back("Locator"); - - auto& hash = graph.insert(); - hash.Algorithm = cmSPDXHashAlgorithm::OTHER; - hash.HashValue = "HashValue"; - - graph.insert(); - - auto& lifecycleScopedRelationship = - graph.insert(); - lifecycleScopedRelationship.Completeness = - cmSPDXRelationshipCompletenessType::NO_ASSERTION; - lifecycleScopedRelationship.EndTime = "EndTime"; - lifecycleScopedRelationship.From = ident; - lifecycleScopedRelationship.RelationshipType = cmSPDXRelationshipType::OTHER; - lifecycleScopedRelationship.StartTime = "StartTime"; - lifecycleScopedRelationship.To.push_back(ident); - lifecycleScopedRelationship.Scope = cmSPDXLifecycleScopeType::OTHER; - - auto& namespaceMap = graph.insert(); - namespaceMap.Namespace = "Namespace"; - namespaceMap.Prefix = "Prefix"; - - graph.insert(); - - auto& packageVerificationCode = - graph.insert(); - packageVerificationCode.Algorithm = cmSPDXHashAlgorithm::OTHER; - packageVerificationCode.HashValue = "HashValue"; - packageVerificationCode.PackageVerificationCodeExcludedFile.emplace() - .push_back("PacakgeVerificationCodeExcludeFile"); - - graph.insert(); - - auto& positiveIntegerRange = graph.insert(); - positiveIntegerRange.BeginIntegerRange = 1; - positiveIntegerRange.EndIntegerRange = 2; - - graph.insert(); - - graph.insert(); - - auto& spdxDocument = graph.insert(); - spdxDocument.DataLicense = ident; - spdxDocument.ExternalMap = ident; - spdxDocument.NamespaceMap = ident; - - graph.insert(); - - // Software - auto& contentIdentifier = graph.insert(); - contentIdentifier.ContentIdentifierType = - cmSPDXContentIdentifierType::GITOID; - contentIdentifier.ContentIdentifierValue = "ContentIdentifierValue"; - - auto& file = graph.insert(); - file.AdditionalPurpose.emplace().push_back(cmSPDXSoftwarePurpose::OTHER); - file.AttributionText = "AttributionText"; - file.ContentIdentifier = ident; - file.CopyrightText = "CopyrightText"; - file.PrimaryPurpose = cmSPDXSoftwarePurpose::FILE; - file.ContentType = "ContentType"; - file.FileKind = cmSPDXFileKindType::FILE; - - auto& package = graph.insert(); - package.DownloadLocation = "DownloadLocation"; - package.HomePage = "HomePage"; - package.PackageUrl = "PackageUrl"; - package.PackageVersion = "PackageVersion"; - package.SourceInfo = "SourceInfo"; - - auto& sbom = graph.insert(); - sbom.SbomType.emplace().push_back(cmSPDXSbomType::BUILD); - - auto& snippet = graph.insert(); - snippet.ByteRange = ident; - snippet.LineRange = ident; - snippet.SnippetFromFile = ident; - - // SimpleLicensing - auto& licenseExpression = graph.insert(); - licenseExpression.CustomIdToUri.emplace().push_back(ident); - licenseExpression.LicenseExpression = "LicenseExpression"; - licenseExpression.LicenseListVersion = "LicenseListVersion"; - - auto& simpleLicensingText = graph.insert(); - simpleLicensingText.LicenseText = "LicenseText"; - - Json::Value root; - Json::Reader().parse(Optional.c_str(), root); - - std::cout << "Optional SPDX:"; - std::cout << "\nConstructed Graph: " << graph.toJsonLD().toStyledString(); - std::cout << "\nComparison Graph:" << root.toStyledString() << "\n"; - - // Convert to string to disregard differences in number signedness - return root.toStyledString() == graph.toJsonLD().toStyledString(); -}; - -int testSPDXSerializer(int /* argc */, char* /* argv */[]) -{ - if (!testNonOptional()) - return -1; - - if (!testOptional()) - return -1; - - return 0; -} diff --git a/Tests/CMakeLib/testSpdxSerializer.cxx b/Tests/CMakeLib/testSpdxSerializer.cxx new file mode 100644 index 0000000000..ab394cbc4b --- /dev/null +++ b/Tests/CMakeLib/testSpdxSerializer.cxx @@ -0,0 +1,84 @@ + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ + +#include +#include +#include + +#include + +#include + +#include "cmSbomObject.h" +#include "cmSpdx.h" +#include "cmSpdxSerializer.h" + +#include "testCommon.h" + +namespace { + +bool testSerializeSpdxJson() +{ + + auto constexpr contextUrl = "https://spdx.org/rdf/3.0.1/spdx-context.jsonld"; + + cmSbomDocument doc; + doc.Context = contextUrl; + + cmSpdxDocument spdxValue; + spdxValue.SpdxId = "_:SPDXRef-Document"; + spdxValue.DataLicense = "CC0-1.0"; + auto spdx = insert_back(doc.Graph, std::move(spdxValue)); + + { + cmSpdxCreationInfo ci; + ci.SpdxId = "_:SPDXRef-CreationInfo"; + ci.SpecVersion = "3.0.1"; + spdx->CreationInfo = std::move(ci); + } + + { + cmSpdxPackage pkg; + pkg.Name = "sample-package"; + pkg.SpdxId = "_:SPDXRef-Package"; + + spdx->RootElements.emplace_back(std::move(pkg)); + } + + { + cmSpdxSerializer serializer; + doc.Serialize(serializer); + auto value = serializer.GetJson(); + + ASSERT_TRUE(value.isObject()); + + Json::Value const& context = value["@context"]; + ASSERT_EQUAL(context.asString(), contextUrl); + + Json::Value const& graph = value["@graph"]; + ASSERT_TRUE(graph.isArray()); + + Json::Value const& docValue = graph[0]; + ASSERT_TRUE(docValue.isObject()); + ASSERT_EQUAL(docValue["type"].asString(), "SpdxDocument"); + ASSERT_EQUAL(docValue["@id"].asString(), "_:SPDXRef-Document"); + + auto const& creationInfo = docValue["creationInfo"]; + ASSERT_EQUAL(creationInfo["@id"].asString(), "_:SPDXRef-CreationInfo"); + ASSERT_EQUAL(creationInfo["type"].asString(), "CreationInfo"); + + auto const& package = docValue["rootElement"][0]; + ASSERT_EQUAL(package["type"].asString(), "software_Package"); + ASSERT_EQUAL(package["@id"].asString(), "_:SPDXRef-Package"); + } + + return true; +} + +} // namespace + +int testSpdxSerializer(int /*unused*/, char* /*unused*/[]) +{ + return runTests({ testSerializeSpdxJson }); +}