From d42b84839dc8182b0117465e013719201ffdb00e Mon Sep 17 00:00:00 2001 From: Alex Alzate Date: Fri, 1 Mar 2024 08:48:30 -0500 Subject: [PATCH] Add Tags Support and others Signed-off-by: Alex Alzate --- .../java/org/cyclonedx/model/Component.java | 39 ++++++++++++++++ .../java/org/cyclonedx/model/Metadata.java | 13 ++++++ .../org/cyclonedx/model/ReleaseNotes.java | 12 ++--- .../java/org/cyclonedx/model/Service.java | 6 +++ .../org/cyclonedx/model/component/Tags.java | 35 +++++++++++++++ .../util/deserializer/TagsDeserializer.java | 44 +++++++++++++++++++ .../cyclonedx/parsers/AbstractParserTest.java | 2 +- 7 files changed, 144 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/cyclonedx/model/component/Tags.java create mode 100644 src/main/java/org/cyclonedx/util/deserializer/TagsDeserializer.java diff --git a/src/main/java/org/cyclonedx/model/Component.java b/src/main/java/org/cyclonedx/model/Component.java index 5774b64bb..6fde7019a 100644 --- a/src/main/java/org/cyclonedx/model/Component.java +++ b/src/main/java/org/cyclonedx/model/Component.java @@ -22,9 +22,11 @@ import java.util.List; import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonUnwrapped; import org.cyclonedx.Version; import org.cyclonedx.model.component.ModelCard; import org.cyclonedx.model.component.crypto.CryptoProperties; +import org.cyclonedx.model.component.Tags; import org.cyclonedx.model.component.modelCard.ComponentData; import org.cyclonedx.util.deserializer.ExternalReferencesDeserializer; import org.cyclonedx.util.deserializer.HashesDeserializer; @@ -142,6 +144,7 @@ public String getScopeName() { private String mimeType; @VersionFilter(Version.VERSION_12) private OrganizationalEntity supplier; + @Deprecated @VersionFilter(Version.VERSION_12) private String author; @VersionFilter(Version.VERSION_11) @@ -193,6 +196,18 @@ public String getScopeName() { @JsonProperty("provides") private List provides; + @VersionFilter(Version.VERSION_16) + @JsonUnwrapped + private Tags tags; + + @VersionFilter(Version.VERSION_16) + @JsonProperty("authors") + private List authors; + + @VersionFilter(Version.VERSION_16) + @JsonProperty("manufacturer") + private OrganizationalEntity manufacturer; + @JsonOnly @VersionFilter(Version.VERSION_14) private Signature signature; @@ -493,6 +508,30 @@ public void setProvides(final List provides) { this.provides = provides; } + public Tags getTags() { + return tags; + } + + public void setTags(final Tags tags) { + this.tags = tags; + } + + public List getAuthors() { + return authors; + } + + public void setAuthors(final List authors) { + this.authors = authors; + } + + public OrganizationalEntity getManufacturer() { + return manufacturer; + } + + public void setManufacturer(final OrganizationalEntity manufacturer) { + this.manufacturer = manufacturer; + } + @Override public int hashCode() { return Objects.hash(author, publisher, group, name, version, description, scope, hashes, license, copyright, diff --git a/src/main/java/org/cyclonedx/model/Metadata.java b/src/main/java/org/cyclonedx/model/Metadata.java index 2ddc20849..a79ae8aa5 100644 --- a/src/main/java/org/cyclonedx/model/Metadata.java +++ b/src/main/java/org/cyclonedx/model/Metadata.java @@ -73,6 +73,11 @@ public class Metadata @VersionFilter(Version.VERSION_12) private Component component; + @VersionFilter(Version.VERSION_16) + @JsonProperty("manufacturer") + private OrganizationalEntity manufacturer; + + @Deprecated @VersionFilter(Version.VERSION_12) private OrganizationalEntity manufacture; @@ -197,6 +202,14 @@ public void setToolChoice(final ToolInformation toolInformation) { this.toolInformation = toolInformation; } + public OrganizationalEntity getManufacturer() { + return manufacturer; + } + + public void setManufacturer(final OrganizationalEntity manufacturer) { + this.manufacturer = manufacturer; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/org/cyclonedx/model/ReleaseNotes.java b/src/main/java/org/cyclonedx/model/ReleaseNotes.java index c9a777976..34239e892 100644 --- a/src/main/java/org/cyclonedx/model/ReleaseNotes.java +++ b/src/main/java/org/cyclonedx/model/ReleaseNotes.java @@ -24,12 +24,14 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import org.cyclonedx.Version; +import org.cyclonedx.model.component.Tags; import org.cyclonedx.util.deserializer.NotesDeserializer; import org.cyclonedx.util.deserializer.PropertiesDeserializer; import org.cyclonedx.util.deserializer.ResolvesDeserializer; @@ -67,7 +69,8 @@ public ReleaseNotes() {} @VersionFilter(Version.VERSION_14) private Date timestamp; private List aliases; - private List tags; + @JsonUnwrapped + private Tags tags; private List resolves; private List notes; private List properties; @@ -131,14 +134,11 @@ public void setAliases(final List aliases) { this.aliases = aliases; } - @JacksonXmlElementWrapper(localName = "tags") - @JacksonXmlProperty(localName = "tag") - @JsonDeserialize(using = StringListDeserializer.class) - public List getTags() { + public Tags getTags() { return tags; } - public void setTags(final List tags) { + public void setTags(final Tags tags) { this.tags = tags; } diff --git a/src/main/java/org/cyclonedx/model/Service.java b/src/main/java/org/cyclonedx/model/Service.java index 14b087c72..b692f996d 100644 --- a/src/main/java/org/cyclonedx/model/Service.java +++ b/src/main/java/org/cyclonedx/model/Service.java @@ -22,10 +22,12 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import org.cyclonedx.Version; +import org.cyclonedx.model.component.Tags; import org.cyclonedx.util.deserializer.ExternalReferencesDeserializer; import org.cyclonedx.util.deserializer.StringListDeserializer; @@ -48,6 +50,7 @@ "licenses", "externalReferences", "properties", + "tags", "services", "releaseNotes", "signature" @@ -72,6 +75,9 @@ public class Service extends ExtensibleElement { private List externalReferences; @VersionFilter(Version.VERSION_13) private List properties; + @VersionFilter(value = Version.VERSION_16) + @JsonUnwrapped + private Tags tags; private List services; private ReleaseNotes releaseNotes; @JsonOnly diff --git a/src/main/java/org/cyclonedx/model/component/Tags.java b/src/main/java/org/cyclonedx/model/component/Tags.java new file mode 100644 index 000000000..e180e3d59 --- /dev/null +++ b/src/main/java/org/cyclonedx/model/component/Tags.java @@ -0,0 +1,35 @@ +package org.cyclonedx.model.component; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import org.cyclonedx.util.deserializer.TagsDeserializer; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonDeserialize(using = TagsDeserializer.class) +public class Tags +{ + private List tags; + + public Tags() { + } + + public Tags(List tags){ + this.tags = tags; + } + + @JacksonXmlElementWrapper(localName = "tags") + @JacksonXmlProperty(localName = "tag") + @JsonProperty("tags") + public List getTags() { + return tags; + } + + public void setTags(final List tags) { + this.tags = tags; + } +} diff --git a/src/main/java/org/cyclonedx/util/deserializer/TagsDeserializer.java b/src/main/java/org/cyclonedx/util/deserializer/TagsDeserializer.java new file mode 100644 index 000000000..ebf288eba --- /dev/null +++ b/src/main/java/org/cyclonedx/util/deserializer/TagsDeserializer.java @@ -0,0 +1,44 @@ +package org.cyclonedx.util.deserializer; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import org.cyclonedx.model.component.Tags; + +public class TagsDeserializer + extends JsonDeserializer +{ + + private final ObjectMapper mapper = new ObjectMapper(); + @Override + public Tags deserialize(JsonParser parser, DeserializationContext context) throws IOException { + JsonNode node = parser.getCodec().readTree(parser); + + if(node.has("tag")) { + return parseNode(node.get("tag")); + } else { + return parseNode(node); + } + } + + private Tags parseNode(JsonNode node) { + List list = new ArrayList<>(); + + ArrayNode nodes = (node.isArray() ? (ArrayNode) node : new ArrayNode(null).add(node)); + for (JsonNode tagNode : nodes) { + list.add(tagNode.asText()); + } + + if(!list.isEmpty()) { + return new Tags(list); + } + return null; + } +} \ No newline at end of file diff --git a/src/test/java/org/cyclonedx/parsers/AbstractParserTest.java b/src/test/java/org/cyclonedx/parsers/AbstractParserTest.java index 279e923d8..bf34ef755 100644 --- a/src/test/java/org/cyclonedx/parsers/AbstractParserTest.java +++ b/src/test/java/org/cyclonedx/parsers/AbstractParserTest.java @@ -837,7 +837,7 @@ void assertMetadata(final Metadata metadata, final Version version) { assertNotNull(releaseNotes.getSocialImage()); assertNotNull(releaseNotes.getTimestamp()); assertEquals(1, releaseNotes.getAliases().size()); - assertEquals(1, releaseNotes.getTags().size()); + assertEquals(1, releaseNotes.getTags().getTags().size()); //Resolves assertEquals(1, releaseNotes.getResolves().size());