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.client.HttpClientFactory
26 import org.onap.so.logger.ErrorCode
28 import java.text.SimpleDateFormat
29 import javax.ws.rs.core.Response
30 import java.net.URLEncoder
32 import org.apache.commons.codec.binary.Base64
33 import org.apache.commons.lang3.*
34 import org.camunda.bpm.engine.delegate.BpmnError
35 import org.camunda.bpm.engine.delegate.DelegateExecution
39 import org.json.JSONObject
41 import org.onap.so.bpmn.core.UrnPropertiesReader
42 import org.onap.so.bpmn.core.WorkflowException
43 import org.onap.so.bpmn.core.domain.RollbackData
44 import org.onap.so.bpmn.core.json.JsonUtils
45 import org.onap.so.client.HttpClient
46 import org.onap.so.logger.MessageEnum
47 import org.slf4j.Logger
48 import org.slf4j.LoggerFactory
49 import org.onap.so.utils.TargetEntity
54 class SDNCAdapterRestV1 extends AbstractServiceTaskProcessor {
55 private static final Logger logger = LoggerFactory.getLogger( SDNCAdapterRestV1.class);
58 ExceptionUtil exceptionUtil = new ExceptionUtil()
59 JsonUtils jsonUtil = new JsonUtils()
62 * Processes the incoming request.
64 public void preProcessRequest (DelegateExecution execution) {
65 def method = getClass().getSimpleName() + '.preProcessRequest(' +
66 'execution=' + execution.getId() +
68 logger.trace('Entered ' + method)
70 def prefix="SDNCREST_"
71 execution.setVariable("prefix", prefix)
72 setSuccessIndicator(execution, false)
75 // Determine the request type and log the request
77 String request = validateRequest(execution, "mso-request-id")
78 String requestType = jsonUtil.getJsonRootProperty(request)
79 execution.setVariable(prefix + 'requestType', requestType)
80 logger.debug(getProcessKey(execution) + ': ' + prefix + 'requestType = ' + requestType)
82 // Determine the SDNCAdapter endpoint
84 String sdncAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.sdnc.rest.endpoint", execution)
86 if (sdncAdapterEndpoint == null || sdncAdapterEndpoint.isEmpty()) {
87 String msg = getProcessKey(execution) + ': mso:adapters:sdnc:rest:endpoint URN mapping is not defined'
89 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
90 ErrorCode.UnknownError.getValue());
91 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
94 while (sdncAdapterEndpoint.endsWith('/')) {
95 sdncAdapterEndpoint = sdncAdapterEndpoint.substring(0, sdncAdapterEndpoint.length()-1)
98 String sdncAdapterMethod = null
99 String sdncAdapterUrl = null
100 String sdncAdapterRequest = request
102 if ('SDNCServiceRequest'.equals(requestType)) {
103 // Get the sdncRequestId from the request
105 String sdncRequestId = jsonUtil.getJsonValue(request, requestType + ".sdncRequestId")
107 if (sdncRequestId == null || sdncRequestId.isEmpty()) {
108 String msg = getProcessKey(execution) + ': no sdncRequestId in ' + requestType
110 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
111 ErrorCode.UnknownError.getValue());
112 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
115 execution.setVariable('SDNCAResponse_CORRELATOR', sdncRequestId)
116 logger.debug(getProcessKey(execution) + ': SDNCAResponse_CORRELATOR = ' + sdncRequestId)
118 // Get the bpNotificationUrl from the request (just to make sure it's there)
120 String bpNotificationUrl = jsonUtil.getJsonValue(request, requestType + ".bpNotificationUrl")
122 if (bpNotificationUrl == null || bpNotificationUrl.isEmpty()) {
123 String msg = getProcessKey(execution) + ': no bpNotificationUrl in ' + requestType
125 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
126 ErrorCode.UnknownError.getValue());
127 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
130 sdncAdapterMethod = 'POST'
131 sdncAdapterUrl = sdncAdapterEndpoint
133 RollbackData rollbackData = new RollbackData()
134 rollbackData.setRequestId(sdncRequestId)
135 rollbackData.getAdditionalData().put("service", jsonUtil.getJsonValue(request, requestType + ".sdncService"))
136 rollbackData.getAdditionalData().put("operation", jsonUtil.getJsonValue(request, requestType + ".sdncOperation"))
137 execution.setVariable("RollbackData", rollbackData)
140 String msg = getProcessKey(execution) + ': Unsupported request type: ' + requestType
142 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
143 ErrorCode.UnknownError.getValue());
144 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
147 execution.setVariable(prefix + 'sdncAdapterMethod', sdncAdapterMethod)
148 execution.setVariable(prefix + 'sdncAdapterUrl', sdncAdapterUrl)
149 execution.setVariable(prefix + 'sdncAdapterRequest', sdncAdapterRequest)
151 // Get the Basic Auth credentials for the SDNCAdapter (yes... we ARE using the PO adapters credentials)
153 String basicAuthValue = UrnPropertiesReader.getVariable("mso.adapters.po.auth", execution)
155 if (basicAuthValue == null || basicAuthValue.isEmpty()) {
156 logger.debug(getProcessKey(execution) + ": mso:adapters:po:auth URN mapping is not defined")
157 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
158 getProcessKey(execution) + ": mso:adapters:po:auth URN mapping is not defined", "BPMN",
159 ErrorCode.UnknownError.getValue());
162 def encodedString = utils.getBasicAuth(basicAuthValue, UrnPropertiesReader.getVariable("mso.msoKey", execution))
163 execution.setVariable(prefix + 'basicAuthHeaderValue', encodedString)
164 } catch (IOException ex) {
165 logger.debug(getProcessKey(execution) + ": Unable to encode BasicAuth credentials for SDNCAdapter")
166 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
167 getProcessKey(execution) + ": Unable to encode BasicAuth credentials for SDNCAdapter",
168 "BPMN", ErrorCode.UnknownError.getValue(), ex);
172 // Set the timeout value, e.g. PT5M. It may be specified in the request as the
173 // bpTimeout value. If it's not in the request, use the URN mapping value.
175 String timeout = jsonUtil.getJsonValue(request, requestType + ".bpTimeout")
177 // in addition to null/empty, also need to verify that the timer value is a valid duration "P[n]T[n]H|M|S"
178 String timerRegex = "PT[0-9]+[HMS]";
179 if (timeout == null || timeout.isEmpty() || !timeout.matches(timerRegex)) {
180 logger.debug(getProcessKey(execution) + ': preProcessRequest(): null/empty/invalid bpTimeout value. Using "mso.adapters.sdnc.timeout"')
181 timeout = UrnPropertiesReader.getVariable("mso.adapters.sdnc.timeout", execution)
184 // the timeout could still be null at this point if the config parm is missing/undefined
185 // forced to log (so OPs can fix the config) and temporarily use a hard coded value of 10 seconds
186 if (timeout == null) {
187 msoLogger.warnSimple('preProcessRequest()', 'property "mso.adapters.sdnc.timeout" is missing/undefined. Using "PT10S"')
191 execution.setVariable(prefix + 'timeout', timeout)
192 logger.debug(getProcessKey(execution) + ': ' + prefix + 'timeout = ' + timeout)
193 } catch (BpmnError e) {
195 } catch (Exception e) {
196 String msg = 'Caught exception in ' + method + ": " + e
198 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
199 ErrorCode.UnknownError.getValue());
200 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
205 * Sends the request to the SDNC adapter.
207 public void sendRequestToSDNCAdapter(DelegateExecution execution) {
208 def method = getClass().getSimpleName() + '.sendRequestToSDNCAdapter(' +
209 'execution=' + execution.getId() +
211 logger.trace('Entered ' + method)
213 String prefix = execution.getVariable('prefix')
216 String sdncAdapterMethod = execution.getVariable(prefix + 'sdncAdapterMethod')
217 logger.debug("SDNC Method is: " + sdncAdapterMethod)
218 String sdncAdapterUrl = execution.getVariable(prefix + 'sdncAdapterUrl')
219 logger.debug("SDNC Url is: " + sdncAdapterUrl)
220 String sdncAdapterRequest = execution.getVariable(prefix + 'sdncAdapterRequest')
221 logger.debug("SDNC Rest Request is: " + sdncAdapterRequest)
223 URL url = new URL(sdncAdapterUrl);
225 HttpClient httpClient = new HttpClientFactory().newJsonClient(url, TargetEntity.SDNC_ADAPTER)
226 httpClient.addAdditionalHeader("X-ONAP-RequestID", execution.getVariable("mso-request-id"))
227 httpClient.addAdditionalHeader("X-ONAP-InvocationID", UUID.randomUUID().toString())
228 httpClient.addAdditionalHeader("X-ONAP-PartnerName", "SO-SDNCAdapter")
229 httpClient.addAdditionalHeader("mso-request-id", execution.getVariable("mso-request-id"))
230 httpClient.addAdditionalHeader("mso-service-instance-id", execution.getVariable("mso-service-instance-id"))
231 httpClient.addAdditionalHeader("Authorization", execution.getVariable(prefix + "basicAuthHeaderValue"))
235 if ("GET".equals(sdncAdapterMethod)) {
236 response = httpClient.get()
237 } else if ("PUT".equals(sdncAdapterMethod)) {
238 response = httpClient.put(sdncAdapterRequest)
239 } else if ("POST".equals(sdncAdapterMethod)) {
240 response = httpClient.post(sdncAdapterRequest)
241 } else if ("DELETE".equals(sdncAdapterMethod)) {
242 response = httpClient.delete(sdncAdapterRequest)
244 String msg = 'Unsupported HTTP method "' + sdncAdapterMethod + '" in ' + method + ": " + e
246 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
247 ErrorCode.UnknownError.getValue());
248 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
251 execution.setVariable(prefix + "sdncAdapterStatusCode", response.getStatus())
252 if(response.hasEntity()){
253 execution.setVariable(prefix + "sdncAdapterResponse", response.readEntity(String.class))
255 } catch (BpmnError e) {
257 } catch (Exception e) {
258 String msg = 'Caught exception in ' + method + ": " + e
260 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
261 ErrorCode.UnknownError.getValue());
262 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
267 * Processes a callback.
269 public void processCallback(DelegateExecution execution){
270 def method = getClass().getSimpleName() + '.processCallback(' +
271 'execution=' + execution.getId() +
273 logger.trace('Entered ' + method)
275 String prefix = execution.getVariable('prefix')
276 String callback = execution.getVariable('SDNCAResponse_MESSAGE')
277 logger.debug("Incoming SDNC Rest Callback is: " + callback)
280 int callbackNumber = 1
281 while (execution.getVariable(prefix + 'callback' + callbackNumber) != null) {
285 execution.setVariable(prefix + 'callback' + callbackNumber, callback)
286 execution.removeVariable('SDNCAResponse_MESSAGE')
288 String responseType = jsonUtil.getJsonRootProperty(callback)
290 // Get the ackFinalIndicator and make sure it's either Y or N. Default to Y.
291 String ackFinalIndicator = jsonUtil.getJsonValue(callback, responseType + ".ackFinalIndicator")
293 if (!'N'.equals(ackFinalIndicator)) {
294 ackFinalIndicator = 'Y'
297 execution.setVariable(prefix + "ackFinalIndicator", ackFinalIndicator)
299 if (responseType.endsWith('Error')) {
300 sdncAdapterBuildWorkflowException(execution, callback)
302 } catch (Exception e) {
303 callback = callback == null || String.valueOf(callback).isEmpty() ? "NONE" : callback
304 String msg = "Received error from SDNCAdapter: " + callback
305 logger.debug(getProcessKey(execution) + ': ' + msg)
306 exceptionUtil.buildWorkflowException(execution, 5300, msg)
311 * Tries to parse the response as XML to extract the information to create
312 * a WorkflowException. If the response cannot be parsed, a more generic
313 * WorkflowException is created.
315 public void sdncAdapterBuildWorkflowException(DelegateExecution execution, String response) {
317 String responseType = jsonUtil.getJsonRootProperty(response)
318 String responseCode = jsonUtil.getJsonValue(response, responseType + ".responseCode")
319 String responseMessage = jsonUtil.getJsonValue(response, responseType + ".responseMessage")
323 if (responseCode != null && !responseCode.isEmpty()) {
324 info += " responseCode='" + responseCode + "'"
327 if (responseMessage != null && !responseMessage.isEmpty()) {
328 info += " responseMessage='" + responseMessage + "'"
331 // Note: the mapping function handles a null or empty responseCode
332 int mappedResponseCode = Integer.parseInt(exceptionUtil.MapSDNCResponseCodeToErrorCode(responseCode));
333 exceptionUtil.buildWorkflowException(execution, mappedResponseCode, "Received " + responseType +
334 " from SDNCAdapter:" + info)
335 } catch (Exception e) {
336 response = response == null || String.valueOf(response).isEmpty() ? "NONE" : response
337 exceptionUtil.buildWorkflowException(execution, 5300, "Received error from SDNCAdapter: " + response)
342 * Gets the last callback request from the execution, or null if there was no callback.
344 public String getLastCallback(DelegateExecution execution) {
345 def method = getClass().getSimpleName() + '.getLastCallback(' +
346 'execution=' + execution.getId() +
348 logger.trace('Entered ' + method)
350 String prefix = execution.getVariable('prefix')
353 int callbackNumber = 1
354 String callback = null
357 String thisCallback = (String) execution.getVariable(prefix + 'callback' + callbackNumber)
359 if (thisCallback == null) {
363 callback = thisCallback
368 } catch (Exception e) {
369 String msg = 'Caught exception in ' + method + ": " + e
371 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
372 ErrorCode.UnknownError.getValue());
373 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
378 * Sets the timeout value to wait for the next notification.
380 public void setTimeoutValue(DelegateExecution execution) {
381 def method = getClass().getSimpleName() + '.setTimeoutValue(' +
382 'execution=' + execution.getId() +
384 logger.trace('Entered ' + method)
386 String prefix = execution.getVariable('prefix')
389 def timeoutValue = UrnPropertiesReader.getVariable("mso.adapters.sdnc.timeout", execution)
391 if (execution.getVariable(prefix + 'callback1') != null) {
392 // Waiting for subsequent notifications
394 } catch (Exception e) {
395 String msg = 'Caught exception in ' + method + ": " + e
397 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
398 ErrorCode.UnknownError.getValue());
399 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
403 public Logger getLogger() {