Skip to content

Commit

Permalink
Merge pull request #426 from CycloneDX/Add_validations_external_refer…
Browse files Browse the repository at this point in the history
…ences

External References and Metadata Validations
  • Loading branch information
nscuro authored Jun 15, 2024
2 parents 024b725 + bd29da2 commit 66423fe
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.cyclonedx.Version;
import org.cyclonedx.model.Bom;
import org.cyclonedx.util.serializer.EvidenceSerializer;
import org.cyclonedx.util.serializer.ExternalReferenceSerializer;
import org.cyclonedx.util.serializer.InputTypeSerializer;
import org.cyclonedx.util.serializer.LicenseChoiceSerializer;
import org.cyclonedx.util.serializer.LifecycleSerializer;
Expand Down Expand Up @@ -63,5 +64,9 @@ protected void setupObjectMapper(boolean isXml) {
SimpleModule signatoryModule = new SimpleModule();
signatoryModule.addSerializer(new SignatorySerializer(isXml));
mapper.registerModule(signatoryModule);

SimpleModule externalSerializer = new SimpleModule();
externalSerializer.addSerializer(new ExternalReferenceSerializer(getSchemaVersion()));
mapper.registerModule(externalSerializer);
}
}
3 changes: 2 additions & 1 deletion src/main/java/org/cyclonedx/model/Bom.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public class Bom extends ExtensibleElement {
@VersionFilter(Version.VERSION_15)
private List<Annotation> annotations;

@VersionFilter(Version.VERSION_13)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<Property> properties;

@JacksonXmlProperty(isAttribute = true)
Expand Down Expand Up @@ -241,6 +241,7 @@ public void setAnnotations(List<Annotation> annotations) {
@JacksonXmlElementWrapper(localName = "properties")
@JacksonXmlProperty(localName = "property")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@VersionFilter(Version.VERSION_13)
public List<Property> getProperties() {
return properties;
}
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/cyclonedx/model/Component.java
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ public void setPedigree(Pedigree pedigree) {
@JacksonXmlElementWrapper(localName = "externalReferences")
@JacksonXmlProperty(localName = "reference")
@JsonDeserialize(using = ExternalReferencesDeserializer.class)
@VersionFilter(Version.VERSION_11)
public List<ExternalReference> getExternalReferences() {
return externalReferences;
}
Expand Down
3 changes: 0 additions & 3 deletions src/main/java/org/cyclonedx/model/ExternalReference.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,13 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
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.util.serializer.ExternalReferenceSerializer;

@SuppressWarnings("unused")
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonSerialize(using = ExternalReferenceSerializer.class)
@JsonPropertyOrder({"url", "comment", "hashes"})
public class ExternalReference {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,25 @@
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import org.apache.commons.collections4.CollectionUtils;
import org.cyclonedx.Version;
import org.cyclonedx.model.ExternalReference;
import org.cyclonedx.model.ExternalReference.Type;
import org.cyclonedx.model.Hash;
import org.cyclonedx.model.VersionFilter;
import org.cyclonedx.util.BomUtils;

public class ExternalReferenceSerializer
extends StdSerializer<ExternalReference>
{
public ExternalReferenceSerializer() {
this(null);
private final Version version;

public ExternalReferenceSerializer(final Version version) {
this(null, version);
}

public ExternalReferenceSerializer(final Class<ExternalReference> t) {
public ExternalReferenceSerializer(final Class<ExternalReference> t, final Version version) {
super(t);
this.version = version;
}

@Override
Expand All @@ -53,6 +58,10 @@ public void serialize(
return;
}

if(!shouldSerializeField(extRef.getType())) {
return;
}

if (gen instanceof ToXmlGenerator) {
serializeXml((ToXmlGenerator) gen, extRef);
}
Expand Down Expand Up @@ -114,4 +123,22 @@ private void serializeJson(final JsonGenerator gen, final ExternalReference extR
}
gen.writeEndObject();
}

private boolean shouldSerializeField(Object obj) {
try {
if (obj instanceof Type) {
Type type = (Type) obj;
VersionFilter filter = type.getClass().getField(type.name()).getAnnotation(VersionFilter.class);
return filter == null || filter.value().getVersion() <= version.getVersion();
}
return true;
}catch (NoSuchFieldException e) {
return false;
}
}

@Override
public Class<ExternalReference> handledType() {
return ExternalReference.class;
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package org.cyclonedx.util.serializer;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import org.apache.commons.collections4.CollectionUtils;
import org.cyclonedx.Version;
import org.cyclonedx.model.Metadata;
import org.cyclonedx.model.Property;
import org.cyclonedx.model.VersionFilter;
import org.cyclonedx.model.metadata.ToolInformation;

public class MetadataSerializer
Expand Down Expand Up @@ -45,20 +48,20 @@ private void createMetadataInfo(final Metadata metadata, final JsonGenerator jso
{
jsonGenerator.writeStartObject();

if (metadata.getTimestamp() != null) {
if (metadata.getTimestamp() != null && shouldSerializeField(metadata, "timestamp")) {
jsonGenerator.writeFieldName("timestamp");
new CustomDateSerializer().serialize(metadata.getTimestamp(), jsonGenerator, serializerProvider);
}

if(metadata.getLifecycles() != null) {
if(metadata.getLifecycles() != null && shouldSerializeField(metadata, "lifecycles")) {
jsonGenerator.writeFieldName("lifecycles");
new LifecycleSerializer(isXml).serialize(metadata.getLifecycles(), jsonGenerator, serializerProvider);
}

//Tools
parseTools(metadata, jsonGenerator);

if (metadata.getAuthors() != null) {
if (metadata.getAuthors() != null && shouldSerializeField(metadata, "author")) {
if (isXml) {
ToXmlGenerator xmlGenerator = (ToXmlGenerator) jsonGenerator;
writeArrayFieldXML(metadata.getAuthors(), xmlGenerator, "author");
Expand All @@ -68,28 +71,28 @@ private void createMetadataInfo(final Metadata metadata, final JsonGenerator jso
}
}

if(metadata.getComponent() != null) {
if(metadata.getComponent() != null && shouldSerializeField(metadata, "component")) {
jsonGenerator.writeObjectField("component", metadata.getComponent());
}

if(metadata.getManufacture() != null) {
if(metadata.getManufacture() != null && shouldSerializeField(metadata, "manufacture")) {
jsonGenerator.writeObjectField("manufacture", metadata.getManufacture());
}

if(metadata.getManufacturer() != null) {
if(metadata.getManufacturer() != null && shouldSerializeField(metadata, "manufacturer")) {
jsonGenerator.writeObjectField("manufacturer", metadata.getManufacturer());
}

if(metadata.getSupplier() != null) {
if(metadata.getSupplier() != null && shouldSerializeField(metadata, "supplier")) {
jsonGenerator.writeObjectField("supplier", metadata.getSupplier());
}

if(metadata.getLicenses() != null) {
if(metadata.getLicenses() != null && shouldSerializeField(metadata, "licenses")) {
jsonGenerator.writeFieldName("licenses");
new LicenseChoiceSerializer(isXml, version).serialize(metadata.getLicenses(), jsonGenerator, serializerProvider);
}

if(metadata.getProperties()!=null) {
if (CollectionUtils.isNotEmpty(metadata.getProperties()) && shouldSerializeField(metadata, "properties")) {
if (isXml) {
ToXmlGenerator xmlGenerator = (ToXmlGenerator) jsonGenerator;
xmlGenerator.writeFieldName("properties");
Expand Down Expand Up @@ -165,6 +168,17 @@ private <T> void writeArrayFieldXML(List<T> items, ToXmlGenerator xmlGenerator,
}
}

private boolean shouldSerializeField(Object obj, String fieldName) {
try {
Field field = obj.getClass().getDeclaredField(fieldName);
VersionFilter filter = field.getAnnotation(VersionFilter.class);
return filter == null || filter.value().getVersion() <= version.getVersion();
} catch (NoSuchFieldException e) {
// If the field does not exist, assume it should be serialized
return true;
}
}

@Override
public Class<Metadata> handledType() {
return Metadata.class;
Expand Down

0 comments on commit 66423fe

Please sign in to comment.