org.cyclonedx.BomGenerator11 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cyclonedx-core-java Show documentation
Show all versions of cyclonedx-core-java Show documentation
The CycloneDX core module provides a model representation of the BOM along with utilities to assist in creating, parsing, and validating BOMs.
/*
* This file is part of CycloneDX Core (Java).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
* Copyright (c) Steve Springett. All Rights Reserved.
*/
package org.cyclonedx;
import org.cyclonedx.model.Attribute;
import org.cyclonedx.model.Bom;
import org.cyclonedx.model.Commit;
import org.cyclonedx.model.Component;
import org.cyclonedx.model.ExternalReference;
import org.cyclonedx.model.IdentifiableActionType;
import org.cyclonedx.model.Pedigree;
import org.cyclonedx.model.ext.dependencyGraph.Dependency;
import org.cyclonedx.util.BomUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
/**
* BomGenerator creates a CycloneDX bill-of-material document from a set of
* {@link Component}s. Proper usage assumes {@link #generate()} is called after
* construction and optionally followed by {@link #toXmlString()}.
* @since 2.0.0
*/
public class BomGenerator11 extends AbstractBomGenerator implements BomGenerator {
private final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); // Quoted "Z" to indicate UTC, no timezone offset
private final Bom bom;
/**
* Constructs a new BomGenerator object.
* @param bom the BOM to generate
*/
BomGenerator11(final Bom bom) {
this.bom = bom;
}
/**
* Returns the version of the CycloneDX schema used by this instance
* @return a CycloneDxSchemaVersion enum
*/
public CycloneDxSchema.Version getSchemaVersion() {
return CycloneDxSchema.Version.VERSION_11;
}
/**
* Creates a CycloneDX BoM from a set of Components.
* @return an XML Document representing a CycloneDX BoM
* @since 2.0.0
*/
public Document generate() throws ParserConfigurationException {
final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
docFactory.setNamespaceAware(true);
final DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
this.doc = docBuilder.newDocument();
doc.setXmlStandalone(true);
final List attributes = new ArrayList<>();
attributes.add(new Attribute("xmlns", NS_BOM_11));
attributes.add(new Attribute("version", String.valueOf(bom.getVersion())));
if (bom.getDependencies() != null && bom.getDependencies().size() > 0) {
attributes.add(new Attribute("xmlns:dg", NS_DEPENDENCY_GRAPH_10));
}
// Create root node
final Element bomNode = createRootElement("bom", null, attributes.toArray(new Attribute[0]));
if (bom.getSerialNumber() != null) {
bomNode.setAttribute("serialNumber", bom.getSerialNumber());
}
final Element componentsNode = createElement(bomNode, "components");
createComponentsNode(componentsNode, bom.getComponents());
createExternalReferencesNode(bomNode, bom.getExternalReferences());
if (bom.getDependencies() != null && bom.getDependencies().size() > 0) {
final Element dependenciesNode = createElement(bomNode, "dg:dependencies");
createDependenciesNode(dependenciesNode, bom.getDependencies());
}
processExtensions(bomNode, bom);
return doc;
}
private void createComponentsNode(Node parent, List components) {
if (components != null && !components.isEmpty()) {
for (Component component : components) {
final List componentAttrs = new ArrayList<>();
componentAttrs.add(new Attribute("type", component.getType().getTypeName()));
if (component.getBomRef() != null) {
componentAttrs.add(new Attribute("bom-ref", component.getBomRef()));
}
final Element componentNode = createElement(parent, "component", null, componentAttrs.toArray(new Attribute[0]));
createElement(componentNode, "publisher", stripBreaks(component.getPublisher()));
createElement(componentNode, "group", stripBreaks(component.getGroup()));
createElement(componentNode, "name", stripBreaks(component.getName()));
createElement(componentNode, "version", stripBreaks(component.getVersion()));
createElement(componentNode, "description", stripBreaks(component.getDescription()));
if (component.getScope() == null) {
createElement(componentNode, "scope", Component.Scope.REQUIRED.getScopeName());
} else {
createElement(componentNode, "scope", component.getScope().getScopeName());
}
createHashesNode(componentNode, component.getHashes());
createLicenseNode(componentNode, component.getLicenseChoice(), true);
createElement(componentNode, "copyright", stripBreaks(component.getCopyright()));
createElement(componentNode, "cpe", stripBreaks(component.getCpe()));
createElement(componentNode, "purl", stripBreaks(component.getPurl()));
createPedigreeNode(componentNode, component.getPedigree());
createExternalReferencesNode(componentNode, component.getExternalReferences());
if (component.getComponents() != null && !component.getComponents().isEmpty()) {
final Element subComponentsNode = createElement(componentNode, "components");
createComponentsNode(subComponentsNode, component.getComponents());
}
processExtensions(componentNode, component);
}
}
}
private void createPedigreeNode(Node parent, Pedigree pedigree) {
if (pedigree != null) {
final Element pedigreeNode = createElement(parent, "pedigree");
if (pedigree.getAncestors() != null && !pedigree.getAncestors().isEmpty()) {
final Element ancestorsNode = createElement(pedigreeNode, "ancestors");
createComponentsNode(ancestorsNode, pedigree.getAncestors());
}
if (pedigree.getDescendants() != null && !pedigree.getDescendants().isEmpty()) {
final Element descendantsNode = createElement(pedigreeNode, "descendants");
createComponentsNode(descendantsNode, pedigree.getDescendants());
}
if (pedigree.getVariants() != null && !pedigree.getVariants().isEmpty()) {
final Element variantsNode = createElement(pedigreeNode, "variants");
createComponentsNode(variantsNode, pedigree.getVariants());
}
if (pedigree.getCommits() != null && !pedigree.getCommits().isEmpty()) {
final Element commitsNode = createElement(pedigreeNode, "commits");
createCommitsNode(commitsNode, pedigree.getCommits());
}
createElement(pedigreeNode, "notes", stripBreaks(pedigree.getNotes()));
processExtensions(pedigreeNode, pedigree);
}
}
private void createCommitsNode(Node parent, List commits) {
if (commits != null) {
for (Commit commit: commits) {
final Element commitNode = createElement(parent, "commit");
createElement(commitNode, "uid", stripBreaks(commit.getUid()));
createElement(commitNode, "url", stripBreaks(commit.getUrl()));
createActorNode(commitNode, "author", commit.getAuthor());
createActorNode(commitNode, "committer", commit.getCommitter());
createElement(commitNode, "message", stripBreaks(commit.getMessage()));
processExtensions(commitNode, commit);
}
}
}
private void createActorNode(Node parent, String nodeName, IdentifiableActionType actor) {
if (actor != null) {
final Element authorNode = createElement(parent, nodeName);
if (actor.getTimestamp() != null) {
createElement(authorNode, "timestamp", dateFormat.format(actor.getTimestamp()));
}
createElement(authorNode, "name", stripBreaks(actor.getName()));
createElement(authorNode, "email", stripBreaks(actor.getEmail()));
processExtensions(authorNode, actor);
}
}
private void createExternalReferencesNode(Node parent, List references) {
if (references != null && !references.isEmpty()) {
final Element externalReferencesNode = createElement(parent, "externalReferences");
for (ExternalReference reference: references) {
if (reference.getType() != null && BomUtils.validateUrlString(reference.getUrl())) {
final Element referenceNode = createElement(externalReferencesNode, "reference", null, new Attribute("type", reference.getType().getTypeName()));
createElement(referenceNode, "url", stripBreaks(reference.getUrl()));
createElement(referenceNode, "comment", stripBreaks(reference.getComment()));
}
}
}
}
private void createDependenciesNode(Node parent, List dependencies) {
if (dependencies != null && !dependencies.isEmpty()) {
for (Dependency dependency : dependencies) {
final Element dependencyNode = createElement(parent, "dg:dependency", null, new Attribute("ref", dependency.getRef()));
if (dependency.getDependencies() != null && !dependency.getDependencies().isEmpty()) {
createDependenciesNode(dependencyNode, dependency.getDependencies());
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy