Enhance / fix REST resource resolution 70/81870/6
authorAlexis de Talhouët <adetalhouet89@gmail.com>
Fri, 8 Mar 2019 18:41:18 +0000 (13:41 -0500)
committerAlexis de Talhouët <adetalhouet89@gmail.com>
Mon, 11 Mar 2019 19:59:44 +0000 (15:59 -0400)
- provide sync web client
- add support for VERB
- add support for payload
- fix URI resolution from input-key-mapping

Change-Id: Id4f1973a15778ad4f2ab0f7e2a4b2c61054a234d
Issue-ID: CCSDK-1131
Signed-off-by: Alexis de Talhouët <adetalhouet89@gmail.com>
16 files changed:
components/model-catalog/definition-type/starter-type/node_type/source-rest.json
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/resource/resolution/ResourceSourceProperties.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt
ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/BluePrintRestLibConfiguration.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/BluePrintRestLibData.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/BluePrintRestLibPropertyService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/BlueprintWebClientService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/DME2ProxyRestClientService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/SSLBasicAuthRestClientService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/TokenAuthRestClientService.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/utils/WebClientUtils.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/RestClientServiceTest.kt

index 0449830..b28e934 100644 (file)
         }
       ]
     },
+    "verb": {
+      "required": false,
+      "type": "string",
+      "default": "GET",
+      "constraints": [
+        {
+          "valid_values": [
+            "GET", "POST", "DELETE", "PUT"
+          ]
+        }
+      ]
+    },
+    "payload": {
+      "required": false,
+      "type": "string",
+      "default": ""
+    },
     "endpoint-selector": {
       "required": false,
       "type": "string"
index 39be14c..ca4d631 100644 (file)
@@ -22,7 +22,13 @@ import org.onap.ccsdk.apps.blueprintsprocessor.db.primary.DBLibGenericService
 import org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.DatabaseResourceSource
 import org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR
 import org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils
-import org.onap.ccsdk.apps.controllerblueprints.core.*
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintTypes
+import org.onap.ccsdk.apps.controllerblueprints.core.checkEqualsOrThrow
+import org.onap.ccsdk.apps.controllerblueprints.core.checkNotEmpty
+import org.onap.ccsdk.apps.controllerblueprints.core.checkNotEmptyOrThrow
+import org.onap.ccsdk.apps.controllerblueprints.core.nullToEmpty
+import org.onap.ccsdk.apps.controllerblueprints.core.returnNotEmptyOrThrow
 import org.onap.ccsdk.apps.controllerblueprints.core.utils.JacksonUtils
 import org.onap.ccsdk.apps.controllerblueprints.resource.dict.ResourceAssignment
 import org.onap.ccsdk.apps.controllerblueprints.resource.dict.ResourceDictionaryConstants
@@ -91,7 +97,7 @@ open class DatabaseResourceAssignmentProcessor(private val dBLibGenericService:
     }
 
     private fun blueprintDBLibService(sourceProperties: DatabaseResourceSource): NamedParameterJdbcTemplate {
-        return if (checkNotEmpty(sourceProperties.endpointSelector!!)) {
+        return if (checkNotEmpty(sourceProperties.endpointSelector)) {
             val dbPropertiesJson = raRuntimeService.resolveDSLExpression(sourceProperties.endpointSelector!!)
             dBLibGenericService.remoteJdbcTemplate(dbPropertiesJson)
         } else {
index 37b4774..9bb1ea2 100644 (file)
@@ -19,9 +19,8 @@ package org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.pr
 
 import com.fasterxml.jackson.databind.node.ArrayNode
 import com.fasterxml.jackson.databind.node.JsonNodeFactory
-import com.fasterxml.jackson.databind.node.MissingNode
-import com.fasterxml.jackson.databind.node.NullNode
 import com.fasterxml.jackson.databind.node.ObjectNode
+import org.apache.commons.collections.MapUtils
 import org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR
 import org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.RestResourceSource
 import org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils
@@ -41,6 +40,7 @@ import org.slf4j.LoggerFactory
 import org.springframework.beans.factory.config.ConfigurableBeanFactory
 import org.springframework.context.annotation.Scope
 import org.springframework.stereotype.Service
+import java.util.*
 
 /**
  * RestResourceResolutionProcessor
@@ -63,11 +63,11 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
             validate(resourceAssignment)
 
             // Check if It has Input
-            val value = raRuntimeService.getInputValue(resourceAssignment.name)
-            if (value !is MissingNode && value !is NullNode) {
-                logger.info("primary-db source template key (${resourceAssignment.name}) found from input and value is ($value)")
+            try {
+                val value = raRuntimeService.getInputValue(resourceAssignment.name)
+                logger.info("rest source template key (${resourceAssignment.name}) found from input and value is ($value)")
                 ResourceAssignmentUtils.setResourceDataValue(resourceAssignment, raRuntimeService, value)
-            } else {
+            } catch (e: BluePrintProcessorException) {
                 val dName = resourceAssignment.dictionaryName
                 val dSource = resourceAssignment.dictionarySource
                 val resourceDefinition = resourceDictionaries[dName]
@@ -78,17 +78,22 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
                     checkNotNull(resourceSource.properties) { "failed to get source properties for $dName " }
                 val sourceProperties =
                     JacksonUtils.getInstanceFromMap(resourceSourceProperties, RestResourceSource::class.java)
-
-                val urlPath =
-                    checkNotNull(sourceProperties.urlPath) { "failed to get request urlPath for $dName under $dSource properties" }
                 val path = nullToEmpty(sourceProperties.path)
                 val inputKeyMapping =
                     checkNotNull(sourceProperties.inputKeyMapping) { "failed to get input-key-mappings for $dName under $dSource properties" }
+                val resolvedInputKeyMapping = populateInputKeyMappingVariables(inputKeyMapping)
+
+                // Resolving content Variables
+                val payload = resolveFromInputKeyMapping(nullToEmpty(sourceProperties.payload), resolvedInputKeyMapping)
+                val urlPath =
+                    resolveFromInputKeyMapping(checkNotNull(sourceProperties.urlPath), resolvedInputKeyMapping)
+                val verb = resolveFromInputKeyMapping(nullToEmpty(sourceProperties.verb), resolvedInputKeyMapping)
 
                 logger.info("$dSource dictionary information : ($urlPath), ($inputKeyMapping), (${sourceProperties.outputKeyMapping})")
                 // Get the Rest Client Service
                 val restClientService = blueprintWebClientService(resourceAssignment, sourceProperties)
-                val response = restClientService.getResource(urlPath, String::class.java)
+
+                val response = restClientService.exchangeResource(verb, urlPath, payload)
                 if (response.isBlank()) {
                     logger.warn("Failed to get $dSource result for dictionary name ($dName) using urlPath ($urlPath)")
                 } else {
@@ -104,8 +109,8 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
         }
     }
 
-    open fun blueprintWebClientService(resourceAssignment: ResourceAssignment,
-                                       restResourceSource: RestResourceSource): BlueprintWebClientService {
+    private fun blueprintWebClientService(resourceAssignment: ResourceAssignment,
+                                          restResourceSource: RestResourceSource): BlueprintWebClientService {
         return if (checkNotEmpty(restResourceSource.endpointSelector)) {
             val restPropertiesJson = raRuntimeService.resolveDSLExpression(restResourceSource.endpointSelector!!)
             blueprintRestLibPropertyService.blueprintWebClientService(restPropertiesJson)
@@ -181,6 +186,29 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
         }
     }
 
+    private fun populateInputKeyMappingVariables(inputKeyMapping: Map<String, String>): Map<String, Any> {
+        val resolvedInputKeyMapping = HashMap<String, Any>()
+        if (MapUtils.isNotEmpty(inputKeyMapping)) {
+            for ((key, value) in inputKeyMapping) {
+                val expressionValue = raRuntimeService.getResolutionStore(value).asText()
+                logger.trace("Reference dictionary key ({}), value ({})", key, expressionValue)
+                resolvedInputKeyMapping[key] = expressionValue
+            }
+        }
+        return resolvedInputKeyMapping
+    }
+
+    private fun resolveFromInputKeyMapping(valueToResolve: String, keyMapping: Map<String, Any>): String {
+        if (valueToResolve.isEmpty() || !valueToResolve.contains("$")) {
+            return valueToResolve
+        }
+        var res = valueToResolve
+        for (entry in keyMapping.entries) {
+            res = res.replace(("\\$" + entry.key).toRegex(), entry.value.toString())
+        }
+        return res
+    }
+
     @Throws(BluePrintProcessorException::class)
     private fun validate(resourceAssignment: ResourceAssignment) {
         checkNotEmptyOrThrow(resourceAssignment.name, "resource assignment template key is not defined")
index b5b126a..d55ccac 100644 (file)
@@ -24,7 +24,13 @@ import com.fasterxml.jackson.databind.ObjectMapper
 import com.fasterxml.jackson.databind.node.NullNode
 import com.fasterxml.jackson.databind.node.ObjectNode
 import org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.ResourceAssignmentRuntimeService
-import org.onap.ccsdk.apps.controllerblueprints.core.*
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintTypes
+import org.onap.ccsdk.apps.controllerblueprints.core.checkNotEmpty
+import org.onap.ccsdk.apps.controllerblueprints.core.checkNotEmptyOrThrow
+import org.onap.ccsdk.apps.controllerblueprints.core.nullToEmpty
+import org.onap.ccsdk.apps.controllerblueprints.core.returnNotEmptyOrThrow
 import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintRuntimeService
 import org.onap.ccsdk.apps.controllerblueprints.core.utils.JacksonUtils
 import org.onap.ccsdk.apps.controllerblueprints.resource.dict.ResourceAssignment
@@ -36,7 +42,6 @@ class ResourceAssignmentUtils {
         private val logger: EELFLogger = EELFManager.getInstance().getLogger(ResourceAssignmentUtils::class.toString())
 
         // TODO("Modify Value type from Any to JsonNode")
-        @Synchronized
         @Throws(BluePrintProcessorException::class)
         fun setResourceDataValue(resourceAssignment: ResourceAssignment,
                                  raRuntimeService: ResourceAssignmentRuntimeService, value: Any?) {
@@ -85,7 +90,6 @@ class ResourceAssignmentUtils {
 
         }
 
-        @Synchronized
         fun setFailedResourceDataValue(resourceAssignment: ResourceAssignment, message: String?) {
             if (checkNotEmpty(resourceAssignment.name)) {
                 resourceAssignment.updatedDate = Date()
@@ -95,7 +99,6 @@ class ResourceAssignmentUtils {
             }
         }
 
-        @Synchronized
         @Throws(BluePrintProcessorException::class)
         fun assertTemplateKeyValueNotNull(resourceAssignment: ResourceAssignment) {
             val resourceProp = checkNotNull(resourceAssignment.property) { "Failed to populate mandatory resource resource mapping $resourceAssignment" }
@@ -105,7 +108,6 @@ class ResourceAssignmentUtils {
             }
         }
 
-        @Synchronized
         @Throws(BluePrintProcessorException::class)
         fun generateResourceDataForAssignments(assignments: List<ResourceAssignment>): String {
             val result: String
@@ -139,10 +141,6 @@ class ResourceAssignmentUtils {
             return resourceAssignmentRuntimeService
         }
 
-        /*
-         * Populate the Field property type for the Data type
-         */
-        @Synchronized
         @Throws(BluePrintProcessorException::class)
         fun getPropertyType(raRuntimeService: ResourceAssignmentRuntimeService, dataTypeName: String, propertyName: String): String {
             lateinit var type: String
index f1d9789..009493a 100644 (file)
@@ -15,7 +15,8 @@
   ~  See the License for the specific language governing permissions and
   ~  limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.onap.ccsdk.apps.blueprintsprocessor</groupId>
             <groupId>org.onap.ccsdk.apps.blueprintsprocessor</groupId>
             <artifactId>core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${apache.httpcomponents.client.version}</version>
+        </dependency>
     </dependencies>
 
 </project>
index f63e39f..7af91c6 100644 (file)
@@ -30,6 +30,7 @@ open class BluePrintRestLibConfiguration
 class RestLibConstants {
     companion object {
         const val SERVICE_BLUEPRINT_REST_LIB_PROPERTY = "blueprint-rest-lib-property-service"
+        const val TYPE_TOKEN_AUTH = "token-auth"
         const val TYPE_BASIC_AUTH = "basic-auth"
         const val TYPE_SSL_BASIC_AUTH = "ssl-basic-auth"
         const val TYPE_DME2_PROXY = "dme2-proxy"
index 41e4545..dd4d9f7 100644 (file)
@@ -19,19 +19,23 @@ package org.onap.ccsdk.apps.blueprintsprocessor.rest
 open class RestClientProperties {
     lateinit var type: String
     lateinit var url: String
-    lateinit var userId: String
 }
 
 open class BasicAuthRestClientProperties : RestClientProperties() {
+    lateinit var password: String
+    lateinit var username: String
+}
+
+open class TokenAuthRestClientProperties : RestClientProperties() {
     var token: String? = null
 }
 
 open class SSLBasicAuthRestClientProperties : RestClientProperties() {
     lateinit var keyStoreInstance: String // JKS, PKCS12
     lateinit var sslTrust: String
-    lateinit var sslTrustPasswd: String
+    lateinit var sslTrustPassword: String
     lateinit var sslKey: String
-    lateinit var sslKeyPasswd: String
+    lateinit var sslKeyPassword: String
 }
 
 open class DME2RestClientProperties : RestClientProperties() {
index 130706d..0502f67 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2017-2018 AT&T Intellectual Property.
+ * Copyright © 2017-2019 AT&T, Bell Canada
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 package org.onap.ccsdk.apps.blueprintsprocessor.rest.service
 
+import org.apache.http.message.BasicHeader
 import org.onap.ccsdk.apps.blueprintsprocessor.rest.BasicAuthRestClientProperties
-import org.onap.ccsdk.apps.blueprintsprocessor.rest.utils.WebClientUtils
 import org.springframework.http.HttpHeaders
 import org.springframework.http.MediaType
-import org.springframework.web.reactive.function.BodyInserters
-import org.springframework.web.reactive.function.client.ExchangeFilterFunctions
-import org.springframework.web.reactive.function.client.WebClient
-
-
-class BasicAuthRestClientService(private val restClientProperties: BasicAuthRestClientProperties) : BlueprintWebClientService {
-
-    private var webClient: WebClient? = null
-
-    override fun webClient(): WebClient {
-        if (webClient == null) {
-            webClient = WebClient.builder()
-                    .baseUrl(restClientProperties.url)
-                    .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
-                    .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
-                    .filter(ExchangeFilterFunctions
-                            .basicAuthentication(restClientProperties.userId, restClientProperties.token))
-                    .filter(WebClientUtils.logRequest())
-                    .filter(WebClientUtils.logResponse())
-                    .build()
-        }
-        return webClient!!
-    }
-
-    override fun <T> getResource(path: String, responseType: Class<T>): T {
-        return getResource(path, null, responseType)
-    }
-
-    override fun <T> getResource(path: String, headers: Map<String, String>?, responseType: Class<T>): T {
-        return webClient().get()
-                .uri(path)
-                .headers { httpHeaders ->
-                    headers?.forEach {
-                        httpHeaders.set(it.key, it.value)
-                    }
-                }
-                .retrieve()
-                .bodyToMono(responseType).block()!!
-    }
-
-    override fun <T> postResource(path: String, request: Any, responseType: Class<T>): T {
-        return postResource(path, null, request, responseType)
+import java.nio.charset.Charset
+import java.util.*
+
+class BasicAuthRestClientService(private val restClientProperties: BasicAuthRestClientProperties) :
+    BlueprintWebClientService {
+
+    override fun headers(): Array<BasicHeader> {
+        val encodedCredentials = setBasicAuth(restClientProperties.username, restClientProperties.password)
+        val params = arrayListOf<BasicHeader>()
+        params.add(BasicHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))
+        params.add(BasicHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE))
+        params.add(BasicHeader(HttpHeaders.AUTHORIZATION, "Basic $encodedCredentials"))
+        return params.toTypedArray()
     }
 
-    override fun <T> postResource(path: String, headers: Map<String, String>?, request: Any, responseType: Class<T>): T {
-        return webClient().post()
-                .uri(path)
-                .headers { httpHeaders ->
-                    headers?.forEach {
-                        httpHeaders.set(it.key, it.value)
-                    }
-                }
-                .body(BodyInserters.fromObject(request))
-                .retrieve().bodyToMono(responseType).block()!!
+    override fun host(uri: String): String {
+        return restClientProperties.url + uri
     }
 
-    override fun <T> exchangeResource(methodType: String, path: String, request: Any, responseType: Class<T>): T {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    private fun setBasicAuth(username: String, password: String): String {
+        val credentialsString = "$username:$password"
+        return Base64.getEncoder().encodeToString(credentialsString.toByteArray(Charset.defaultCharset()))
     }
 }
\ No newline at end of file
index 705caa2..3888bb7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2017-2018 AT&T Intellectual Property.
+ * Copyright © 2017-2019 AT&T, Bell Canada
  * Modifications Copyright © 2019 IBM.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,7 +19,13 @@ package org.onap.ccsdk.apps.blueprintsprocessor.rest.service
 
 import com.fasterxml.jackson.databind.JsonNode
 import org.onap.ccsdk.apps.blueprintsprocessor.core.BluePrintProperties
-import org.onap.ccsdk.apps.blueprintsprocessor.rest.*
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.BasicAuthRestClientProperties
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.DME2RestClientProperties
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.PolicyManagerRestClientProperties
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.RestClientProperties
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.RestLibConstants
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.SSLBasicAuthRestClientProperties
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.TokenAuthRestClientProperties
 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintProcessorException
 import org.onap.ccsdk.apps.controllerblueprints.core.utils.JacksonUtils
 import org.springframework.stereotype.Service
@@ -27,6 +33,17 @@ import org.springframework.stereotype.Service
 @Service(RestLibConstants.SERVICE_BLUEPRINT_REST_LIB_PROPERTY)
 open class BluePrintRestLibPropertyService(private var bluePrintProperties: BluePrintProperties) {
 
+    fun blueprintWebClientService(jsonNode: JsonNode): BlueprintWebClientService {
+        val restClientProperties = restClientProperties(jsonNode)
+        return blueprintWebClientService(restClientProperties)
+    }
+
+    fun blueprintWebClientService(selector: String): BlueprintWebClientService {
+        val prefix = "blueprintsprocessor.restclient.$selector"
+        val restClientProperties = restClientProperties(prefix)
+        return blueprintWebClientService(restClientProperties)
+    }
+
     fun restClientProperties(prefix: String): RestClientProperties {
         val type = bluePrintProperties.propertyBeanType("$prefix.type", String::class.java)
         return when (type) {
@@ -48,9 +65,12 @@ open class BluePrintRestLibPropertyService(private var bluePrintProperties: Blue
         }
     }
 
-    fun restClientProperties(jsonNode: JsonNode): RestClientProperties {
+    private fun restClientProperties(jsonNode: JsonNode): RestClientProperties {
         val type = jsonNode.get("type").textValue()
         return when (type) {
+            RestLibConstants.TYPE_TOKEN_AUTH -> {
+                JacksonUtils.readValue(jsonNode, TokenAuthRestClientProperties::class.java)!!
+            }
             RestLibConstants.TYPE_BASIC_AUTH -> {
                 JacksonUtils.readValue(jsonNode, BasicAuthRestClientProperties::class.java)!!
             }
@@ -69,20 +89,11 @@ open class BluePrintRestLibPropertyService(private var bluePrintProperties: Blue
         }
     }
 
-
-    fun blueprintWebClientService(selector: String): BlueprintWebClientService {
-        val prefix = "blueprintsprocessor.restclient.$selector"
-        val restClientProperties = restClientProperties(prefix)
-        return blueprintWebClientService(restClientProperties)
-    }
-
-    fun blueprintWebClientService(jsonNode: JsonNode): BlueprintWebClientService {
-        val restClientProperties = restClientProperties(jsonNode)
-        return blueprintWebClientService(restClientProperties)
-    }
-
-    fun blueprintWebClientService(restClientProperties: RestClientProperties): BlueprintWebClientService {
+    private fun blueprintWebClientService(restClientProperties: RestClientProperties): BlueprintWebClientService {
         when (restClientProperties) {
+            is TokenAuthRestClientProperties -> {
+                return TokenAuthRestClientService(restClientProperties)
+            }
             is BasicAuthRestClientProperties -> {
                 return BasicAuthRestClientService(restClientProperties)
             }
@@ -98,19 +109,19 @@ open class BluePrintRestLibPropertyService(private var bluePrintProperties: Blue
         }
     }
 
-    fun basicAuthRestClientProperties(prefix: String): BasicAuthRestClientProperties {
+    private fun basicAuthRestClientProperties(prefix: String): BasicAuthRestClientProperties {
         return bluePrintProperties.propertyBeanType(prefix, BasicAuthRestClientProperties::class.java)
     }
 
-    fun sslBasicAuthRestClientProperties(prefix: String): SSLBasicAuthRestClientProperties {
+    private fun sslBasicAuthRestClientProperties(prefix: String): SSLBasicAuthRestClientProperties {
         return bluePrintProperties.propertyBeanType(prefix, SSLBasicAuthRestClientProperties::class.java)
     }
 
-    fun dme2ProxyClientProperties(prefix: String): DME2RestClientProperties {
+    private fun dme2ProxyClientProperties(prefix: String): DME2RestClientProperties {
         return bluePrintProperties.propertyBeanType(prefix, DME2RestClientProperties::class.java)
     }
 
-    fun policyManagerRestClientProperties(prefix: String): PolicyManagerRestClientProperties {
+    private fun policyManagerRestClientProperties(prefix: String): PolicyManagerRestClientProperties {
         return bluePrintProperties.propertyBeanType(prefix, PolicyManagerRestClientProperties::class.java)
     }
 }
index 8106c07..9c2caad 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2017-2018 AT&T Intellectual Property.
+ * Copyright © 2017-2019 AT&T, Bell Canada
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 package org.onap.ccsdk.apps.blueprintsprocessor.rest.service
 
-import org.springframework.web.reactive.function.client.WebClient
+import org.apache.commons.io.IOUtils
+import org.apache.http.client.methods.HttpDelete
+import org.apache.http.client.methods.HttpGet
+import org.apache.http.client.methods.HttpPost
+import org.apache.http.client.methods.HttpPut
+import org.apache.http.entity.StringEntity
+import org.apache.http.impl.client.CloseableHttpClient
+import org.apache.http.impl.client.HttpClients
+import org.apache.http.message.BasicHeader
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.utils.WebClientUtils
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintProcessorException
+import org.springframework.http.HttpMethod
+import java.nio.charset.Charset
 
 interface BlueprintWebClientService {
 
-    fun webClient(): WebClient
+    fun headers(): Array<BasicHeader>
 
-    fun <T> getResource(path: String, responseType: Class<T>): T
+    fun host(uri: String): String
 
-    fun <T> getResource(path: String, headers: Map<String, String>?, responseType: Class<T>): T
+    fun httpClient(): CloseableHttpClient {
+        return HttpClients.custom()
+            .addInterceptorFirst(WebClientUtils.logRequest())
+            .addInterceptorLast(WebClientUtils.logResponse())
+            .build()
+    }
 
-    fun <T> postResource(path: String, request: Any, responseType: Class<T>): T
+    fun exchangeResource(methodType: String, path: String, request: String): String {
+        return when (HttpMethod.resolve(methodType)) {
+            HttpMethod.DELETE -> delete(path)
+            HttpMethod.GET -> get(path)
+            HttpMethod.POST -> post(path, request)
+            HttpMethod.PUT -> put(path, request)
+            else -> throw BluePrintProcessorException("Unsupported methodType($methodType)")
+        }
+    }
 
-    fun <T> postResource(path: String, headers: Map<String, String>?, request: Any, responseType: Class<T>): T
+    fun delete(path: String): String {
+        val httpDelete = HttpDelete(host(path))
+        httpDelete.setHeaders(headers())
+        httpClient().execute(httpDelete).entity.content.use {
+            return IOUtils.toString(it, Charset.defaultCharset())
+        }
+    }
 
-    fun <T> exchangeResource(methodType: String, path: String, request: Any, responseType: Class<T>): T
+    fun get(path: String): String {
+        val httpGet = HttpGet(host(path))
+        httpGet.setHeaders(headers())
+        httpClient().execute(httpGet).entity.content.use {
+            return IOUtils.toString(it, Charset.defaultCharset())
+        }
+    }
 
-}
+    fun post(path: String, request: String): String {
+        val httpPost = HttpPost(host(path))
+        val entity = StringEntity(request)
+        httpPost.entity = entity
+        httpPost.setHeaders(headers())
+        httpClient().execute(httpPost).entity.content.use {
+            return IOUtils.toString(it, Charset.defaultCharset())
+        }
+    }
 
+    fun put(path: String, request: String): String {
+        val httpPut = HttpPut(host(path))
+        val entity = StringEntity(request)
+        httpPut.entity = entity
+        httpPut.setHeaders(headers())
+        httpClient().execute(httpPut).entity.content.use {
+            return IOUtils.toString(it, Charset.defaultCharset())
+        }
+    }
+}
\ No newline at end of file
index 27dbe6f..2b2578a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2017-2018 AT&T Intellectual Property.
+ * Copyright © 2017-2019 AT&T, Bell Canada
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 package org.onap.ccsdk.apps.blueprintsprocessor.rest.service
 
+import org.apache.http.message.BasicHeader
 import org.onap.ccsdk.apps.blueprintsprocessor.rest.RestClientProperties
-import org.springframework.web.reactive.function.client.WebClient
 
 class DME2ProxyRestClientService(restClientProperties: RestClientProperties) : BlueprintWebClientService {
-    override fun webClient(): WebClient {
+    override fun headers(): Array<BasicHeader> {
         TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
     }
 
-    override fun <T> getResource(path: String, responseType: Class<T>): T {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
-    }
-
-    override fun <T> getResource(path: String, headers: Map<String, String>?, responseType: Class<T>): T {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
-    }
-
-    override fun <T> postResource(path: String, request: Any, responseType: Class<T>): T {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
-    }
-
-    override fun <T> postResource(path: String, headers: Map<String, String>?, request: Any, responseType: Class<T>): T {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
-    }
-
-    override fun <T> exchangeResource(methodType: String, path: String, request: Any, responseType: Class<T>): T {
+    override fun host(uri: String): String {
         TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
     }
 }
\ No newline at end of file
index 71727b9..dc2993d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2017-2018 AT&T Intellectual Property.
+ * Copyright © 2017-2019 AT&T, Bell Canada
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 package org.onap.ccsdk.apps.blueprintsprocessor.rest.service
 
-import io.netty.handler.ssl.SslContextBuilder
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory
+import org.apache.http.impl.client.CloseableHttpClient
+import org.apache.http.impl.client.HttpClients
+import org.apache.http.message.BasicHeader
+import org.apache.http.ssl.SSLContextBuilder
 import org.onap.ccsdk.apps.blueprintsprocessor.rest.SSLBasicAuthRestClientProperties
 import org.onap.ccsdk.apps.blueprintsprocessor.rest.utils.WebClientUtils
 import org.springframework.http.HttpHeaders
 import org.springframework.http.MediaType
-import org.springframework.http.client.reactive.ReactorClientHttpConnector
-import org.springframework.web.reactive.function.BodyInserters
-import org.springframework.web.reactive.function.client.WebClient
-import reactor.netty.http.client.HttpClient
 import java.io.File
+import java.io.FileInputStream
 import java.security.KeyStore
 import java.security.cert.X509Certificate
 
+class SSLBasicAuthRestClientService(private val restClientProperties: SSLBasicAuthRestClientProperties) :
+    BlueprintWebClientService {
 
-class SSLBasicAuthRestClientService(private val restClientProperties: SSLBasicAuthRestClientProperties) : BlueprintWebClientService {
+    override fun headers(): Array<BasicHeader> {
+        val params = arrayListOf<BasicHeader>()
+        params.add(BasicHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))
+        params.add(BasicHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE))
+        return params.toTypedArray()
+    }
 
-    override fun webClient(): WebClient {
+    override fun host(uri: String): String {
+        return restClientProperties.url + uri
+    }
 
-        // Load the Keystore Information
-        val ketInputStream = File(restClientProperties.sslKey).inputStream()
-        val ks = KeyStore.getInstance(restClientProperties.keyStoreInstance)
-        ks.load(ketInputStream, restClientProperties.sslKeyPasswd.toCharArray())
+    override fun httpClient(): CloseableHttpClient {
 
-        // Manage Trust Store
-        val trustCertCollection = ks.aliases().toList().map { alias ->
-            ks.getCertificate(alias) as X509Certificate
-        }.toTypedArray()
-        val sslContext = SslContextBuilder
-                .forClient()
-                .trustManager(*trustCertCollection)
-                .build()
+        val keystoreInstance = restClientProperties.keyStoreInstance
+        val sslKey = restClientProperties.sslKey
+        val sslKeyPwd = restClientProperties.sslKeyPassword
+        val sslTrust = restClientProperties.sslTrust
+        val sslTrustPwd = restClientProperties.sslTrustPassword
 
-        // Create Http Client
-        val httpClient = HttpClient.create().secure { t -> t.sslContext(sslContext) }
+        val acceptingTrustStrategy = { chain: Array<X509Certificate>, authType: String -> true }
 
-        return WebClient.builder()
-                .baseUrl(restClientProperties.url)
-                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
-                .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
-                .filter(WebClientUtils.logRequest())
-                .clientConnector(ReactorClientHttpConnector(httpClient)).build()
-    }
+        FileInputStream(sslKey).use { keyInput ->
+            val keyStore = KeyStore.getInstance(keystoreInstance)
+            keyStore.load(keyInput, sslKeyPwd.toCharArray())
 
-    override fun <T> getResource(path: String, responseType: Class<T>): T {
-        return getResource(path, null, responseType)
-    }
+            val sslContext =
+                SSLContextBuilder.create()
+                    .loadKeyMaterial(keyStore, sslKeyPwd.toCharArray())
+                    .loadTrustMaterial(File(sslTrust), sslTrustPwd.toCharArray(), acceptingTrustStrategy).build()
 
-    override fun <T> getResource(path: String, headers: Map<String, String>?, responseType: Class<T>): T {
-        return webClient().get()
-                .uri(path)
-                .headers { httpHeaders ->
-                    headers?.forEach {
-                        httpHeaders.set(it.key, it.value)
-                    }
-                }
-                .retrieve()
-                .bodyToMono(responseType).block()!!
-    }
-
-    override fun <T> postResource(path: String, request: Any, responseType: Class<T>): T {
-        return postResource(path, null, request, responseType)
-    }
-
-    override fun <T> postResource(path: String, headers: Map<String, String>?, request: Any, responseType: Class<T>): T {
-        return webClient().post()
-                .uri(path)
-                .headers { httpHeaders ->
-                    headers?.forEach {
-                        httpHeaders.set(it.key, it.value)
-                    }
-                }
-                .body(BodyInserters.fromObject(request))
-                .retrieve().bodyToMono(responseType).block()!!
-    }
+            val csf = SSLConnectionSocketFactory(sslContext!!)
 
-    override fun <T> exchangeResource(methodType: String, path: String, request: Any, responseType: Class<T>): T {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+            return HttpClients.custom()
+                .addInterceptorFirst(WebClientUtils.logRequest())
+                .addInterceptorLast(WebClientUtils.logResponse())
+                .setSSLSocketFactory(csf).build()
+        }
     }
 }
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/TokenAuthRestClientService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/apps/blueprintsprocessor/rest/service/TokenAuthRestClientService.kt
new file mode 100644 (file)
index 0000000..6e90957
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.apps.blueprintsprocessor.rest.service
+
+import org.apache.http.message.BasicHeader
+import org.onap.ccsdk.apps.blueprintsprocessor.rest.TokenAuthRestClientProperties
+import org.springframework.http.HttpHeaders
+import org.springframework.http.MediaType
+
+class TokenAuthRestClientService(private val restClientProperties: TokenAuthRestClientProperties) :
+    BlueprintWebClientService {
+
+    override fun headers(): Array<BasicHeader> {
+        val params = arrayListOf<BasicHeader>()
+        params.add(BasicHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))
+        params.add(BasicHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE))
+        params.add(BasicHeader(HttpHeaders.AUTHORIZATION, restClientProperties.token))
+        return params.toTypedArray()
+    }
+
+    override fun host(uri: String): String {
+        return restClientProperties.url + uri
+    }
+}
index 40d6ba6..d6167a8 100644 (file)
 
 package org.onap.ccsdk.apps.blueprintsprocessor.rest.utils
 
+import org.apache.http.HttpRequestInterceptor
+import org.apache.http.HttpResponseInterceptor
+import org.slf4j.Logger
 import org.slf4j.LoggerFactory
-import org.springframework.web.reactive.function.client.ExchangeFilterFunction
-import reactor.core.publisher.Mono
-
 
 class WebClientUtils {
     companion object {
 
-        val log = LoggerFactory.getLogger(WebClientUtils::class.java)!!
-
-        fun logRequest(): ExchangeFilterFunction {
+        val log: Logger = LoggerFactory.getLogger(WebClientUtils::class.java)
 
-            return ExchangeFilterFunction.ofRequestProcessor { clientRequest ->
-                log.info("Rest request method(${clientRequest.method()}), url(${clientRequest.url()})")
-                Mono.just(clientRequest)
-            }
-        }
+        fun logRequest(): HttpRequestInterceptor =
+            HttpRequestInterceptor { request, _ -> log.info("Rest request method(${request?.requestLine?.method}), url(${request?.requestLine?.uri})") }
 
-        fun logResponse(): ExchangeFilterFunction {
-            return ExchangeFilterFunction.ofResponseProcessor { clientResponse ->
-                log.info("Response status(${clientResponse.statusCode()})")
-                Mono.just(clientResponse)
-            }
-        }
+        fun logResponse(): HttpResponseInterceptor =
+            HttpResponseInterceptor { response, _ -> log.info("Response status(${response.statusLine.statusCode})") }
     }
 }
\ No newline at end of file
index 2582196..4fa82df 100644 (file)
@@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
 import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.http.HttpMethod
 import org.springframework.test.context.ContextConfiguration
 import org.springframework.test.context.TestPropertySource
 import org.springframework.test.context.junit4.SpringRunner
@@ -39,11 +40,10 @@ import kotlin.test.assertNotNull
 @ContextConfiguration(classes = [BluePrintRestLibConfiguration::class, BlueprintPropertyConfiguration::class,
     SampleController::class, BluePrintProperties::class, BluePrintProperties::class])
 @TestPropertySource(properties =
-["server.port=9111",
-    "blueprintsprocessor.restclient.sample.type=basic-auth",
-    "blueprintsprocessor.restclient.sample.url=http://127.0.0.1:9111",
-    "blueprintsprocessor.restclient.sample.userId=sampleuser",
-    "blueprintsprocessor.restclient.sample.token=sampletoken"])
+["blueprintsprocessor.restclient.sample.type=basic-auth",
+    "blueprintsprocessor.restclient.sample.url=http://127.0.0.1:8080",
+    "blueprintsprocessor.restclient.sample.username=sampleuser",
+    "blueprintsprocessor.restclient.sample.password=sampletoken"])
 class RestClientServiceTest {
 
     @Autowired
@@ -51,11 +51,10 @@ class RestClientServiceTest {
 
     @Test
     fun testBaseAuth() {
-
         val restClientService = bluePrintRestLibPropertyService.blueprintWebClientService("sample")
         val headers = mutableMapOf<String, String>()
         headers["X-Transaction-Id"] = "1234"
-        val response = restClientService.getResource("/sample/name", headers, String::class.java)
+        val response = restClientService.exchangeResource(HttpMethod.GET.name, "/sample/name", "")
         assertNotNull(response, "failed to get response")
     }