Skip to content

Commit 9a8c342

Browse files
committed
External References and Metadata Validations
1 parent 024b725 commit 9a8c342

File tree

6 files changed

+61
-16
lines changed

6 files changed

+61
-16
lines changed

src/main/java/org/cyclonedx/generators/AbstractBomGenerator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.cyclonedx.Version;
77
import org.cyclonedx.model.Bom;
88
import org.cyclonedx.util.serializer.EvidenceSerializer;
9+
import org.cyclonedx.util.serializer.ExternalReferenceSerializer;
910
import org.cyclonedx.util.serializer.InputTypeSerializer;
1011
import org.cyclonedx.util.serializer.LicenseChoiceSerializer;
1112
import org.cyclonedx.util.serializer.LifecycleSerializer;
@@ -63,5 +64,9 @@ protected void setupObjectMapper(boolean isXml) {
6364
SimpleModule signatoryModule = new SimpleModule();
6465
signatoryModule.addSerializer(new SignatorySerializer(isXml));
6566
mapper.registerModule(signatoryModule);
67+
68+
SimpleModule externalSerializer = new SimpleModule();
69+
externalSerializer.addSerializer(new ExternalReferenceSerializer(getSchemaVersion()));
70+
mapper.registerModule(externalSerializer);
6671
}
6772
}

src/main/java/org/cyclonedx/model/Bom.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public class Bom extends ExtensibleElement {
100100
@VersionFilter(Version.VERSION_15)
101101
private List<Annotation> annotations;
102102

103-
@VersionFilter(Version.VERSION_13)
103+
@JsonInclude(JsonInclude.Include.NON_EMPTY)
104104
private List<Property> properties;
105105

106106
@JacksonXmlProperty(isAttribute = true)
@@ -241,6 +241,7 @@ public void setAnnotations(List<Annotation> annotations) {
241241
@JacksonXmlElementWrapper(localName = "properties")
242242
@JacksonXmlProperty(localName = "property")
243243
@JsonInclude(JsonInclude.Include.NON_EMPTY)
244+
@VersionFilter(Version.VERSION_13)
244245
public List<Property> getProperties() {
245246
return properties;
246247
}

src/main/java/org/cyclonedx/model/Component.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ public void setPedigree(Pedigree pedigree) {
412412
@JacksonXmlElementWrapper(localName = "externalReferences")
413413
@JacksonXmlProperty(localName = "reference")
414414
@JsonDeserialize(using = ExternalReferencesDeserializer.class)
415+
@VersionFilter(Version.VERSION_11)
415416
public List<ExternalReference> getExternalReferences() {
416417
return externalReferences;
417418
}

src/main/java/org/cyclonedx/model/ExternalReference.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,13 @@
2525
import com.fasterxml.jackson.annotation.JsonInclude;
2626
import com.fasterxml.jackson.annotation.JsonProperty;
2727
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
28-
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
2928
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
3029
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
3130
import org.cyclonedx.Version;
32-
import org.cyclonedx.util.serializer.ExternalReferenceSerializer;
3331

3432
@SuppressWarnings("unused")
3533
@JsonIgnoreProperties(ignoreUnknown = true)
3634
@JsonInclude(JsonInclude.Include.NON_NULL)
37-
@JsonSerialize(using = ExternalReferenceSerializer.class)
3835
@JsonPropertyOrder({"url", "comment", "hashes"})
3936
public class ExternalReference {
4037

src/main/java/org/cyclonedx/util/serializer/ExternalReferenceSerializer.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,25 @@
2626
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
2727
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
2828
import org.apache.commons.collections4.CollectionUtils;
29+
import org.cyclonedx.Version;
2930
import org.cyclonedx.model.ExternalReference;
3031
import org.cyclonedx.model.ExternalReference.Type;
3132
import org.cyclonedx.model.Hash;
33+
import org.cyclonedx.model.VersionFilter;
3234
import org.cyclonedx.util.BomUtils;
3335

3436
public class ExternalReferenceSerializer
3537
extends StdSerializer<ExternalReference>
3638
{
37-
public ExternalReferenceSerializer() {
38-
this(null);
39+
private final Version version;
40+
41+
public ExternalReferenceSerializer(final Version version) {
42+
this(null, version);
3943
}
4044

41-
public ExternalReferenceSerializer(final Class<ExternalReference> t) {
45+
public ExternalReferenceSerializer(final Class<ExternalReference> t, final Version version) {
4246
super(t);
47+
this.version = version;
4348
}
4449

4550
@Override
@@ -53,6 +58,10 @@ public void serialize(
5358
return;
5459
}
5560

61+
if(!shouldSerializeField(extRef.getType())) {
62+
return;
63+
}
64+
5665
if (gen instanceof ToXmlGenerator) {
5766
serializeXml((ToXmlGenerator) gen, extRef);
5867
}
@@ -114,4 +123,22 @@ private void serializeJson(final JsonGenerator gen, final ExternalReference extR
114123
}
115124
gen.writeEndObject();
116125
}
126+
127+
private boolean shouldSerializeField(Object obj) {
128+
try {
129+
if (obj instanceof Type) {
130+
Type type = (Type) obj;
131+
VersionFilter filter = type.getClass().getField(type.name()).getAnnotation(VersionFilter.class);
132+
return filter == null || filter.value().getVersion() <= version.getVersion();
133+
}
134+
return true;
135+
}catch (NoSuchFieldException e) {
136+
return false;
137+
}
138+
}
139+
140+
@Override
141+
public Class<ExternalReference> handledType() {
142+
return ExternalReference.class;
143+
}
117144
}

src/main/java/org/cyclonedx/util/serializer/MetadataSerializer.java

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
package org.cyclonedx.util.serializer;
22

33
import java.io.IOException;
4+
import java.lang.reflect.Field;
45
import java.util.List;
56

67
import com.fasterxml.jackson.core.JsonGenerator;
78
import com.fasterxml.jackson.databind.SerializerProvider;
89
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
910
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
11+
import org.apache.commons.collections4.CollectionUtils;
1012
import org.cyclonedx.Version;
1113
import org.cyclonedx.model.Metadata;
1214
import org.cyclonedx.model.Property;
15+
import org.cyclonedx.model.VersionFilter;
1316
import org.cyclonedx.model.metadata.ToolInformation;
1417

1518
public class MetadataSerializer
@@ -45,20 +48,20 @@ private void createMetadataInfo(final Metadata metadata, final JsonGenerator jso
4548
{
4649
jsonGenerator.writeStartObject();
4750

48-
if (metadata.getTimestamp() != null) {
51+
if (metadata.getTimestamp() != null && shouldSerializeField(metadata, "timestamp")) {
4952
jsonGenerator.writeFieldName("timestamp");
5053
new CustomDateSerializer().serialize(metadata.getTimestamp(), jsonGenerator, serializerProvider);
5154
}
5255

53-
if(metadata.getLifecycles() != null) {
56+
if(metadata.getLifecycles() != null && shouldSerializeField(metadata, "lifecycles")) {
5457
jsonGenerator.writeFieldName("lifecycles");
5558
new LifecycleSerializer(isXml).serialize(metadata.getLifecycles(), jsonGenerator, serializerProvider);
5659
}
5760

5861
//Tools
5962
parseTools(metadata, jsonGenerator);
6063

61-
if (metadata.getAuthors() != null) {
64+
if (metadata.getAuthors() != null && shouldSerializeField(metadata, "author")) {
6265
if (isXml) {
6366
ToXmlGenerator xmlGenerator = (ToXmlGenerator) jsonGenerator;
6467
writeArrayFieldXML(metadata.getAuthors(), xmlGenerator, "author");
@@ -68,28 +71,28 @@ private void createMetadataInfo(final Metadata metadata, final JsonGenerator jso
6871
}
6972
}
7073

71-
if(metadata.getComponent() != null) {
74+
if(metadata.getComponent() != null && shouldSerializeField(metadata, "component")) {
7275
jsonGenerator.writeObjectField("component", metadata.getComponent());
7376
}
7477

75-
if(metadata.getManufacture() != null) {
78+
if(metadata.getManufacture() != null && shouldSerializeField(metadata, "manufacture")) {
7679
jsonGenerator.writeObjectField("manufacture", metadata.getManufacture());
7780
}
7881

79-
if(metadata.getManufacturer() != null) {
82+
if(metadata.getManufacturer() != null && shouldSerializeField(metadata, "manufacturer")) {
8083
jsonGenerator.writeObjectField("manufacturer", metadata.getManufacturer());
8184
}
8285

83-
if(metadata.getSupplier() != null) {
86+
if(metadata.getSupplier() != null && shouldSerializeField(metadata, "supplier")) {
8487
jsonGenerator.writeObjectField("supplier", metadata.getSupplier());
8588
}
8689

87-
if(metadata.getLicenses() != null) {
90+
if(metadata.getLicenses() != null && shouldSerializeField(metadata, "licenses")) {
8891
jsonGenerator.writeFieldName("licenses");
8992
new LicenseChoiceSerializer(isXml, version).serialize(metadata.getLicenses(), jsonGenerator, serializerProvider);
9093
}
9194

92-
if(metadata.getProperties()!=null) {
95+
if (CollectionUtils.isNotEmpty(metadata.getProperties()) && shouldSerializeField(metadata, "properties")) {
9396
if (isXml) {
9497
ToXmlGenerator xmlGenerator = (ToXmlGenerator) jsonGenerator;
9598
xmlGenerator.writeFieldName("properties");
@@ -165,6 +168,17 @@ private <T> void writeArrayFieldXML(List<T> items, ToXmlGenerator xmlGenerator,
165168
}
166169
}
167170

171+
private boolean shouldSerializeField(Object obj, String fieldName) {
172+
try {
173+
Field field = obj.getClass().getDeclaredField(fieldName);
174+
VersionFilter filter = field.getAnnotation(VersionFilter.class);
175+
return filter == null || filter.value().getVersion() <= version.getVersion();
176+
} catch (NoSuchFieldException e) {
177+
// If the field does not exist, assume it should be serialized
178+
return true;
179+
}
180+
}
181+
168182
@Override
169183
public Class<Metadata> handledType() {
170184
return Metadata.class;

0 commit comments

Comments
 (0)