diff options
Diffstat (limited to 'services/external-schema-manager/src/main/java')
12 files changed, 767 insertions, 2 deletions
diff --git a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/exception/IncorrectInternalFileReferenceException.java b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/exception/IncorrectInternalFileReferenceException.java new file mode 100644 index 00000000..32617567 --- /dev/null +++ b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/exception/IncorrectInternalFileReferenceException.java @@ -0,0 +1,29 @@ +/* + * ============LICENSE_START======================================================= + * DCAEGEN2-SERVICES-SDK + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.services.sdk.services.external.schema.manager.exception; + +public class IncorrectInternalFileReferenceException extends RuntimeException { + + public IncorrectInternalFileReferenceException(String message) { + super(message); + } + +} diff --git a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/externalschemamanager/Main.java b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/exception/NoLocalReferenceException.java index c60cff39..f51ff2e6 100644 --- a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/externalschemamanager/Main.java +++ b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/exception/NoLocalReferenceException.java @@ -18,7 +18,12 @@ * ============LICENSE_END========================================================= */ -package org.onap.dcaegen2.services.sdk.services.externalschemamanager; +package org.onap.dcaegen2.services.sdk.services.external.schema.manager.exception; + +public class NoLocalReferenceException extends RuntimeException { + + public NoLocalReferenceException(String message) { + super(message); + } -public class Main { } diff --git a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/model/SchemaReference.java b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/model/SchemaReference.java new file mode 100644 index 00000000..5da34430 --- /dev/null +++ b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/model/SchemaReference.java @@ -0,0 +1,58 @@ +/* + * ============LICENSE_START======================================================= + * DCAEGEN2-SERVICES-SDK + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.services.sdk.services.external.schema.manager.model; + +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.service.SchemaReferenceResolver; + +public class SchemaReference { + + public static final String URL_SEPARATOR = "#"; + + private final String url; + private final String internalReference; + + public SchemaReference(SchemaReferenceResolver schemaReferenceResolver) { + this.url = schemaReferenceResolver.resolveUrl(); + this.internalReference = schemaReferenceResolver.resolveInternalReference(); + } + + public SchemaReference(String url, String internalReference) { + this.url = url; + this.internalReference = internalReference; + } + + public String getUrl() { + return url; + } + + public String getInternalReference() { + return internalReference; + } + + /** + * Creates full schema reference as <path to yaml file>#<reference to part of yaml file with specific schema> + * + * @return <path to yaml file>#<reference to part of yaml file with specific schema> + */ + public String getFullSchemaReference() { + return url + URL_SEPARATOR + internalReference; + } +} diff --git a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/FileReader.java b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/FileReader.java new file mode 100644 index 00000000..e49266e3 --- /dev/null +++ b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/FileReader.java @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START======================================================= + * DCAEGEN2-SERVICES-SDK + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.services.sdk.services.external.schema.manager.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +class FileReader { + + private static final Logger logger = LoggerFactory.getLogger(FileReader.class); + + private final String filename; + + FileReader(String filename) { + this.filename = filename; + } + + String readFile() { + String fileContent = ""; + try { + fileContent = getFileContent(); + } catch (IOException e) { + logger.error("Error while reading file. Filename: {}", filename); + } + return fileContent; + } + + boolean doesFileExists() { + return new File(filename).exists(); + } + + private String getFileContent() throws IOException { + return new String(readBytes()); + } + + private byte[] readBytes() throws IOException { + return Files.readAllBytes(Paths.get(filename)); + } +}
\ No newline at end of file diff --git a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/JsonFragmentRetriever.java b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/JsonFragmentRetriever.java new file mode 100644 index 00000000..71f300fc --- /dev/null +++ b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/JsonFragmentRetriever.java @@ -0,0 +1,33 @@ +/* + * ============LICENSE_START======================================================= + * DCAEGEN2-SERVICES-SDK + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.services.sdk.services.external.schema.manager.service; + +import com.fasterxml.jackson.databind.JsonNode; + +final class JsonFragmentRetriever { + + private JsonFragmentRetriever() { + } + + static JsonNode getFragment(JsonNode event, String fragmentPath) { + return event.at(fragmentPath); + } +} diff --git a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/SchemaReferenceJsonGenerator.java b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/SchemaReferenceJsonGenerator.java new file mode 100644 index 00000000..50ca6421 --- /dev/null +++ b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/SchemaReferenceJsonGenerator.java @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START======================================================= + * DCAEGEN2-SERVICES-SDK + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.services.sdk.services.external.schema.manager.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.model.SchemaReference; + +import java.io.IOException; + +final class SchemaReferenceJsonGenerator { + + private SchemaReferenceJsonGenerator() { + } + + static JsonNode getSchemaReferenceJson(SchemaReference schemaReference) throws IOException { + return toJsonNode(getReferenceJson(schemaReference)); + } + + private static JsonNode toJsonNode(String content) throws IOException { + return new ObjectMapper().readTree(content); + } + + private static String getReferenceJson(SchemaReference url) { + return "{\"$ref\":\"" + url.getFullSchemaReference() + "\"}"; + } +} diff --git a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/SchemaReferenceMapper.java b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/SchemaReferenceMapper.java new file mode 100644 index 00000000..79108f01 --- /dev/null +++ b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/SchemaReferenceMapper.java @@ -0,0 +1,55 @@ +/* + * ============LICENSE_START======================================================= + * DCAEGEN2-SERVICES-SDK + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.services.sdk.services.external.schema.manager.service; + +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.model.SchemaReference; + +import java.io.File; + +class SchemaReferenceMapper { + + private final UrlMapper urlMapper; + private final String schemasPath; + + SchemaReferenceMapper(UrlMapper urlMapper, String schemasPath) { + this.urlMapper = urlMapper; + this.schemasPath = schemasPath; + } + + UrlMapper getUrlMapper() { + return urlMapper; + } + + SchemaReference mapToLocalSchema(SchemaReference schemaReference) { + String publicUrl = schemaReference.getUrl(); + String localUrl = urlMapper.mapToLocalUrl(publicUrl); + return createLocalSchemaReference(localUrl, schemaReference.getInternalReference()); + } + + private SchemaReference createLocalSchemaReference(String localUrl, String internalReference) { + String relativeLocalUrl = getRelativeLocalUrl(localUrl); + return new SchemaReference(relativeLocalUrl, internalReference); + } + + private String getRelativeLocalUrl(String localUrl) { + return schemasPath + File.separator + localUrl; + } +} diff --git a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/SchemaReferenceResolver.java b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/SchemaReferenceResolver.java new file mode 100644 index 00000000..0dd1b805 --- /dev/null +++ b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/SchemaReferenceResolver.java @@ -0,0 +1,81 @@ +/* + * ============LICENSE_START======================================================= + * DCAEGEN2-SERVICES-SDK + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.services.sdk.services.external.schema.manager.service; + +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.model.SchemaReference; + + +public class SchemaReferenceResolver { + + private static final String ROOT_REFERENCE = "/"; + private static final int URL_INDEX = 0; + private static final int INTERNAL_REFERENCE_INDEX = 1; + private static final int REFERENCE_FRAGMENTS_CONTAINING_INTERNAL_REF_SIZE = 2; + + private final String schemaReference; + + public SchemaReferenceResolver(String schemaReference) { + this.schemaReference = schemaReference; + } + + /** + * Extracts the schema reference fragment, provided in the event, corresponding to the url path (before #). + * + * @return url path + */ + public String resolveUrl() { + String[] referenceFragments = schemaReference.split(SchemaReference.URL_SEPARATOR); + return referenceFragments[URL_INDEX]; + } + + /** + * Returns internal reference (after #) if it is present in schema reference and add "/" on the beginning if it's + * not present, otherwise returns "/". + * + * @return resolved internal reference + */ + public String resolveInternalReference() { + String reference; + String[] referenceFragments = schemaReference.split(SchemaReference.URL_SEPARATOR); + if (internalReferenceExists(referenceFragments)) { + String internalReference = referenceFragments[INTERNAL_REFERENCE_INDEX]; + reference = prepareExistingInternalReference(internalReference); + } else { + reference = ROOT_REFERENCE; + } + + return reference; + } + + private boolean internalReferenceExists(String[] referenceFragments) { + return referenceFragments.length == REFERENCE_FRAGMENTS_CONTAINING_INTERNAL_REF_SIZE; + } + + private String prepareExistingInternalReference(String internalReference) { + return (!isAbsolute(internalReference)) ? ROOT_REFERENCE + internalReference : internalReference; + } + + private boolean isAbsolute(String internalReference) { + return internalReference.startsWith(ROOT_REFERENCE); + } + + +} diff --git a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/StndDefinedValidator.java b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/StndDefinedValidator.java new file mode 100644 index 00000000..0b343394 --- /dev/null +++ b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/StndDefinedValidator.java @@ -0,0 +1,151 @@ +/* + * ============LICENSE_START======================================================= + * DCAEGEN2-SERVICES-SDK + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.services.sdk.services.external.schema.manager.service; + +import com.fasterxml.jackson.databind.JsonNode; +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.exception.IncorrectInternalFileReferenceException; +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.exception.NoLocalReferenceException; +import org.openapi4j.core.validation.ValidationException; +import org.openapi4j.schema.validator.v3.SchemaValidator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; + +public class StndDefinedValidator { + private static final Logger logger = LoggerFactory.getLogger(StndDefinedValidator.class); + private final String schemaRefPath; + private final String stndDefinedDataPath; + private final ValidatorCache validatorCache; + + private StndDefinedValidator(String schemaRefPath, String stndDefinedDataPath, ValidatorCache validatorCache) { + this.schemaRefPath = schemaRefPath; + this.stndDefinedDataPath = stndDefinedDataPath; + this.validatorCache = validatorCache; + } + + ValidatorCache getValidatorCache() { + return validatorCache; + } + + /** + * Validates incoming event + * + * @param event as JsonNode + * @return validation result + * @throws IncorrectInternalFileReferenceException when reference to part of openApi yaml file with schemas is incorrect. + * @throws NoLocalReferenceException when mapping for public url is not present in schema mapping file. + */ + public boolean validate(JsonNode event) throws IncorrectInternalFileReferenceException, NoLocalReferenceException { + boolean validationResult = false; + try { + JsonNode stndDefinedData = JsonFragmentRetriever.getFragment(event, this.stndDefinedDataPath); + SchemaValidator schemaValidator = validatorCache.resolveValidator(event, schemaRefPath); + schemaValidator.validate(stndDefinedData); + logger.info("Validation of stndDefinedDomain has been successful"); + validationResult = true; + } catch (ValidationException ex) { + logger.error(String.valueOf(ex.results())); + } catch (IOException ex){ + logger.error("Schema reference has invalid characters", ex); + } + return validationResult; + } + + public static final class ValidatorBuilder { + + public static final String DEFAULT_MAPPING_FILE_PATH = "etc/externalRepo/schema-map.json"; + public static final String DEFAULT_SCHEMA_REF_PATH = "/event/stndDefinedFields/schemaReference"; + public static final String DEFAULT_STND_DEFINED_DATA_PATH = "/event/stndDefinedFields/data"; + public static final String DEFAULT_SCHEMAS_PATH = "etc/externalRepo"; + + private String mappingFilePath = DEFAULT_MAPPING_FILE_PATH; + private String schemaRefPath = DEFAULT_SCHEMA_REF_PATH; + private String stndDefinedDataPath = DEFAULT_STND_DEFINED_DATA_PATH; + private String schemasPath = DEFAULT_SCHEMAS_PATH; + + /** + * @param mappingFilePath relative path to the file with mappings of schemas from the context in which + * the application is running. + * @return builder reference + * @implNote example mapping file: + * [ + * { + * "publicURL": "http://localhost:8080/external1", + * "localURL": "rel-16.4/2020-07-10-3GPP_TS28532_FaultMNS.yaml" + * } + * ] + * @implNote default mapping file path: "etc/externalRepo/schema-map.json" + */ + public ValidatorBuilder mappingFilePath(String mappingFilePath) { + this.mappingFilePath = mappingFilePath; + return this; + } + + /** + * @param schemaRefPath schema reference path in json. + * @return builder reference + * @implNote default: "/event/stndDefinedFields/schemaReference" + */ + public ValidatorBuilder schemaRefPath(String schemaRefPath) { + this.schemaRefPath = schemaRefPath; + return this; + } + + /** + * @param stndDefinedDataPath path to stndDefined data in json. + * @return builder reference + * @implNote default: "/event/stndDefinedFields/data" + */ + public ValidatorBuilder stndDefinedDataPath(String stndDefinedDataPath) { + this.stndDefinedDataPath = stndDefinedDataPath; + return this; + } + + /** + * @param schemasPath relative path to schemas directory from the context in which the application is running. + * @return builder reference + * @implNote default: "etc/externalRepo" + */ + public ValidatorBuilder schemasPath(String schemasPath) { + this.schemasPath = new File(schemasPath).getAbsolutePath(); + return this; + } + + /** + * Builds stndDefined Validator. May log warnings when: + * - schema mapping file does not exist + * - schema mapping file has invalid format + * - any of schema files does not exist + * - any of schema files has invalid yaml format + * - any of schema files is empty + * + * @return stndDefinedValidator with cached schemas + */ + public StndDefinedValidator build() { + UrlMapper urlMapper = new UrlMapperFactory().getUrlMapper(mappingFilePath, schemasPath); + SchemaReferenceMapper schemaReferenceMapper = new SchemaReferenceMapper(urlMapper, schemasPath); + ValidatorCache validatorCache = new ValidatorCache(schemaReferenceMapper); + return new StndDefinedValidator(schemaRefPath, stndDefinedDataPath, validatorCache); + } + } +} diff --git a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/UrlMapper.java b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/UrlMapper.java new file mode 100644 index 00000000..06864b31 --- /dev/null +++ b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/UrlMapper.java @@ -0,0 +1,48 @@ +/* + * ============LICENSE_START======================================================= + * DCAEGEN2-SERVICES-SDK + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.services.sdk.services.external.schema.manager.service; + +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.exception.NoLocalReferenceException; + +import java.util.Map; + +final class UrlMapper { + + private final Map<String, String> mappingsCache; + + UrlMapper(Map<String, String> mappings) { + this.mappingsCache = Map.copyOf(mappings); + } + + Map<String, String> getMappingsCache() { + return Map.copyOf(mappingsCache); + } + + String mapToLocalUrl(String publicUrl) { + String externalUrl = mappingsCache.get(publicUrl); + if (externalUrl == null) { + throw new NoLocalReferenceException("Couldn't find mapping for public url. PublicURL: " + publicUrl); + } + return externalUrl; + } + + +}
\ No newline at end of file diff --git a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/UrlMapperFactory.java b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/UrlMapperFactory.java new file mode 100644 index 00000000..730bc17e --- /dev/null +++ b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/UrlMapperFactory.java @@ -0,0 +1,107 @@ +/* + * ============LICENSE_START======================================================= + * DCAEGEN2-SERVICES-SDK + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.services.sdk.services.external.schema.manager.service; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class UrlMapperFactory { + + private static final Logger logger = LoggerFactory.getLogger(UrlMapperFactory.class); + + UrlMapper getUrlMapper(String mappingFilePath, String schemasPath) { + Map<String, String> mappings = new HashMap<>(); + try { + mappings = readMappingFile(mappingFilePath, schemasPath); + } catch (IOException ex) { + logger.warn("Unable to read mapping file. Mapping file path: {}", mappingFilePath); + } catch (NullPointerException ex) { + mappings = Collections.emptyMap(); + logger.warn("Schema mapping file has incorrect format. Mapping file path: {}", mappingFilePath); + } + + return new UrlMapper(mappings); + } + + private Map<String, String> readMappingFile(String mappingFilePath, String schemasPath) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + FileReader fileReader = new FileReader(mappingFilePath); + Map<String, String> mappings = new HashMap<>(); + + for (JsonNode mapping : objectMapper.readTree(fileReader.readFile())) { + String localURL = mapping.get("localURL").asText(); + if (isMappingValid(schemasPath, localURL)) { + mappings.put(mapping.get("publicURL").asText(), localURL); + } else { + logger.warn("Mapping for publicURL ({}) will not be added to validator.", mapping.get("publicURL")); + } + } + return mappings; + } + + private boolean isMappingValid(String schemasPath, String localURL) throws IOException { + String schemaRelativePath = schemasPath + File.separator + localURL; + return doesLocalFileExist(schemaRelativePath) && isFileValidSchema(schemaRelativePath); + } + + private boolean isFileValidSchema(String schemaRelativePath) throws IOException { + String schemaContent = new FileReader(schemaRelativePath).readFile(); + return isNotEmpty(schemaContent, schemaRelativePath) && isYaml(schemaContent, schemaRelativePath); + } + + private boolean isNotEmpty(String schemaContent, String schemaRelativePath) { + if (schemaContent.isEmpty()) { + logger.warn("Schema file is empty. Schema path: {}", schemaRelativePath); + return false; + } + return true; + } + + private boolean isYaml(String schemaContent, String schemaRelativePath) throws IOException { + ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory()).findAndRegisterModules(); + try { + yamlMapper.readTree(schemaContent); + } catch (JsonParseException e) { + logger.warn("Schema has incorrect YAML structure. Schema path: {}", schemaRelativePath); + return false; + } + return true; + } + + private boolean doesLocalFileExist(String schemaRelativePath) { + FileReader fileReader = new FileReader(schemaRelativePath); + if (!fileReader.doesFileExists()) { + logger.warn("Local schema resource missing. Schema file with path {} has not been found.", schemaRelativePath); + return false; + } + return true; + } +} diff --git a/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/ValidatorCache.java b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/ValidatorCache.java new file mode 100644 index 00000000..e67f0ebc --- /dev/null +++ b/services/external-schema-manager/src/main/java/org/onap/dcaegen2/services/sdk/services/external/schema/manager/service/ValidatorCache.java @@ -0,0 +1,91 @@ +/* + * ============LICENSE_START======================================================= + * DCAEGEN2-SERVICES-SDK + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.services.sdk.services.external.schema.manager.service; + +import com.fasterxml.jackson.databind.JsonNode; +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.model.SchemaReference; +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.exception.IncorrectInternalFileReferenceException; +import org.openapi4j.core.exception.ResolutionException; +import org.openapi4j.schema.validator.v3.SchemaValidator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +class ValidatorCache { + + private static final Logger logger = LoggerFactory.getLogger(ValidatorCache.class); + private final SchemaReferenceMapper schemaReferenceMapper; + private final Map<String, SchemaValidator> cache; + + ValidatorCache(SchemaReferenceMapper schemaReferenceMapper) { + this.schemaReferenceMapper = schemaReferenceMapper; + this.cache = new HashMap<>(); + } + + SchemaReferenceMapper getSchemaReferenceMapper() { + return schemaReferenceMapper; + } + + synchronized SchemaValidator resolveValidator(JsonNode event, String schemaRefPath) throws IOException { + SchemaReference schemaReference = resolveSchemaReference(event, schemaRefPath); + schemaReference = schemaReferenceMapper.mapToLocalSchema(schemaReference); + SchemaValidator validator = cache.get(schemaReference.getUrl()); + if (!isValidatorCached(validator)) { + validator = createNewValidator(schemaReference); + } + return validator; + } + + private SchemaReference resolveSchemaReference(JsonNode event, String schemaRefPath) { + String publicSchemaReference = JsonFragmentRetriever.getFragment(event, schemaRefPath).asText(); + SchemaReferenceResolver schemaReferenceResolver = new SchemaReferenceResolver(publicSchemaReference); + return new SchemaReference(schemaReferenceResolver); + } + + private boolean isValidatorCached(SchemaValidator validator) { + return validator != null; + } + + private SchemaValidator createNewValidator(SchemaReference schemaReference) throws IOException { + logger.info("Creating new stndDefined schema validator"); + JsonNode schemaRefNode = SchemaReferenceJsonGenerator.getSchemaReferenceJson(schemaReference); + SchemaValidator schemaValidator = handleValidatorCreation(schemaRefNode); + cacheSchemaValidator(schemaReference.getFullSchemaReference(), schemaValidator); + return schemaValidator; + } + + private SchemaValidator handleValidatorCreation(JsonNode schemaNode) { + try { + return new SchemaValidator("StndDefinedSchemaValidator", schemaNode); + } catch (ResolutionException e) { + throw new IncorrectInternalFileReferenceException("Schema reference refer to existing file, " + + "but internal reference (after #) is incorrect. " + e.getMessage()); + } + } + + private void cacheSchemaValidator(String localSchemaReference, SchemaValidator schemaValidator) { + logger.info("Adding new stndDefined schema validator to cache"); + cache.put(localSchemaReference, schemaValidator); + } +} |