2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Modifications Copyright (c) 2019 Samsung
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=========================================================
23 package org.onap.so.bpmn.common.scripts
25 import org.onap.so.logger.LoggingAnchor
26 import org.onap.so.client.HttpClientFactory
27 import org.onap.so.logger.ErrorCode
29 import java.text.SimpleDateFormat
30 import javax.ws.rs.core.Response
31 import java.net.URLEncoder
33 import org.apache.commons.codec.binary.Base64
34 import org.apache.commons.lang3.*
35 import org.camunda.bpm.engine.delegate.BpmnError
36 import org.camunda.bpm.engine.delegate.DelegateExecution
40 import org.json.JSONObject
42 import org.onap.so.bpmn.core.UrnPropertiesReader
43 import org.onap.so.bpmn.core.WorkflowException
44 import org.onap.so.bpmn.core.domain.RollbackData
45 import org.onap.so.bpmn.core.json.JsonUtils
46 import org.onap.so.client.HttpClient
47 import org.onap.so.logger.MessageEnum
48 import org.slf4j.Logger
49 import org.slf4j.LoggerFactory
50 import org.onap.so.utils.TargetEntity
55 class SDNCAdapterRestV1 extends AbstractServiceTaskProcessor {
56 private static final Logger logger = LoggerFactory.getLogger( SDNCAdapterRestV1.class);
59 ExceptionUtil exceptionUtil = new ExceptionUtil()
60 JsonUtils jsonUtil = new JsonUtils()
63 * Processes the incoming request.
65 public void preProcessRequest (DelegateExecution execution) {
66 def method = getClass().getSimpleName() + '.preProcessRequest(' +
67 'execution=' + execution.getId() +
69 logger.trace('Entered ' + method)
71 def prefix="SDNCREST_"
72 execution.setVariable("prefix", prefix)
73 setSuccessIndicator(execution, false)
76 // Determine the request type and log the request
78 String request = validateRequest(execution, "mso-request-id")
79 String requestType = jsonUtil.getJsonRootProperty(request)
80 execution.setVariable(prefix + 'requestType', requestType)
81 logger.debug(getProcessKey(execution) + ': ' + prefix + 'requestType = ' + requestType)
83 // Determine the SDNCAdapter endpoint
85 String sdncAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.sdnc.rest.endpoint", execution)
87 if (sdncAdapterEndpoint == null || sdncAdapterEndpoint.isEmpty()) {
88 String msg = getProcessKey(execution) + ': mso:adapters:sdnc:rest:endpoint URN mapping is not defined'
90 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
91 ErrorCode.UnknownError.getValue());
92 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
95 while (sdncAdapterEndpoint.endsWith('/')) {
96 sdncAdapterEndpoint = sdncAdapterEndpoint.substring(0, sdncAdapterEndpoint.length()-1)
99 String sdncAdapterMethod = null
100 String sdncAdapterUrl = null
101 String sdncAdapterRequest = request
103 if ('SDNCServiceRequest'.equals(requestType)) {
104 // Get the sdncRequestId from the request
106 String sdncRequestId = jsonUtil.getJsonValue(request, requestType + ".sdncRequestId")
108 if (sdncRequestId == null || sdncRequestId.isEmpty()) {
109 String msg = getProcessKey(execution) + ': no sdncRequestId in ' + requestType
111 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
112 ErrorCode.UnknownError.getValue());
113 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
116 execution.setVariable('SDNCAResponse_CORRELATOR', sdncRequestId)
117 logger.debug(getProcessKey(execution) + ': SDNCAResponse_CORRELATOR = ' + sdncRequestId)
119 // Get the bpNotificationUrl from the request (just to make sure it's there)
121 String bpNotificationUrl = jsonUtil.getJsonValue(request, requestType + ".bpNotificationUrl")
123 if (bpNotificationUrl == null || bpNotificationUrl.isEmpty()) {
124 String msg = getProcessKey(execution) + ': no bpNotificationUrl in ' + requestType
126 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
127 ErrorCode.UnknownError.getValue());
128 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
131 sdncAdapterMethod = 'POST'
132 sdncAdapterUrl = sdncAdapterEndpoint
134 RollbackData rollbackData = new RollbackData()
135 rollbackData.setRequestId(sdncRequestId)
136 rollbackData.getAdditionalData().put("service", jsonUtil.getJsonValue(request, requestType + ".sdncService"))
137 rollbackData.getAdditionalData().put("operation", jsonUtil.getJsonValue(request, requestType + ".sdncOperation"))
138 execution.setVariable("RollbackData", rollbackData)
141 String msg = getProcessKey(execution) + ': Unsupported request type: ' + requestType
143 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
144 ErrorCode.UnknownError.getValue());
145 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
148 execution.setVariable(prefix + 'sdncAdapterMethod', sdncAdapterMethod)
149 execution.setVariable(prefix + 'sdncAdapterUrl', sdncAdapterUrl)
150 execution.setVariable(prefix + 'sdncAdapterRequest', sdncAdapterRequest)
152 // Get the Basic Auth credentials for the SDNCAdapter (yes... we ARE using the PO adapters credentials)
154 String basicAuthValue = UrnPropertiesReader.getVariable("mso.adapters.po.auth", execution)
156 if (basicAuthValue == null || basicAuthValue.isEmpty()) {
157 logger.debug(getProcessKey(execution) + ": mso:adapters:po:auth URN mapping is not defined")
158 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
159 getProcessKey(execution) + ": mso:adapters:po:auth URN mapping is not defined", "BPMN",
160 ErrorCode.UnknownError.getValue());
163 def encodedString = utils.getBasicAuth(basicAuthValue, UrnPropertiesReader.getVariable("mso.msoKey", execution))
164 execution.setVariable(prefix + 'basicAuthHeaderValue', encodedString)
165 } catch (IOException ex) {
166 logger.debug(getProcessKey(execution) + ": Unable to encode BasicAuth credentials for SDNCAdapter")
167 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
168 getProcessKey(execution) + ": Unable to encode BasicAuth credentials for SDNCAdapter",
169 "BPMN", ErrorCode.UnknownError.getValue(), ex);
173 // Set the timeout value, e.g. PT5M. It may be specified in the request as the
174 // bpTimeout value. If it's not in the request, use the URN mapping value.
176 String timeout = jsonUtil.getJsonValue(request, requestType + ".bpTimeout")
178 // in addition to null/empty, also need to verify that the timer value is a valid duration "P[n]T[n]H|M|S"
179 String timerRegex = "PT[0-9]+[HMS]";
180 if (timeout == null || timeout.isEmpty() || !timeout.matches(timerRegex)) {
181 logger.debug(getProcessKey(execution) + ': preProcessRequest(): null/empty/invalid bpTimeout value. Using "mso.adapters.sdnc.timeout"')
182 timeout = UrnPropertiesReader.getVariable("mso.adapters.sdnc.timeout", execution)
185 // the timeout could still be null at this point if the config parm is missing/undefined
186 // forced to log (so OPs can fix the config) and temporarily use a hard coded value of 10 seconds
187 if (timeout == null) {
188 msoLogger.warnSimple('preProcessRequest()', 'property "mso.adapters.sdnc.timeout" is missing/undefined. Using "PT10S"')
192 execution.setVariable(prefix + 'timeout', timeout)
193 logger.debug(getProcessKey(execution) + ': ' + prefix + 'timeout = ' + timeout)
194 } catch (BpmnError e) {
196 } catch (Exception e) {
197 String msg = 'Caught exception in ' + method + ": " + e
199 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
200 ErrorCode.UnknownError.getValue());
201 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
206 * Sends the request to the SDNC adapter.
208 public void sendRequestToSDNCAdapter(DelegateExecution execution) {
209 def method = getClass().getSimpleName() + '.sendRequestToSDNCAdapter(' +
210 'execution=' + execution.getId() +
212 logger.trace('Entered ' + method)
214 String prefix = execution.getVariable('prefix')
217 String sdncAdapterMethod = execution.getVariable(prefix + 'sdncAdapterMethod')
218 logger.debug("SDNC Method is: " + sdncAdapterMethod)
219 String sdncAdapterUrl = execution.getVariable(prefix + 'sdncAdapterUrl')
220 logger.debug("SDNC Url is: " + sdncAdapterUrl)
221 String sdncAdapterRequest = execution.getVariable(prefix + 'sdncAdapterRequest')
222 logger.debug("SDNC Rest Request is: " + sdncAdapterRequest)
224 URL url = new URL(sdncAdapterUrl);
226 HttpClient httpClient = new HttpClientFactory().newJsonClient(url, TargetEntity.SDNC_ADAPTER)
227 httpClient.addAdditionalHeader("X-ONAP-RequestID", execution.getVariable("mso-request-id"))
228 httpClient.addAdditionalHeader("X-ONAP-InvocationID", UUID.randomUUID().toString())
229 httpClient.addAdditionalHeader("X-ONAP-PartnerName", "SO-SDNCAdapter")
230 httpClient.addAdditionalHeader("mso-request-id", execution.getVariable("mso-request-id"))
231 httpClient.addAdditionalHeader("mso-service-instance-id", execution.getVariable("mso-service-instance-id"))
232 httpClient.addAdditionalHeader("Authorization", execution.getVariable(prefix + "basicAuthHeaderValue"))
236 if ("GET".equals(sdncAdapterMethod)) {
237 response = httpClient.get()
238 } else if ("PUT".equals(sdncAdapterMethod)) {
239 response = httpClient.put(sdncAdapterRequest)
240 } else if ("POST".equals(sdncAdapterMethod)) {
241 response = httpClient.post(sdncAdapterRequest)
242 } else if ("DELETE".equals(sdncAdapterMethod)) {
243 response = httpClient.delete(sdncAdapterRequest)
245 String msg = 'Unsupported HTTP method "' + sdncAdapterMethod + '" in ' + method + ": " + e
247 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
248 ErrorCode.UnknownError.getValue());
249 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
252 execution.setVariable(prefix + "sdncAdapterStatusCode", response.getStatus())
253 if(response.hasEntity()){
254 execution.setVariable(prefix + "sdncAdapterResponse", response.readEntity(String.class))
256 } catch (BpmnError e) {
258 } catch (Exception e) {
259 String msg = 'Caught exception in ' + method + ": " + e
261 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
262 ErrorCode.UnknownError.getValue());
263 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
268 * Processes a callback.
270 public void processCallback(DelegateExecution execution){
271 def method = getClass().getSimpleName() + '.processCallback(' +
272 'execution=' + execution.getId() +
274 logger.trace('Entered ' + method)
276 String prefix = execution.getVariable('prefix')
277 String callback = execution.getVariable('SDNCAResponse_MESSAGE')
278 logger.debug("Incoming SDNC Rest Callback is: " + callback)
281 int callbackNumber = 1
282 while (execution.getVariable(prefix + 'callback' + callbackNumber) != null) {
286 execution.setVariable(prefix + 'callback' + callbackNumber, callback)
287 execution.removeVariable('SDNCAResponse_MESSAGE')
289 String responseType = jsonUtil.getJsonRootProperty(callback)
291 // Get the ackFinalIndicator and make sure it's either Y or N. Default to Y.
292 String ackFinalIndicator = jsonUtil.getJsonValue(callback, responseType + ".ackFinalIndicator")
294 if (!'N'.equals(ackFinalIndicator)) {
295 ackFinalIndicator = 'Y'
298 execution.setVariable(prefix + "ackFinalIndicator", ackFinalIndicator)
300 if (responseType.endsWith('Error')) {
301 sdncAdapterBuildWorkflowException(execution, callback)
303 } catch (Exception e) {
304 callback = callback == null || String.valueOf(callback).isEmpty() ? "NONE" : callback
305 String msg = "Received error from SDNCAdapter: " + callback
306 logger.debug(getProcessKey(execution) + ': ' + msg)
307 exceptionUtil.buildWorkflowException(execution, 5300, msg)
312 * Tries to parse the response as XML to extract the information to create
313 * a WorkflowException. If the response cannot be parsed, a more generic
314 * WorkflowException is created.
316 public void sdncAdapterBuildWorkflowException(DelegateExecution execution, String response) {
318 String responseType = jsonUtil.getJsonRootProperty(response)
319 String responseCode = jsonUtil.getJsonValue(response, responseType + ".responseCode")
320 String responseMessage = jsonUtil.getJsonValue(response, responseType + ".responseMessage")
324 if (responseCode != null && !responseCode.isEmpty()) {
325 info += " responseCode='" + responseCode + "'"
328 if (responseMessage != null && !responseMessage.isEmpty()) {
329 info += " responseMessage='" + responseMessage + "'"
332 // Note: the mapping function handles a null or empty responseCode
333 int mappedResponseCode = Integer.parseInt(exceptionUtil.MapSDNCResponseCodeToErrorCode(responseCode));
334 exceptionUtil.buildWorkflowException(execution, mappedResponseCode, "Received " + responseType +
335 " from SDNCAdapter:" + info)
336 } catch (Exception e) {
337 response = response == null || String.valueOf(response).isEmpty() ? "NONE" : response
338 exceptionUtil.buildWorkflowException(execution, 5300, "Received error from SDNCAdapter: " + response)
343 * Gets the last callback request from the execution, or null if there was no callback.
345 public String getLastCallback(DelegateExecution execution) {
346 def method = getClass().getSimpleName() + '.getLastCallback(' +
347 'execution=' + execution.getId() +
349 logger.trace('Entered ' + method)
351 String prefix = execution.getVariable('prefix')
354 int callbackNumber = 1
355 String callback = null
358 String thisCallback = (String) execution.getVariable(prefix + 'callback' + callbackNumber)
360 if (thisCallback == null) {
364 callback = thisCallback
369 } catch (Exception e) {
370 String msg = 'Caught exception in ' + method + ": " + e
372 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
373 ErrorCode.UnknownError.getValue());
374 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
379 * Sets the timeout value to wait for the next notification.
381 public void setTimeoutValue(DelegateExecution execution) {
382 def method = getClass().getSimpleName() + '.setTimeoutValue(' +
383 'execution=' + execution.getId() +
385 logger.trace('Entered ' + method)
387 String prefix = execution.getVariable('prefix')
390 def timeoutValue = UrnPropertiesReader.getVariable("mso.adapters.sdnc.timeout", execution)
392 if (execution.getVariable(prefix + 'callback1') != null) {
393 // Waiting for subsequent notifications
395 } catch (Exception e) {
396 String msg = 'Caught exception in ' + method + ": " + e
398 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
399 ErrorCode.UnknownError.getValue());
400 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
404 public Logger getLogger() {