diff options
author | Vijay Venkatesh Kumar <vv770d@att.com> | 2019-03-27 23:56:21 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@onap.org> | 2019-03-27 23:56:21 +0000 |
commit | b7fccfde3f8dddf27310b4d14770fd2e0824875f (patch) | |
tree | ee63a1c111623e72b869caa73c10327e2d4b256a /standardization/api-custom-header | |
parent | 999a1d92f3f30156501186bc4b9407bb6913db67 (diff) | |
parent | dc478d6c91264f483c6dfb79cf1ff80a12eb1be2 (diff) |
Merge "api custom header Issue-ID: DCAEGEN2-897"
Diffstat (limited to 'standardization/api-custom-header')
7 files changed, 596 insertions, 0 deletions
diff --git a/standardization/api-custom-header/pom.xml b/standardization/api-custom-header/pom.xml new file mode 100644 index 00000000..6b00d06c --- /dev/null +++ b/standardization/api-custom-header/pom.xml @@ -0,0 +1,45 @@ +<?xml version="1.0"?> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.onap.dcaegen2.services.sdk</groupId> + <artifactId>dcaegen2-services-sdk-standardization</artifactId> + <version>1.1.3-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + + <groupId>org.onap.dcaegen2.services.sdk.standardization</groupId> + <artifactId>api-custom-header</artifactId> + <name>api-custom-header</name> + <packaging>jar</packaging> + + <properties> + <java.version>8</java.version> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.8.5</version> + </dependency> + <dependency> + <groupId>org.jetbrains</groupId> + <artifactId>annotations</artifactId> + </dependency> + <!-- TESTING --> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/standardization/api-custom-header/src/main/java/org/onap/dcaegen2/services/sdk/standardization/header/ApiVersionManagement.java b/standardization/api-custom-header/src/main/java/org/onap/dcaegen2/services/sdk/standardization/header/ApiVersionManagement.java new file mode 100644 index 00000000..06515dca --- /dev/null +++ b/standardization/api-custom-header/src/main/java/org/onap/dcaegen2/services/sdk/standardization/header/ApiVersionManagement.java @@ -0,0 +1,141 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.services.sdk + * ================================================================================ + * Copyright (C) 2019 vmware. 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.standardization.header; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.onap.dcaegen2.services.sdk.standardization.util.ObjectManagement; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.google.gson.Gson; + +public final class ApiVersionManagement { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApiVersionManagement.class); + private static final Object INSTANCE = new Object(); + private static final String API_VERSION = "apiVersion"; + + private static Map<String, List<ApiVersionModel>> verModelMap; + + /** + * private constructor + */ + private ApiVersionManagement() { + + } + + /** + * get api version from json string + * + * @param apiFilePath api file path + * @param requestedApiName current api name + * @return all api version for a major version + */ + public static List<ApiVersionModel> getApiVersion(String apiFilePath, String requestedApiName) { + if (null != verModelMap) { + List<ApiVersionModel> apiLst = verModelMap.get(requestedApiName); + return ObjectManagement.isCollectionEmpty(apiLst) ? Collections.emptyList() + : Collections.unmodifiableList(apiLst); + } + + synchronized (INSTANCE) { + if (null == verModelMap) { + verModelMap = new HashMap<>(); + String apiVerJsonStr = readApiVersions(apiFilePath); + + // component not pass the apiversion parameter + if (apiVerJsonStr.isEmpty()) { + return Collections.emptyList(); + } + + // read service or resource api and put in HashMap one by one. + convertVerToModel(parseApiVersion(apiVerJsonStr)); + } + } + + List<ApiVersionModel> apiLst = verModelMap.get(requestedApiName); + return ObjectManagement.isCollectionEmpty(apiLst) ? Collections.emptyList() + : Collections.unmodifiableList(verModelMap.get(requestedApiName)); + } + + /** + * parse api versions from api json string + * + * @param apiVerJsonStr all api versions in json format + * @return api versions<apikey, List<version>> in map format + */ + private static Map<String, Object> parseApiVersion(String apiVerJsonStr) { + Map<String, Object> apiMap = new Gson().fromJson(apiVerJsonStr, Map.class); + if (apiMap.containsKey(API_VERSION)) { + return apiMap; + } + + // there is no apiVersion filed in apiVerJsonStr or the format is wrong. + LOGGER.error("the struct of api version is wrong, so return the empty api map."); + return Collections.emptyMap(); + } + + /** + * convert api version into ApiVersionModel object + * + * @param apiMap Map object for all api versions + */ + private static void convertVerToModel(Map<String, Object> apiMap) { + if (apiMap.isEmpty()) { + verModelMap = Collections.emptyMap(); + return; + } + + List<Object> currApiArray = null; + Map<String, Object> apiVersMap = (apiMap.get(API_VERSION) instanceof Map) ? (Map) apiMap.get(API_VERSION) : null; + if (null != apiVersMap) { + for (Map.Entry<String, Object> entry : apiVersMap.entrySet()) { + currApiArray = (entry.getValue() instanceof List) ? (List) entry.getValue() : null; + if (null != currApiArray) { + List<ApiVersionModel> currApiLst = new ArrayList<>(); + currApiArray.forEach(currApi -> currApiLst.add(new ApiVersionModel(currApi.toString()))); + verModelMap.put(entry.getKey(), currApiLst); + } + } + } + } + + /** + * read api version from path + * + * @param filePath api versions + * @return api versions json string + */ + private static String readApiVersions(String filePath) { + try { + return new String(Files.readAllBytes(Paths.get(filePath))); + } catch (IOException e) { + LOGGER.error("Fail to read api version file", e); + } + + return ""; + } +}
\ No newline at end of file diff --git a/standardization/api-custom-header/src/main/java/org/onap/dcaegen2/services/sdk/standardization/header/ApiVersionModel.java b/standardization/api-custom-header/src/main/java/org/onap/dcaegen2/services/sdk/standardization/header/ApiVersionModel.java new file mode 100644 index 00000000..d3c09a2b --- /dev/null +++ b/standardization/api-custom-header/src/main/java/org/onap/dcaegen2/services/sdk/standardization/header/ApiVersionModel.java @@ -0,0 +1,53 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.services.sdk + * ================================================================================ + * Copyright (C) 2019 vmware. 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.standardization.header; + +public class ApiVersionModel { + private String majorVersion; + private String minorVersion; + private String patchVersion; + private String version; + + public ApiVersionModel(String version) { + this.version = version; + if (null != version) { + String[] verArray = version.split("\\."); + majorVersion = verArray[0]; + minorVersion = verArray.length > 1 ? verArray[1] : null; + patchVersion = verArray.length > 2 ? verArray[2] : null; + } + } + + public String getMajorVersion() { + return majorVersion; + } + + public String getMinorVersion() { + return minorVersion; + } + + public String getPatchVersion() { + return patchVersion; + } + + public String getVersion() { + return version; + } +}
\ No newline at end of file diff --git a/standardization/api-custom-header/src/main/java/org/onap/dcaegen2/services/sdk/standardization/header/CustomHeaderUtils.java b/standardization/api-custom-header/src/main/java/org/onap/dcaegen2/services/sdk/standardization/header/CustomHeaderUtils.java new file mode 100644 index 00000000..ecd08314 --- /dev/null +++ b/standardization/api-custom-header/src/main/java/org/onap/dcaegen2/services/sdk/standardization/header/CustomHeaderUtils.java @@ -0,0 +1,222 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.services.sdk + * ================================================================================ + * Copyright (C) 2019 vmware. 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.standardization.header; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.jetbrains.annotations.NotNull; +import org.onap.dcaegen2.services.sdk.standardization.util.ObjectManagement; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CustomHeaderUtils { + + private static final Logger logger = LoggerFactory.getLogger(CustomHeaderUtils.class); + + /** + * more detail: + * https://wiki.onap.org/display/DW/ONAP+API+Common+Versioning+Strategy+%28CVS%29+Guidelines + */ + private static final String API_MINOR_VERSION = "X-MinorVersion"; + private static final String API_PATCH_VERSION = "X-PatchVersion"; + private static final String API_LATEST_VERSION = "X-LatestVersion"; + + /** + * identify whether validate minor version successfully + */ + private static final ThreadLocal<Boolean> CLIENT_MINOR_VERSION_OK = new ThreadLocal<>(); + private String majorVersion = null; + private String minorVersion = null; + private List<ApiVersionModel> verLst = null; + + /** + * construct + * + * @param requestMajorVer client request major version + * @param reqHeaderMap request headers + * @param apiFilePath api file path + * @param requestedApiName api name that is requested by client + * + */ + public CustomHeaderUtils(@NotNull String requestMajorVer, @NotNull Map<String, String> reqHeaderMap, + @NotNull String apiFilePath, @NotNull String requestedApiName) { + // all api versions + if (!requestedApiName.isEmpty()) { + verLst = ApiVersionManagement.getApiVersion(apiFilePath, requestedApiName); + } + + // major version that client requests + this.majorVersion = requestMajorVer; + + // minor version that client requests + this.minorVersion = reqHeaderMap.get(API_MINOR_VERSION); + + CLIENT_MINOR_VERSION_OK.set(Boolean.TRUE); + } + + /** + * get the custom headers of response + * + * @return rspHeader custom headers of response + */ + public Map<String, String> getRspCustomHeader() { + try { + return calCustomHeader(); + } finally { + CLIENT_MINOR_VERSION_OK.remove(); + } + } + + /** + * calculate the custom header for response + * + * @return rspHeader custom headers of response + */ + private Map<String, String> calCustomHeader() { + if (ObjectManagement.isCollectionEmpty(this.verLst)) { + logger.warn("there is no api version configured in server."); + return new HashMap<>(); + } + + // if client not send X-MinorVersion, return the first minor version that major version is requested + if (ObjectManagement.isStringEmpty(this.minorVersion)) { + return calHeadersNoMinorVer(); + } + + // if client send x-MinorVersion, minor vefrsion is wrong + if (!CLIENT_MINOR_VERSION_OK.get()) { + return calHeadersWithWrongMinorVer(); + } + + // client send X-MinorVersion and minor version is right + return calHeadersWithMinorVer(); + } + + /** + * calculate the custom header should be returned when client send minor version which is wrong + * + * @return rspHeader custom headers of response + */ + private Map<String, String> calHeadersWithWrongMinorVer() { + Map<String, String> rspHeader = new HashMap<>(3); + + // Latest version mean greatest version + rspHeader.put(API_LATEST_VERSION, this.verLst.get(verLst.size() - 1).getVersion()); + + ApiVersionModel currVer = null; + for (int index = 0; index < this.verLst.size(); index++) { + if (this.majorVersion.equals(this.verLst.get(index).getMajorVersion())) { + currVer = this.verLst.get(index); + } else { + if (null != currVer) { + break; + } + } + } + + if (null == currVer) { + logger.warn("wrong apiVersiona are provided, major {} not foud in them", this.majorVersion); + } else { + rspHeader.put(API_MINOR_VERSION, currVer.getMinorVersion()); + rspHeader.put(API_PATCH_VERSION, currVer.getPatchVersion()); + } + + return rspHeader; + } + + /** + * calculate the custom header should be returned when client send minor version which is right + * + * @return rspHeader custom headers of response + */ + private Map<String, String> calHeadersWithMinorVer() { + Map<String, String> rspHeader = new HashMap<>(3); + + // Latest version mean greatest version + rspHeader.put(API_LATEST_VERSION, this.verLst.get(verLst.size() - 1).getVersion()); + + // set minor version + rspHeader.put(API_MINOR_VERSION, this.minorVersion); + + // set patch version + ApiVersionModel currVer = null; + for (int index = 0; index < this.verLst.size(); index++) { + currVer = verLst.get(index); + if (this.majorVersion.equals(currVer.getMajorVersion()) && this.minorVersion.equals(currVer.getMinorVersion())) { + rspHeader.put(API_PATCH_VERSION, currVer.getPatchVersion()); + break; + } + } + + return rspHeader; + } + + /** + * calculate the custom header should be returned when client not send minor version + * + * @return rspHeader custom headers of response + */ + private Map<String, String> calHeadersNoMinorVer() { + Map<String, String> rspHeader = new HashMap<>(3); + + // Latest version mean greatest version + rspHeader.put(API_LATEST_VERSION, this.verLst.get(verLst.size() - 1).getVersion()); + + // the first version of major version + ApiVersionModel currVer = null; + for (int index = 0; index < this.verLst.size(); index++) { + currVer = verLst.get(index); + if (this.majorVersion.equals(currVer.getMajorVersion())) { + rspHeader.put(API_MINOR_VERSION, currVer.getMinorVersion()); + rspHeader.put(API_PATCH_VERSION, currVer.getPatchVersion()); + break; + } + } + + return rspHeader; + } + + /** + * Check header whether it is right. + * + * @return true when validating successfully or minor version not exist + */ + public boolean isOkCustomHeaders() { + if (ObjectManagement.isStringEmpty(this.minorVersion)) { + logger.warn("X-MinorVersion is empty or null"); + return true; + } + + ApiVersionModel currVer = null; + + // verList is an order array, which is from the first version to the latest version. + for (int index = 0; index < this.verLst.size(); index++) { + currVer = verLst.get(index); + if (currVer.getMajorVersion().equals(this.majorVersion) && currVer.getMinorVersion().equals(this.minorVersion)) { + return true; + } + } + + logger.error("not find major version {} and minor version {}", this.majorVersion, this.minorVersion); + CLIENT_MINOR_VERSION_OK.set(Boolean.FALSE); + return false; + } +}
\ No newline at end of file diff --git a/standardization/api-custom-header/src/main/java/org/onap/dcaegen2/services/sdk/standardization/util/ObjectManagement.java b/standardization/api-custom-header/src/main/java/org/onap/dcaegen2/services/sdk/standardization/util/ObjectManagement.java new file mode 100644 index 00000000..3f173d31 --- /dev/null +++ b/standardization/api-custom-header/src/main/java/org/onap/dcaegen2/services/sdk/standardization/util/ObjectManagement.java @@ -0,0 +1,53 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.services.sdk + * ================================================================================ + * Copyright (C) 2019 vmware. 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.standardization.util; + + +import java.util.Collection; + +public final class ObjectManagement { + + /** + * constructor that not permit to new object + */ + private ObjectManagement() { + + } + + /** + * check string object if it is empty + * + * @param str string object + * @return true when str is null or empty + */ + public static boolean isStringEmpty(String str) { + return null == str || str.isEmpty(); + } + + /** + * check collection object if it is empty + * + * @param c collection object + * @return true when c is null or empty + */ + public static boolean isCollectionEmpty(Collection<?> c) { + return null == c || c.isEmpty(); + } +}
\ No newline at end of file diff --git a/standardization/api-custom-header/src/test/java/org/onap/dcaegen2/services/sdk/standardization/header/CustomHeaderUtilsTest.java b/standardization/api-custom-header/src/test/java/org/onap/dcaegen2/services/sdk/standardization/header/CustomHeaderUtilsTest.java new file mode 100644 index 00000000..73fcec1a --- /dev/null +++ b/standardization/api-custom-header/src/test/java/org/onap/dcaegen2/services/sdk/standardization/header/CustomHeaderUtilsTest.java @@ -0,0 +1,75 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.services.sdk + * ================================================================================ + * Copyright (C) 2019 vmware. 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.standardization.header; + +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class CustomHeaderUtilsTest { + private String filePath = getClass().getClassLoader().getResource("api_version_config.json").getPath(); + + /** + * not send minor version when client requests + */ + @Test + void testRequestNoMinorVer() { + CustomHeaderUtils util = getHeaderUtil(null); + util.isOkCustomHeaders(); + + Map<String, String> rspHeaders = util.getRspCustomHeader(); + Assertions.assertTrue("3".equals(rspHeaders.get("X-MinorVersion"))); + } + + /** + * minor version not exist which client request + */ + @Test + void testRequestWithWrongMinorVer() { + CustomHeaderUtils util = getHeaderUtil("2"); + + // check request header + util.isOkCustomHeaders(); + + Assertions.assertFalse(util.isOkCustomHeaders()); + + Map<String, String> rspHeaders = util.getRspCustomHeader(); + Assertions.assertTrue("4".equals(rspHeaders.get("X-MinorVersion"))); + } + + /** + * minor version exists which client request + */ + @Test + void testRequestWithMinorVerOk() { + CustomHeaderUtils util = getHeaderUtil("3"); + Assertions.assertFalse(!util.isOkCustomHeaders()); + + Map<String, String> rspHeaders = util.getRspCustomHeader(); + Assertions.assertTrue("3".equals(rspHeaders.get("X-MinorVersion"))); + } + + private CustomHeaderUtils getHeaderUtil(String minorVer) { + Map<String, String> reqHeaderMap = new HashMap<String, String>(); + reqHeaderMap.put("X-MinorVersion", minorVer); + return new CustomHeaderUtils("5", reqHeaderMap, filePath, "eventListener"); + } +}
\ No newline at end of file diff --git a/standardization/api-custom-header/src/test/resources/api_version_config.json b/standardization/api-custom-header/src/test/resources/api_version_config.json new file mode 100644 index 00000000..81468ac4 --- /dev/null +++ b/standardization/api-custom-header/src/test/resources/api_version_config.json @@ -0,0 +1,7 @@ +{ + "apiVersion": + { + "eventListener": ["4.7.2","5.3.2","5.4.1","7.0.1"], + "xxxxxx": ["1.0.2","1.1.2","2.0.1"] + } +}
\ No newline at end of file |