diff --git a/tools/pom.xml b/tools/pom.xml
index befc1048..e2e84939 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -54,8 +54,9 @@
2.17.0
3.17.0
1.12.0
+ 1.5.5
1.4.9
- 10.0.0
+ 2.0.16
@@ -98,6 +99,24 @@
+
+
+
+
+ org.slf4j
+ slf4j-api
+ ${lib.slf4j.api}
+
+
+
+ org.slf4j
+ slf4j-simple
+ ${lib.slf4j.api}
+
+
+
+
+
@@ -123,16 +142,22 @@
compile
+
+ com.networknt
+ json-schema-validator
+ ${lib.json.schema.validator}
+ test
+
org.junit.jupiter
- junit-jupiter-engine
- 5.7.0
+ junit-jupiter-api
+ 5.11.4
test
+
- org.cyclonedx
- cyclonedx-core-java
- ${lib.cyclonedx.core.java.version}
+ org.slf4j
+ slf4j-simple
test
@@ -142,15 +167,15 @@
org.apache.maven.plugins
maven-surefire-plugin
- 3.5.1
+ 3.5.2
- ${basedir}/../schema
+ ${project.basedir}/../schema
- src/test/resources/
+ src/test/resources
diff --git a/tools/src/test/java/org/cyclonedx/schema/BaseSchemaVerificationTest.java b/tools/src/test/java/org/cyclonedx/schema/BaseSchemaVerificationTest.java
index a67565ed..31cfc098 100644
--- a/tools/src/test/java/org/cyclonedx/schema/BaseSchemaVerificationTest.java
+++ b/tools/src/test/java/org/cyclonedx/schema/BaseSchemaVerificationTest.java
@@ -33,17 +33,14 @@ List getAllResources() throws Exception {
return files;
}
- List getResources(final String resourceDirectory) throws Exception {
- final List files = new ArrayList<>();
- String dir = resourceDirectory;
- if (!resourceDirectory.endsWith("/")) {
- dir += "/";
- }
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(dir)) {
+ private List getResources(final String resourceDirectory) throws Exception {
+ final List resources = new ArrayList<>();
+ try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(resourceDirectory)) {
if (in != null) {
- files.addAll(IOUtils.readLines(in, StandardCharsets.UTF_8));
+ IOUtils.readLines(in, StandardCharsets.UTF_8)
+ .forEach(resource -> resources.add(resourceDirectory + resource));
}
}
- return files;
+ return resources;
}
}
diff --git a/tools/src/test/java/org/cyclonedx/schema/JsonSchemaVerificationTest.java b/tools/src/test/java/org/cyclonedx/schema/JsonSchemaVerificationTest.java
index 1598c0ae..4680aefa 100644
--- a/tools/src/test/java/org/cyclonedx/schema/JsonSchemaVerificationTest.java
+++ b/tools/src/test/java/org/cyclonedx/schema/JsonSchemaVerificationTest.java
@@ -13,68 +13,127 @@
*/
package org.cyclonedx.schema;
-import java.io.File;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.networknt.schema.DefaultJsonMetaSchemaFactory;
+import com.networknt.schema.DisallowUnknownKeywordFactory;
+import com.networknt.schema.JsonMetaSchema;
+import com.networknt.schema.JsonMetaSchemaFactory;
+import com.networknt.schema.JsonSchema;
+import com.networknt.schema.JsonSchemaFactory;
+import com.networknt.schema.NonValidationKeyword;
+import com.networknt.schema.SchemaId;
+import com.networknt.schema.SchemaLocation;
+import com.networknt.schema.SchemaValidatorsConfig;
+import com.networknt.schema.resource.ClasspathSchemaLoader;
+import com.networknt.schema.resource.DisallowSchemaLoader;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-
-import org.cyclonedx.parsers.JsonParser;
-import org.cyclonedx.Version;
+import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.assertFalse;
+class JsonSchemaVerificationTest extends BaseSchemaVerificationTest {
+
+ private static final ObjectMapper MAPPER = new JsonMapper();
+
+ private static final String JSF_NAMESPACE = "http://cyclonedx.org/schema/jsf-0.82.schema.json";
+ private static final String SPDX_NAMESPACE = "http://cyclonedx.org/schema/spdx.schema.json";
+
+ private static final JsonSchema VERSION_12;
+ private static final JsonSchema VERSION_13;
+ private static final JsonSchema VERSION_14;
+ private static final JsonSchema VERSION_15;
+ private static final JsonSchema VERSION_16;
+
+ static {
+ JsonMetaSchemaFactory metaSchemaFactory = new DefaultJsonMetaSchemaFactory() {
+ @Override
+ public JsonMetaSchema getMetaSchema(
+ String iri, JsonSchemaFactory schemaFactory, SchemaValidatorsConfig config) {
+ return addCustomKeywords(super.getMetaSchema(iri, schemaFactory, config));
+ }
+ };
+ JsonSchemaFactory factory = JsonSchemaFactory.builder()
+ .defaultMetaSchemaIri(SchemaId.V7)
+ .metaSchema(addCustomKeywords(JsonMetaSchema.getV7()))
+ .metaSchemaFactory(metaSchemaFactory)
+ .schemaLoaders(b -> b.add(new ClasspathSchemaLoader()).add(DisallowSchemaLoader.getInstance()))
+ .schemaMappers(b -> b.mapPrefix(SPDX_NAMESPACE, "classpath:spdx.schema.json")
+ .mapPrefix(JSF_NAMESPACE, "classpath:jsf-0.82.schema.json"))
+ .build();
+ VERSION_12 = factory.getSchema(SchemaLocation.of("classpath:bom-1.2-strict.schema.json"));
+ VERSION_13 = factory.getSchema(SchemaLocation.of("classpath:bom-1.3-strict.schema.json"));
+ VERSION_14 = factory.getSchema(SchemaLocation.of("classpath:bom-1.4.schema.json"));
+ VERSION_15 = factory.getSchema(SchemaLocation.of("classpath:bom-1.5.schema.json"));
+ VERSION_16 = factory.getSchema(SchemaLocation.of("classpath:bom-1.6.schema.json"));
+ }
-public class JsonSchemaVerificationTest extends BaseSchemaVerificationTest {
+ private static JsonMetaSchema addCustomKeywords(JsonMetaSchema metaSchema) {
+ return JsonMetaSchema.builder(metaSchema)
+ // Non-standard keywords in the CycloneDX schema files.
+ .keyword(new NonValidationKeyword("deprecated"))
+ .keyword(new NonValidationKeyword("meta:enum"))
+ .unknownKeywordFactory(new DisallowUnknownKeywordFactory())
+ .build();
+ }
@TestFactory
Collection dynamicTestsWithCollection() throws Exception {
- final List files = getAllResources();
+ final List resources = getAllResources();
final List dynamicTests = new ArrayList<>();
- for (final String file: files) {
- if (file.endsWith(".json")) {
- final Version schemaVersion;
- if (file.endsWith("-1.2.json")) {
- schemaVersion = Version.VERSION_12;
- } else if (file.endsWith("-1.3.json")) {
- schemaVersion = Version.VERSION_13;
- } else if (file.endsWith("-1.4.json")) {
- schemaVersion = Version.VERSION_14;
- } else if (file.endsWith("-1.5.json")) {
- schemaVersion = Version.VERSION_15;
- } else if (file.endsWith("-1.6.json")) {
- schemaVersion = Version.VERSION_16;
- } else {
- schemaVersion = null;
- }
- if (file.startsWith("valid") && schemaVersion != null) {
- dynamicTests.add(DynamicTest.dynamicTest(file, () -> assertTrue(
- isValidJson(schemaVersion, "/" + schemaVersion.getVersionString() + "/" + file), file)));
- } else if (file.startsWith("invalid") && schemaVersion != null) {
- dynamicTests.add(DynamicTest.dynamicTest(file, () -> assertFalse(
- isValidJson(schemaVersion, "/" + schemaVersion.getVersionString() + "/" + file), file)));
+ for (final String resource : resources) {
+ String resourceName = StringUtils.substringAfterLast(resource, "/");
+ if (resourceName.endsWith(".json")) {
+ JsonSchema schema = getSchema(resourceName);
+ if (schema != null) {
+ if (resourceName.startsWith("valid")) {
+ dynamicTests.add(DynamicTest.dynamicTest(
+ resource, () -> assertTrue(isValid(schema, resource), resource)));
+ } else if (resourceName.startsWith("invalid")) {
+ dynamicTests.add(DynamicTest.dynamicTest(
+ resource, () -> assertFalse(isValid(schema, resource), resource)));
+ }
}
}
}
return dynamicTests;
}
- private boolean isValidJson(Version version, String resource) throws Exception {
- final File file = new File(this.getClass().getResource(resource).getFile());
- final JsonParser parser = new JsonParser();
- return parser.isValid(file, version);
-
- // Uncomment to provide more detailed validation errors
- /*
- try {
- final String jsonString = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
- parser.getJsonSchema(version, true).validate(new JSONObject(jsonString));
- return true;
- } catch (ValidationException e) {
- e.printStackTrace();
+ private boolean isValid(JsonSchema schema, String resource) {
+ try (InputStream input = getClass().getClassLoader().getResourceAsStream(resource);
+ JsonParser parser = MAPPER.createParser(input)) {
+ JsonNode node = parser.readValueAsTree();
+ return schema.validate(node).isEmpty();
+ } catch (IOException e) {
return false;
}
- */
+ }
+
+ private JsonSchema getSchema(String resourceName) {
+ if (resourceName.endsWith("-1.2.json")) {
+ return VERSION_12;
+ }
+ if (resourceName.endsWith("-1.3.json")) {
+ return VERSION_13;
+ }
+ if (resourceName.endsWith("-1.4.json")) {
+ return VERSION_14;
+ }
+ if (resourceName.endsWith("-1.5.json")) {
+ return VERSION_15;
+ }
+ if (resourceName.endsWith("-1.6.json")) {
+ return VERSION_16;
+ }
+ return null;
}
}
diff --git a/tools/src/test/java/org/cyclonedx/schema/XmlSchemaVerificationTest.java b/tools/src/test/java/org/cyclonedx/schema/XmlSchemaVerificationTest.java
index 2d57dd8a..348d9e5b 100644
--- a/tools/src/test/java/org/cyclonedx/schema/XmlSchemaVerificationTest.java
+++ b/tools/src/test/java/org/cyclonedx/schema/XmlSchemaVerificationTest.java
@@ -13,57 +13,77 @@
*/
package org.cyclonedx.schema;
-import java.io.File;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-
-import org.cyclonedx.parsers.XmlParser;
-import org.cyclonedx.Version;
+import javax.xml.XMLConstants;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.assertFalse;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
public class XmlSchemaVerificationTest extends BaseSchemaVerificationTest {
- @TestFactory
+ private static final Schema VERSION_10;
+ private static final Schema VERSION_11;
+ private static final Schema VERSION_12;
+ private static final Schema VERSION_13;
+ private static final Schema VERSION_14;
+ private static final Schema VERSION_15;
+ private static final Schema VERSION_16;
+
+ static {
+ try {
+ SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "file");
+ ClassLoader cl = XmlSchemaVerificationTest.class.getClassLoader();
+ // Override the `schemaLocation` property in the file
+ factory.setProperty(
+ "http://apache.org/xml/properties/schema/external-schemaLocation",
+ "http://cyclonedx.org/schema/spdx spdx.xsd");
+ VERSION_10 = factory.newSchema(cl.getResource("bom-1.0.xsd"));
+ VERSION_11 = factory.newSchema(cl.getResource("bom-1.1.xsd"));
+ VERSION_12 = factory.newSchema(cl.getResource("bom-1.2.xsd"));
+ VERSION_13 = factory.newSchema(cl.getResource("bom-1.3.xsd"));
+ VERSION_14 = factory.newSchema(cl.getResource("bom-1.4.xsd"));
+ VERSION_15 = factory.newSchema(cl.getResource("bom-1.5.xsd"));
+ VERSION_16 = factory.newSchema(cl.getResource("bom-1.6.xsd"));
+ } catch (SAXException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
/**
* Generates a collection of dynamic tests based on the available XML files.
*
* @return Collection a collection of dynamic tests
* @throws Exception if an error occurs during the generation of the dynamic tests
*/
+ @TestFactory
Collection dynamicTestsWithCollection() throws Exception {
- final List files = getAllResources();
+ final List resources = getAllResources();
final List dynamicTests = new ArrayList<>();
- for (final String file: files) {
- if (file.endsWith(".xml")) {
- final Version schemaVersion;
- if (file.endsWith("-1.0.xml")) {
- schemaVersion = Version.VERSION_10;
- } else if (file.endsWith("-1.1.xml")) {
- schemaVersion = Version.VERSION_11;
- } else if (file.endsWith("-1.2.xml")) {
- schemaVersion = Version.VERSION_12;
- } else if (file.endsWith("-1.3.xml")) {
- schemaVersion = Version.VERSION_13;
- } else if (file.endsWith("-1.4.xml")) {
- schemaVersion = Version.VERSION_14;
- } else if (file.endsWith("-1.5.xml")) {
- schemaVersion = Version.VERSION_15;
- } else if (file.endsWith("-1.6.xml")) {
- schemaVersion = Version.VERSION_16;
- } else {
- schemaVersion = null;
- }
- if (file.startsWith("valid") && schemaVersion != null) {
- dynamicTests.add(DynamicTest.dynamicTest(file, () -> assertTrue(
- isValid(schemaVersion, "/" + schemaVersion.getVersionString() + "/" + file), file)));
- } else if (file.startsWith("invalid") && schemaVersion != null) {
- dynamicTests.add(DynamicTest.dynamicTest(file, () -> assertFalse(
- isValid(schemaVersion, "/" + schemaVersion.getVersionString() + "/" + file), file)));
+ for (final String resource : resources) {
+ String resourceName = StringUtils.substringAfterLast(resource, "/");
+ if (resourceName.endsWith(".xml")) {
+ Schema schema = getSchema(resourceName);
+ if (schema != null) {
+ if (resourceName.startsWith("valid")) {
+ dynamicTests.add(DynamicTest.dynamicTest(
+ resource, () -> assertTrue(isValid(schema, resource), resource)));
+ } else if (resourceName.startsWith("invalid")) {
+ dynamicTests.add(DynamicTest.dynamicTest(
+ resource, () -> assertFalse(isValid(schema, resource), resource)));
+ }
}
}
}
@@ -73,14 +93,59 @@ Collection dynamicTestsWithCollection() throws Exception {
/**
* Validates the given XML file against the specified CycloneDX schema version.
*
- * @param version the CycloneDX schema version to validate against
- * @param resource the path to the XML file to be validated
+ * @param schema the CycloneDX schema to validate against
+ * @param resource the path to the XML file to be validated
* @return boolean true if the XML file is valid according to the specified schema version, false otherwise
* @throws Exception if an error occurs during the validation process
*/
- private boolean isValid(Version version, String resource) throws Exception {
- final File file = new File(this.getClass().getResource(resource).getFile());
- final XmlParser parser = new XmlParser();
- return parser.isValid(file, version);
+ private boolean isValid(Schema schema, String resource) throws Exception {
+ Validator validator = schema.newValidator();
+ validator.setErrorHandler(new ErrorHandler() {
+ @Override
+ public void warning(SAXParseException exception) throws SAXException {
+ throw exception;
+ }
+
+ @Override
+ public void error(SAXParseException exception) throws SAXException {
+ throw exception;
+ }
+
+ @Override
+ public void fatalError(SAXParseException exception) throws SAXException {
+ throw exception;
+ }
+ });
+ try {
+ validator.validate(new StreamSource(getClass().getClassLoader().getResourceAsStream(resource)));
+ } catch (SAXParseException e) {
+ return false;
+ }
+ return true;
+ }
+
+ private Schema getSchema(String resourceName) {
+ if (resourceName.endsWith("-1.0.xml")) {
+ return VERSION_10;
+ }
+ if (resourceName.endsWith("-1.1.xml")) {
+ return VERSION_11;
+ }
+ if (resourceName.endsWith("-1.2.xml")) {
+ return VERSION_12;
+ }
+ if (resourceName.endsWith("-1.3.xml")) {
+ return VERSION_13;
+ }
+ if (resourceName.endsWith("-1.4.xml")) {
+ return VERSION_14;
+ }
+ if (resourceName.endsWith("-1.5.xml")) {
+ return VERSION_15;
+ }
+ if (resourceName.endsWith("-1.6.xml")) {
+ return VERSION_16;
+ }
+ return null;
}
}