From b49c49cd84386bd087d827aade4a159538aa1063 Mon Sep 17 00:00:00 2001 From: Cyril Dangerville <1372580+cdanger@users.noreply.github.com> Date: Thu, 2 Nov 2023 23:24:52 +0100 Subject: [PATCH] - Upgraded parent project: 9.0.0 - Removed workaround for https://github.com/stleary/JSON-java/issues/589 after upgrade of org.everity.json.schema dependency --- pom.xml | 4 +- .../json/model/LimitsCheckingJSONObject.java | 2 +- .../xacml/json/model/XacmlJsonUtils.java | 392 +++++++----------- .../test/XacmlJsonSchemaValidationTest.java | 98 ++--- 4 files changed, 185 insertions(+), 311 deletions(-) diff --git a/pom.xml b/pom.xml index 11b0597..387dfd9 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.ow2.authzforce authzforce-ce-parent - 8.5.0 + 9.0.0 authzforce-ce-xacml-json-model jar @@ -38,7 +38,7 @@ org.testng testng - 6.11 + 7.8.0 test diff --git a/src/main/java/org/ow2/authzforce/xacml/json/model/LimitsCheckingJSONObject.java b/src/main/java/org/ow2/authzforce/xacml/json/model/LimitsCheckingJSONObject.java index d12cf1c..d3255ff 100644 --- a/src/main/java/org/ow2/authzforce/xacml/json/model/LimitsCheckingJSONObject.java +++ b/src/main/java/org/ow2/authzforce/xacml/json/model/LimitsCheckingJSONObject.java @@ -168,7 +168,7 @@ public Object nextValue() throws JSONException this.back(); string = sb.toString().trim(); - if ("".equals(string)) + if (string.isEmpty()) { throw this.syntaxError("Missing value"); } diff --git a/src/main/java/org/ow2/authzforce/xacml/json/model/XacmlJsonUtils.java b/src/main/java/org/ow2/authzforce/xacml/json/model/XacmlJsonUtils.java index e9b3a35..37bba1c 100644 --- a/src/main/java/org/ow2/authzforce/xacml/json/model/XacmlJsonUtils.java +++ b/src/main/java/org/ow2/authzforce/xacml/json/model/XacmlJsonUtils.java @@ -17,6 +17,9 @@ */ package org.ow2.authzforce.xacml.json.model; +import java.io.IOException; +import java.io.InputStream; + import org.everit.json.schema.Schema; import org.everit.json.schema.loader.SchemaClient; import org.everit.json.schema.loader.SchemaLoader; @@ -24,263 +27,146 @@ import org.json.JSONObject; import org.json.JSONTokener; -import java.io.*; -import java.util.*; - /** * Instances of JSON schema as defined by JSON Profile of XACML 3.0 * */ -public final class XacmlJsonUtils -{ - private static final SchemaClient CLASSPATH_AWARE_SCHEMA_CLIENT = SchemaClient.classPathAwareClient(); - - private static Schema loadSchema(String schemaFilenameRelativeToThisClass) - { - try (InputStream inputStream = XacmlJsonUtils.class.getResourceAsStream(schemaFilenameRelativeToThisClass)) - { - final JSONObject rawSchema = new JSONObject(new JSONTokener(inputStream)); - return SchemaLoader.builder().schemaJson(rawSchema).schemaClient(CLASSPATH_AWARE_SCHEMA_CLIENT).resolutionScope("classpath://org/ow2/authzforce/xacml/json/model/").build().load().build(); - } catch (final IOException e) - { - throw new RuntimeException(e); - } - } - - /** - * JSON schema for validating Requests according to JSON Profile of XACML 3.0 - */ - public static final Schema REQUEST_SCHEMA; - - /** - * JSON schema for validating Responses according to JSON Profile of XACML 3.0 - */ - public static final Schema RESPONSE_SCHEMA; - - /** - * JSON schema for validating Policies according to AuthzForce/JSON policy format for XACML Policy(Set) (see Policy.schema.json) - */ - public static final Schema POLICY_SCHEMA; - - static - { - REQUEST_SCHEMA = loadSchema("Request.schema.json"); - RESPONSE_SCHEMA = loadSchema("Response.schema.json"); - POLICY_SCHEMA = loadSchema("Policy.schema.json"); - } - - /* - - */ - private static void canonicalizeObligationsOrAdvice(JSONObject xacmlResult, String obligationsOrAdviceKey, boolean floatWithTrailingZeroToInt) - { - final JSONArray obligationsOrAdvice = xacmlResult.optJSONArray(obligationsOrAdviceKey); - if(obligationsOrAdvice != null) { - - if (obligationsOrAdvice.length() == 0) - { - xacmlResult.remove(obligationsOrAdviceKey); - } else - { - for (final Object obligation : obligationsOrAdvice) - { - assert obligation instanceof JSONObject; - final JSONObject obligationJsonObj = (JSONObject) obligation; - final JSONArray jsonArrayOfAtts = obligationJsonObj.optJSONArray("AttributeAssignment"); - if (jsonArrayOfAtts != null) - { - if (jsonArrayOfAtts.length() == 0) - { - obligationJsonObj.remove("AttributeAssignment"); - } else - { - for (final Object attJson : jsonArrayOfAtts) - { - assert attJson instanceof JSONObject; - final JSONObject attJsonObj = (JSONObject) attJson; - if (floatWithTrailingZeroToInt) - { - floatWithTrailingZeroToInt(attJsonObj); - } - } - } - } - } - } - } - - } - - /** - * Same as {@link #canonicalizeResponse(JSONObject, boolean)} but with second parameter set to false. - * - * @param xacmlJsonResponse - * input XACML Response - * @return canonicalized response - */ - public static JSONObject canonicalizeResponse(final JSONObject xacmlJsonResponse) - { - return canonicalizeResponse(xacmlJsonResponse, false); - } - - /** - * Canonicalize a XACML/JSON response, typically for comparison with another one. In particular, it removes every Result's status as we choose to ignore the Status. Indeed, a PDP implementation - * might return a perfectly XACML-compliant response but with extra StatusCode/Message/Detail that we would not expect. - * - * WARNING: this method modifies the content of {@code xacmlJsonResponse} directly - * FIXME: waiting for 'org.everity.json.schema' to upgrade dependency 'org.json:json' to v20210307 or later in order to fix https://github.com/stleary/JSON-java/issues/589 - * - * @param xacmlJsonResponse - * input XACML Response - * @param floatWithTrailingZeroToInt true iff floats with trailing zero (after decimal point) in AttributeValues are converted to Integer, this is originally a workaround for issue #589 on org.json:json library, used by our dependency 'org.everity.json.schema', which has been fixed in v20210307 of org.json:json; but still waiting for 'org.everity.json.schema' to upgrade. - * @return canonicalized response - */ - public static JSONObject canonicalizeResponse(final JSONObject xacmlJsonResponse, boolean floatWithTrailingZeroToInt) - { - /* - * We iterate over all results, because for each results, we don't compare everything. In particular, we choose to ignore the StatusMessage, StatusDetail and any nested StatusCode. Indeed, a - * PDP implementation might return a perfectly XACML-compliant response but with extra StatusCode/Message/Detail that we would not expect. - */ - for (final Object resultObj : xacmlJsonResponse.getJSONArray("Response")) - { - final JSONObject resultJsonObj = (JSONObject) resultObj; - // Status - final JSONObject statusJsonObj = resultJsonObj.optJSONObject("Status"); - if (statusJsonObj != null) - { - // remove Status if StatusCode OK (optional, default implicit therefore useless) - final JSONObject statusCodeJsonObj = statusJsonObj.getJSONObject("StatusCode"); - final String statusCodeVal = statusCodeJsonObj.getString("Value"); - if (statusCodeVal.equals("urn:oasis:names:tc:xacml:1.0:status:ok")) - { - // Status OK is useless, simplify - resultJsonObj.remove("Status"); - } else - { - // remove any nested status code, StatusMessage and StatusDetail - statusCodeJsonObj.remove("StatusCode"); - statusJsonObj.remove("StatusMessage"); - statusJsonObj.remove("StatusDetail"); - } - } - - // remove empty Category array if any - final JSONArray jsonArrayOfAttCats = resultJsonObj.optJSONArray("Category"); - if (jsonArrayOfAttCats != null) - { - if (jsonArrayOfAttCats.length() == 0) - { - resultJsonObj.remove("Category"); - } else - { - /* - * Remove any IncludeInResult property which is useless and optional in XACML/JSON. (NB.: IncludeInResult is mandatory in XACML/XML schema but optional in JSON Profile). - */ - for (final Object attCatJson : jsonArrayOfAttCats) - { - assert attCatJson instanceof JSONObject; - final JSONObject attCatJsonObj = (JSONObject) attCatJson; - final JSONArray jsonArrayOfAtts = attCatJsonObj.optJSONArray("Attribute"); - if (jsonArrayOfAtts != null) - { - if (jsonArrayOfAtts.length() == 0) - { - attCatJsonObj.remove("Attribute"); - } else - { - for (final Object attJson : jsonArrayOfAtts) - { - assert attJson instanceof JSONObject; - final JSONObject attJsonObj = (JSONObject) attJson; - attJsonObj.remove("IncludeInResult"); - if (floatWithTrailingZeroToInt) - { - floatWithTrailingZeroToInt(attJsonObj); - } - } - } - } - } - } - } - - // Handle attribute values in Obligations and AssociatedAdvice if floatWithTrailingZeroToInt - canonicalizeObligationsOrAdvice(resultJsonObj, "Obligations", floatWithTrailingZeroToInt); - canonicalizeObligationsOrAdvice(resultJsonObj, "AssociatedAdvice", floatWithTrailingZeroToInt); - - } - - return xacmlJsonResponse; - } - - /* - Returns a number if input was a Double with zero fraction, therefore converted to an integer type (BigInteger, Integer, Long, Short); else null - - FIXME: workaround for this issue: https://github.com/stleary/JSON-java/issues/589 - */ - private static Number floatWithTrailingZeroToInt(Object input) - { - if (input instanceof JSONObject) - { - final JSONObject json = (JSONObject) input; - final Map modifiedProperties = new HashMap<>(); - json.keySet().forEach(key -> - { - final Number convertedIfNonNull = floatWithTrailingZeroToInt(json.get(key)); - if (convertedIfNonNull != null) - { - // Double value to be changed to an integer - modifiedProperties.put(key, convertedIfNonNull); - } - }); - // apply modifications if any - modifiedProperties.forEach(json::put); - return null; - } - - if (input instanceof JSONArray) - { - final JSONArray json = (JSONArray) input; - final Deque> modifiedItems = new ArrayDeque<>(json.length()); - int index = 0; - for (final Object item : json) - { - final Number convertedIfNonNull = floatWithTrailingZeroToInt(item); - if (convertedIfNonNull != null) - { - // Double value to be changed to an integer - modifiedItems.addLast(new AbstractMap.SimpleImmutableEntry<>(index, convertedIfNonNull)); - } - index++; - } - // apply modifications if any - modifiedItems.forEach(e -> json.put(e.getKey(), e.getValue())); - return null; - } - - if (input instanceof Double) - { - // FIXME: workaround for this issue: https://github.com/stleary/JSON-java/issues/589 - // if there is some trailing zero, this Double is considered equivalent to an int - // The corresponding int is obtained after serializing/deserializing - final String serialized = JSONObject.valueToString(input); - final Object deserialized = JSONObject.stringToValue(serialized); - if (!(deserialized instanceof Double)) - { - // value was converted to an int - assert deserialized instanceof Number; - return (Number) deserialized; - } - } - - // nothing to change - return null; - } - - private XacmlJsonUtils() - { - // hide constructor - } +public final class XacmlJsonUtils { + /** + * JSON schema for validating Requests according to JSON Profile of XACML 3.0 + */ + public static final Schema REQUEST_SCHEMA; + + /** + * JSON schema for validating Responses according to JSON Profile of XACML 3.0 + */ + public static final Schema RESPONSE_SCHEMA; + + /** + * JSON schema for validating Policies according to AuthzForce/JSON policy format for XACML Policy(Set) (see Policy.schema.json) + */ + public static final Schema POLICY_SCHEMA; + + private static final SchemaClient CLASSPATH_AWARE_SCHEMA_CLIENT = SchemaClient.classPathAwareClient(); + + static { + REQUEST_SCHEMA = loadSchema("Request.schema.json"); + RESPONSE_SCHEMA = loadSchema("Response.schema.json"); + POLICY_SCHEMA = loadSchema("Policy.schema.json"); + } + + private XacmlJsonUtils() { + // hide constructor + } + + private static Schema loadSchema(String schemaFilenameRelativeToThisClass) { + try (InputStream inputStream = XacmlJsonUtils.class.getResourceAsStream(schemaFilenameRelativeToThisClass)) { + if (inputStream == null) { + throw new RuntimeException("No resource name '" + schemaFilenameRelativeToThisClass + "' found on the classpath"); + } + + final JSONObject rawSchema = new JSONObject(new JSONTokener(inputStream)); + return SchemaLoader.builder().schemaJson(rawSchema).schemaClient(CLASSPATH_AWARE_SCHEMA_CLIENT).resolutionScope("classpath://org/ow2/authzforce/xacml/json/model/").build().load().build(); + } + catch (final IOException e) { + throw new RuntimeException(e); + } + } + + /* + + */ + private static void canonicalizeObligationsOrAdvice(JSONObject xacmlResult, String obligationsOrAdviceKey) { + final JSONArray obligationsOrAdvice = xacmlResult.optJSONArray(obligationsOrAdviceKey); + if (obligationsOrAdvice != null) { + if (obligationsOrAdvice.isEmpty()) { + xacmlResult.remove(obligationsOrAdviceKey); + } + else { + for (final Object obligation : obligationsOrAdvice) { + assert obligation instanceof JSONObject; + final JSONObject obligationJsonObj = (JSONObject) obligation; + final JSONArray jsonArrayOfAtts = obligationJsonObj.optJSONArray("AttributeAssignment"); + if (jsonArrayOfAtts != null && jsonArrayOfAtts.isEmpty()) { + obligationJsonObj.remove("AttributeAssignment"); + } + } + } + } + } + + /** + * Canonicalize a XACML/JSON response, typically for comparison with another one. In particular, it removes every Result's status as we choose to ignore the Status. Indeed, a PDP implementation + * might return a perfectly XACML-compliant response but with extra StatusCode/Message/Detail that we would not expect. + *

+ * WARNING: this method modifies the content of {@code xacmlJsonResponse} directly + *

+ * @param xacmlJsonResponse + * input XACML Response + * @return canonicalized response + */ + public static JSONObject canonicalizeResponse(final JSONObject xacmlJsonResponse) { + /* + * We iterate over all results, because for each result, we don't compare everything. In particular, we choose to ignore the StatusMessage, StatusDetail and any nested StatusCode. Indeed, a + * PDP implementation might return a perfectly XACML-compliant response but with extra StatusCode/Message/Detail that we would not expect. + */ + for (final Object resultObj : xacmlJsonResponse.getJSONArray("Response")) { + final JSONObject resultJsonObj = (JSONObject) resultObj; + // Status + final JSONObject statusJsonObj = resultJsonObj.optJSONObject("Status"); + if (statusJsonObj != null) { + // remove Status if StatusCode OK (optional, default implicit therefore useless) + final JSONObject statusCodeJsonObj = statusJsonObj.getJSONObject("StatusCode"); + final String statusCodeVal = statusCodeJsonObj.getString("Value"); + if (statusCodeVal.equals("urn:oasis:names:tc:xacml:1.0:status:ok")) { + // Status OK is useless, simplify + resultJsonObj.remove("Status"); + } + else { + // remove any nested status code, StatusMessage and StatusDetail + statusCodeJsonObj.remove("StatusCode"); + statusJsonObj.remove("StatusMessage"); + statusJsonObj.remove("StatusDetail"); + } + } + + // remove empty Category array if any + final JSONArray jsonArrayOfAttCats = resultJsonObj.optJSONArray("Category"); + if (jsonArrayOfAttCats != null) { + if (jsonArrayOfAttCats.isEmpty()) { + resultJsonObj.remove("Category"); + } + else { + /* + * Remove any IncludeInResult property which is useless and optional in XACML/JSON. (NB.: IncludeInResult is mandatory in XACML/XML schema but optional in JSON Profile). + */ + for (final Object attCatJson : jsonArrayOfAttCats) { + assert attCatJson instanceof JSONObject; + final JSONObject attCatJsonObj = (JSONObject) attCatJson; + final JSONArray jsonArrayOfAtts = attCatJsonObj.optJSONArray("Attribute"); + if (jsonArrayOfAtts != null) { + if (jsonArrayOfAtts.isEmpty()) { + attCatJsonObj.remove("Attribute"); + } + else { + for (final Object attJson : jsonArrayOfAtts) { + assert attJson instanceof JSONObject; + final JSONObject attJsonObj = (JSONObject) attJson; + attJsonObj.remove("IncludeInResult"); + } + } + } + } + } + } + + // Handle attribute values in Obligations and AssociatedAdvice if floatWithTrailingZeroToInt + canonicalizeObligationsOrAdvice(resultJsonObj, "Obligations"); + canonicalizeObligationsOrAdvice(resultJsonObj, "AssociatedAdvice"); + } + + return xacmlJsonResponse; + } /* public static void main(String[] args) throws FileNotFoundException diff --git a/src/test/java/org/ow2/authzforce/xacml/json/model/test/XacmlJsonSchemaValidationTest.java b/src/test/java/org/ow2/authzforce/xacml/json/model/test/XacmlJsonSchemaValidationTest.java index e9cf7d8..bc16466 100644 --- a/src/test/java/org/ow2/authzforce/xacml/json/model/test/XacmlJsonSchemaValidationTest.java +++ b/src/test/java/org/ow2/authzforce/xacml/json/model/test/XacmlJsonSchemaValidationTest.java @@ -17,25 +17,13 @@ */ package org.ow2.authzforce.xacml.json.model.test; -import org.everit.json.schema.Schema; -import org.everit.json.schema.ValidationException; -import org.json.JSONObject; -import org.ow2.authzforce.xacml.Xacml3JaxbHelper; -import org.ow2.authzforce.xacml.json.model.LimitsCheckingJSONObject; -import org.ow2.authzforce.xacml.json.model.XacmlJsonUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.ITestContext; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import javax.xml.bind.JAXBException; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.nio.file.DirectoryStream; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.AbstractMap; import java.util.Arrays; @@ -44,8 +32,21 @@ import java.util.Map.Entry; import java.util.stream.Collectors; -public class XacmlJsonSchemaValidationTest -{ +import jakarta.xml.bind.JAXBException; +import org.everit.json.schema.Schema; +import org.everit.json.schema.ValidationException; +import org.json.JSONObject; +import org.ow2.authzforce.xacml.Xacml3JaxbHelper; +import org.ow2.authzforce.xacml.json.model.LimitsCheckingJSONObject; +import org.ow2.authzforce.xacml.json.model.XacmlJsonUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.ITestContext; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class XacmlJsonSchemaValidationTest { private static final Logger LOGGER = LoggerFactory.getLogger(XacmlJsonSchemaValidationTest.class); private static final int MAX_JSON_STRING_LENGTH = 65536; @@ -61,37 +62,35 @@ public class XacmlJsonSchemaValidationTest * Source XACML/JSON files (not generated from XACML/XML files) */ private static final String[] SRC_XACML_JSON_DATA_DIRECTORY_LOCATIONS = { "src/test/resources/xacml+json.samples/Policies", "src/test/resources/xacml+json.samples/Requests", - "src/test/resources/xacml+json.samples/Responses" }; + "src/test/resources/xacml+json.samples/Responses" }; private static final String[] SRC_XACML_XML_CONFORMANCE_TEST_DATA_PARENT_DIRECTORY_LOCATIONS = { "src/test/resources/xacml+xml.samples/xacml-3.0-ct/mandatory", - "src/test/resources/xacml+xml.samples/xacml-3.0-ct/optional" }; + "src/test/resources/xacml+xml.samples/xacml-3.0-ct/optional" }; private static final String[] GEN_XACML_XML_CONFORMANCE_TEST_DATA_PARENT_DIRECTORY_LOCATIONS = { "target/generated-test-resources/xacml-xslt-outputs/xacml-3.0-ct/mandatory", - "target/generated-test-resources/xacml-xslt-outputs/xacml-3.0-ct/optional" }; + "target/generated-test-resources/xacml-xslt-outputs/xacml-3.0-ct/optional" }; /** * Create test data. Various Requests/Responses in XACML JSON Profile defined format - * - * + * + * * @return iterator over test data */ @DataProvider(name = "xacmlJsonDataProvider") - public Iterator createData() - { + public Iterator createData() { final List> testDataDirLocations = Arrays.stream(SRC_XACML_JSON_DATA_DIRECTORY_LOCATIONS).map(loc -> new AbstractMap.SimpleImmutableEntry<>(new File(loc), (File) null)) - .collect(Collectors.toList()); - for (int i = 0; i < GEN_XACML_XML_CONFORMANCE_TEST_DATA_PARENT_DIRECTORY_LOCATIONS.length; i++) - { + .collect(Collectors.toList()); + for (int i = 0; i < GEN_XACML_XML_CONFORMANCE_TEST_DATA_PARENT_DIRECTORY_LOCATIONS.length; i++) { final String loc = GEN_XACML_XML_CONFORMANCE_TEST_DATA_PARENT_DIRECTORY_LOCATIONS[i]; - try - { + try { final int testDataParentDirIndex = i; - Files.newDirectoryStream(Paths.get(loc)).forEach(testDataDirPath -> testDataDirLocations.add(new AbstractMap.SimpleImmutableEntry<>(testDataDirPath.toFile(), - new File(SRC_XACML_XML_CONFORMANCE_TEST_DATA_PARENT_DIRECTORY_LOCATIONS[testDataParentDirIndex], testDataDirPath.getFileName().toString())))); + try (DirectoryStream dirStream = Files.newDirectoryStream(Paths.get(loc))) { + dirStream.forEach(testDataDirPath -> testDataDirLocations.add(new AbstractMap.SimpleImmutableEntry<>(testDataDirPath.toFile(), + new File(SRC_XACML_XML_CONFORMANCE_TEST_DATA_PARENT_DIRECTORY_LOCATIONS[testDataParentDirIndex], testDataDirPath.getFileName().toString())))); + } i++; } - catch (final IOException e) - { + catch (final IOException e) { throw new RuntimeException("I/O error opening location '" + loc + "' as directory to iterate over its entries", e); } } @@ -100,7 +99,7 @@ public Iterator createData() } /** - * + * * @param xacmlJsonFile XACML/JSON file * @param expectedXacmlXmlFile expected XACML/XML file from conversion of {@code xacmlJsonFile} * @param expectedValid @@ -114,50 +113,40 @@ public Iterator createData() */ @Test(dataProvider = "xacmlJsonDataProvider") public void validateXacmlJson(final File xacmlJsonFile, final boolean expectedValid, final File expectedXacmlXmlFile, final File actualXacmlXmlFile, final ITestContext testCtx) - throws IOException, JAXBException - { + throws IOException, JAXBException { /* * Read properly as UTF-8 to avoid character decoding issues with org.json API */ - try (final BufferedReader reader = Files.newBufferedReader(xacmlJsonFile.toPath(), StandardCharsets.UTF_8)) - { + try (final BufferedReader reader = Files.newBufferedReader(xacmlJsonFile.toPath(), StandardCharsets.UTF_8)) { final JSONObject json = new LimitsCheckingJSONObject(reader, MAX_JSON_STRING_LENGTH, MAX_JSON_CHILDREN_COUNT, MAX_JSON_DEPTH); final Schema schema; final JSONObject jsonToValidate; - if (json.has("Request")) - { + if (json.has("Request")) { schema = XacmlJsonUtils.REQUEST_SCHEMA; jsonToValidate = json; } - else if (json.has("Response")) - { + else if (json.has("Response")) { schema = XacmlJsonUtils.RESPONSE_SCHEMA; jsonToValidate = json; } - else if (json.has("policy")) - { + else if (json.has("policy")) { schema = XacmlJsonUtils.POLICY_SCHEMA; jsonToValidate = json.getJSONObject("policy"); } - else - { + else { throw new IllegalArgumentException("Invalid XACML JSON file. Expected root key: \"Request\" or \"Response\" or \"policy\""); } - try - { + try { schema.validate(jsonToValidate); // throws a ValidationException if this object is invalid - if (!expectedValid) - { + if (!expectedValid) { Assert.fail("Validation against JSON schema succeeded but expected to fail"); } } - catch (final ValidationException e) - { + catch (final ValidationException e) { LOGGER.error("Error validating JSON file: '{}'\n{}", xacmlJsonFile, e.toJSON().toString(2)); - if (expectedValid) - { + if (expectedValid) { Assert.fail("Validation against JSON schema failed but expected to pass"); } } @@ -165,8 +154,7 @@ else if (json.has("policy")) /* * Validation of XACML/XML output from JSON-to-XML XSLT if any */ - if (actualXacmlXmlFile != null) - { + if (actualXacmlXmlFile != null) { final Object expectedXacmlJaxbObj = Xacml3JaxbHelper.createXacml3Unmarshaller().unmarshal(expectedXacmlXmlFile); final Object actualXacmlJaxbObj = Xacml3JaxbHelper.createXacml3Unmarshaller().unmarshal(actualXacmlXmlFile); Assert.assertEquals(actualXacmlJaxbObj, expectedXacmlJaxbObj, "Source XACML/XML file and generated XACML/XML file after XML->JSON->XML (XSLT) conversion do not match");