2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.so.bpmn.common.scripts
23 import java.text.SimpleDateFormat
24 import java.net.URLEncoder
26 import org.apache.commons.codec.binary.Base64
27 import org.apache.commons.lang3.*
28 import org.camunda.bpm.engine.delegate.BpmnError
29 import org.camunda.bpm.engine.delegate.DelegateExecution
33 import org.json.JSONObject
35 import org.onap.so.bpmn.core.UrnPropertiesReader
36 import org.onap.so.bpmn.core.WorkflowException
37 import org.onap.so.bpmn.core.domain.RollbackData
38 import org.onap.so.bpmn.core.json.JsonUtils
39 import org.onap.so.rest.APIResponse
40 import org.onap.so.rest.RESTClient
41 import org.onap.so.rest.RESTConfig
42 import org.onap.so.logger.MessageEnum
43 import org.onap.so.logger.MsoLogger
48 class SDNCAdapterRestV1 extends AbstractServiceTaskProcessor {
49 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, SDNCAdapterRestV1.class);
52 ExceptionUtil exceptionUtil = new ExceptionUtil()
53 JsonUtils jsonUtil = new JsonUtils()
56 * Processes the incoming request.
58 public void preProcessRequest (DelegateExecution execution) {
59 def method = getClass().getSimpleName() + '.preProcessRequest(' +
60 'execution=' + execution.getId() +
62 msoLogger.trace('Entered ' + method)
64 def prefix="SDNCREST_"
65 execution.setVariable("prefix", prefix)
66 setSuccessIndicator(execution, false)
69 // Determine the request type and log the request
71 String request = validateRequest(execution, "mso-request-id")
72 String requestType = jsonUtil.getJsonRootProperty(request)
73 execution.setVariable(prefix + 'requestType', requestType)
74 msoLogger.debug(getProcessKey(execution) + ': ' + prefix + 'requestType = ' + requestType)
76 // Determine the SDNCAdapter endpoint
78 String sdncAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.sdnc.rest.endpoint", execution)
80 if (sdncAdapterEndpoint == null || sdncAdapterEndpoint.isEmpty()) {
81 String msg = getProcessKey(execution) + ': mso:adapters:sdnc:rest:endpoint URN mapping is not defined'
83 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
84 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
87 while (sdncAdapterEndpoint.endsWith('/')) {
88 sdncAdapterEndpoint = sdncAdapterEndpoint.substring(0, sdncAdapterEndpoint.length()-1)
91 String sdncAdapterMethod = null
92 String sdncAdapterUrl = null
93 String sdncAdapterRequest = request
95 if ('SDNCServiceRequest'.equals(requestType)) {
96 // Get the sdncRequestId from the request
98 String sdncRequestId = jsonUtil.getJsonValue(request, requestType + ".sdncRequestId")
100 if (sdncRequestId == null || sdncRequestId.isEmpty()) {
101 String msg = getProcessKey(execution) + ': no sdncRequestId in ' + requestType
103 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
104 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
107 execution.setVariable('SDNCAResponse_CORRELATOR', sdncRequestId)
108 msoLogger.debug(getProcessKey(execution) + ': SDNCAResponse_CORRELATOR = ' + sdncRequestId)
110 // Get the bpNotificationUrl from the request (just to make sure it's there)
112 String bpNotificationUrl = jsonUtil.getJsonValue(request, requestType + ".bpNotificationUrl")
114 if (bpNotificationUrl == null || bpNotificationUrl.isEmpty()) {
115 String msg = getProcessKey(execution) + ': no bpNotificationUrl in ' + requestType
117 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
118 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
121 sdncAdapterMethod = 'POST'
122 sdncAdapterUrl = sdncAdapterEndpoint
124 RollbackData rollbackData = new RollbackData()
125 rollbackData.setRequestId(sdncRequestId)
126 rollbackData.getAdditionalData().put("service", jsonUtil.getJsonValue(request, requestType + ".sdncService"))
127 rollbackData.getAdditionalData().put("operation", jsonUtil.getJsonValue(request, requestType + ".sdncOperation"))
128 execution.setVariable("RollbackData", rollbackData)
131 String msg = getProcessKey(execution) + ': Unsupported request type: ' + requestType
133 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
134 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
137 execution.setVariable(prefix + 'sdncAdapterMethod', sdncAdapterMethod)
138 execution.setVariable(prefix + 'sdncAdapterUrl', sdncAdapterUrl)
139 execution.setVariable(prefix + 'sdncAdapterRequest', sdncAdapterRequest)
141 // Get the Basic Auth credentials for the SDNCAdapter (yes... we ARE using the PO adapters credentials)
143 String basicAuthValue = UrnPropertiesReader.getVariable("mso.adapters.po.auth", execution)
145 if (basicAuthValue == null || basicAuthValue.isEmpty()) {
146 msoLogger.debug(getProcessKey(execution) + ": mso:adapters:po:auth URN mapping is not defined")
147 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, getProcessKey(execution) + ": mso:adapters:po:auth URN mapping is not defined", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
150 def encodedString = utils.getBasicAuth(basicAuthValue, UrnPropertiesReader.getVariable("mso.msoKey", execution))
151 execution.setVariable(prefix + 'basicAuthHeaderValue', encodedString)
152 } catch (IOException ex) {
153 msoLogger.debug(getProcessKey(execution) + ": Unable to encode BasicAuth credentials for SDNCAdapter")
154 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, getProcessKey(execution) + ": Unable to encode BasicAuth credentials for SDNCAdapter", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
158 // Set the timeout value, e.g. PT5M. It may be specified in the request as the
159 // bpTimeout value. If it's not in the request, use the URN mapping value.
161 String timeout = jsonUtil.getJsonValue(request, requestType + ".bpTimeout")
163 // in addition to null/empty, also need to verify that the timer value is a valid duration "P[n]T[n]H|M|S"
164 String timerRegex = "PT[0-9]+[HMS]";
165 if (timeout == null || timeout.isEmpty() || !timeout.matches(timerRegex)) {
166 msoLogger.debug(getProcessKey(execution) + ': preProcessRequest(): null/empty/invalid bpTimeout value. Using "mso.adapters.sdnc.timeout"')
167 timeout = UrnPropertiesReader.getVariable("mso.adapters.sdnc.timeout", execution)
170 // the timeout could still be null at this point if the config parm is missing/undefined
171 // forced to log (so OPs can fix the config) and temporarily use a hard coded value of 10 seconds
172 if (timeout == null) {
173 msoLogger.warnSimple('preProcessRequest()', 'property "mso.adapters.sdnc.timeout" is missing/undefined. Using "PT10S"')
177 execution.setVariable(prefix + 'timeout', timeout)
178 msoLogger.debug(getProcessKey(execution) + ': ' + prefix + 'timeout = ' + timeout)
179 } catch (BpmnError e) {
181 } catch (Exception e) {
182 String msg = 'Caught exception in ' + method + ": " + e
184 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
185 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
190 * Sends the request to the SDNC adapter.
192 public void sendRequestToSDNCAdapter(DelegateExecution execution) {
193 def method = getClass().getSimpleName() + '.sendRequestToSDNCAdapter(' +
194 'execution=' + execution.getId() +
196 msoLogger.trace('Entered ' + method)
198 String prefix = execution.getVariable('prefix')
201 String sdncAdapterMethod = execution.getVariable(prefix + 'sdncAdapterMethod')
202 msoLogger.debug("SDNC Method is: " + sdncAdapterMethod)
203 String sdncAdapterUrl = execution.getVariable(prefix + 'sdncAdapterUrl')
204 msoLogger.debug("SDNC Url is: " + sdncAdapterUrl)
205 String sdncAdapterRequest = execution.getVariable(prefix + 'sdncAdapterRequest')
206 msoLogger.debug("SDNC Rest Request is: " + sdncAdapterRequest)
208 RESTConfig config = new RESTConfig(sdncAdapterUrl)
209 RESTClient client = new RESTClient(config).
210 addHeader("Content-Type", "application/json")
211 .addHeader("mso-request-id",execution.getVariable("mso-request-id"))
212 .addHeader("mso-service-instance-id",execution.getVariable("mso-service-instance-id"))
213 .addAuthorizationHeader(execution.getVariable(prefix + "basicAuthHeaderValue"))
217 if ("GET".equals(sdncAdapterMethod)) {
218 response = client.httpGet()
219 } else if ("PUT".equals(sdncAdapterMethod)) {
220 response = client.httpPut(sdncAdapterRequest)
221 } else if ("POST".equals(sdncAdapterMethod)) {
222 response = client.httpPost(sdncAdapterRequest)
223 } else if ("DELETE".equals(sdncAdapterMethod)) {
224 response = client.httpDelete(sdncAdapterRequest)
226 String msg = 'Unsupported HTTP method "' + sdncAdapterMethod + '" in ' + method + ": " + e
228 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
229 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
232 execution.setVariable(prefix + "sdncAdapterStatusCode", response.getStatusCode())
233 execution.setVariable(prefix + "sdncAdapterResponse", response.getResponseBodyAsString())
234 } catch (BpmnError e) {
236 } catch (Exception e) {
237 String msg = 'Caught exception in ' + method + ": " + e
239 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
240 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
245 * Processes a callback.
247 public void processCallback(DelegateExecution execution){
248 def method = getClass().getSimpleName() + '.processCallback(' +
249 'execution=' + execution.getId() +
251 msoLogger.trace('Entered ' + method)
253 String prefix = execution.getVariable('prefix')
254 String callback = execution.getVariable('SDNCAResponse_MESSAGE')
255 String requestId = execution.getVariable("mso-request-id");
256 String serviceInstanceId = execution.getVariable("mso-service-instance-id")
257 utils.logContext(requestId, serviceInstanceId)
258 msoLogger.debug("Incoming SDNC Rest Callback is: " + callback)
261 int callbackNumber = 1
262 while (execution.getVariable(prefix + 'callback' + callbackNumber) != null) {
266 execution.setVariable(prefix + 'callback' + callbackNumber, callback)
267 execution.removeVariable('SDNCAResponse_MESSAGE')
269 String responseType = jsonUtil.getJsonRootProperty(callback)
271 // Get the ackFinalIndicator and make sure it's either Y or N. Default to Y.
272 String ackFinalIndicator = jsonUtil.getJsonValue(callback, responseType + ".ackFinalIndicator")
274 if (!'N'.equals(ackFinalIndicator)) {
275 ackFinalIndicator = 'Y'
278 execution.setVariable(prefix + "ackFinalIndicator", ackFinalIndicator)
280 if (responseType.endsWith('Error')) {
281 sdncAdapterBuildWorkflowException(execution, callback)
283 } catch (Exception e) {
284 callback = callback == null || String.valueOf(callback).isEmpty() ? "NONE" : callback
285 String msg = "Received error from SDNCAdapter: " + callback
286 msoLogger.debug(getProcessKey(execution) + ': ' + msg)
287 exceptionUtil.buildWorkflowException(execution, 5300, msg)
292 * Tries to parse the response as XML to extract the information to create
293 * a WorkflowException. If the response cannot be parsed, a more generic
294 * WorkflowException is created.
296 public void sdncAdapterBuildWorkflowException(DelegateExecution execution, String response) {
298 String responseType = jsonUtil.getJsonRootProperty(response)
299 String responseCode = jsonUtil.getJsonValue(response, responseType + ".responseCode")
300 String responseMessage = jsonUtil.getJsonValue(response, responseType + ".responseMessage")
304 if (responseCode != null && !responseCode.isEmpty()) {
305 info += " responseCode='" + responseCode + "'"
308 if (responseMessage != null && !responseMessage.isEmpty()) {
309 info += " responseMessage='" + responseMessage + "'"
312 // Note: the mapping function handles a null or empty responseCode
313 int mappedResponseCode = Integer.parseInt(exceptionUtil.MapSDNCResponseCodeToErrorCode(responseCode));
314 exceptionUtil.buildWorkflowException(execution, mappedResponseCode, "Received " + responseType +
315 " from SDNCAdapter:" + info)
316 } catch (Exception e) {
317 response = response == null || String.valueOf(response).isEmpty() ? "NONE" : response
318 exceptionUtil.buildWorkflowException(execution, 5300, "Received error from SDNCAdapter: " + response)
323 * Gets the last callback request from the execution, or null if there was no callback.
325 public String getLastCallback(DelegateExecution execution) {
326 def method = getClass().getSimpleName() + '.getLastCallback(' +
327 'execution=' + execution.getId() +
329 msoLogger.trace('Entered ' + method)
331 String prefix = execution.getVariable('prefix')
334 int callbackNumber = 1
335 String callback = null
338 String thisCallback = (String) execution.getVariable(prefix + 'callback' + callbackNumber)
340 if (thisCallback == null) {
344 callback = thisCallback
349 } catch (Exception e) {
350 String msg = 'Caught exception in ' + method + ": " + e
352 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
353 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
358 * Sets the timeout value to wait for the next notification.
360 public void setTimeoutValue(DelegateExecution execution) {
361 def method = getClass().getSimpleName() + '.setTimeoutValue(' +
362 'execution=' + execution.getId() +
364 msoLogger.trace('Entered ' + method)
366 String prefix = execution.getVariable('prefix')
369 def timeoutValue = UrnPropertiesReader.getVariable("mso.adapters.sdnc.timeout", execution)
371 if (execution.getVariable(prefix + 'callback1') != null) {
372 // Waiting for subsequent notifications
374 } catch (Exception e) {
375 String msg = 'Caught exception in ' + method + ": " + e
377 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
378 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)