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 javax.ws.rs.core.Response
25 import java.net.URLEncoder
27 import org.apache.commons.codec.binary.Base64
28 import org.apache.commons.lang3.*
29 import org.camunda.bpm.engine.delegate.BpmnError
30 import org.camunda.bpm.engine.delegate.DelegateExecution
34 import org.json.JSONObject
36 import org.onap.so.bpmn.core.UrnPropertiesReader
37 import org.onap.so.bpmn.core.WorkflowException
38 import org.onap.so.bpmn.core.domain.RollbackData
39 import org.onap.so.bpmn.core.json.JsonUtils
40 import org.onap.so.client.HttpClient
41 import org.onap.so.logger.MessageEnum
42 import org.onap.so.logger.MsoLogger
43 import org.onap.so.utils.TargetEntity
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 URL url = new URL(sdncAdapterUrl);
210 HttpClient httpClient = new HttpClient(url, "application/json", TargetEntity.SDNC_ADAPTER)
211 httpClient.addAdditionalHeader("mso-request-id", execution.getVariable("mso-request-id"))
212 httpClient.addAdditionalHeader("mso-service-instance-id", execution.getVariable("mso-service-instance-id"))
213 httpClient.addAdditionalHeader("Authorization", execution.getVariable(prefix + "basicAuthHeaderValue"))
217 if ("GET".equals(sdncAdapterMethod)) {
218 response = httpClient.get()
219 } else if ("PUT".equals(sdncAdapterMethod)) {
220 response = httpClient.put(sdncAdapterRequest)
221 } else if ("POST".equals(sdncAdapterMethod)) {
222 response = httpClient.post(sdncAdapterRequest)
223 } else if ("DELETE".equals(sdncAdapterMethod)) {
224 response = httpClient.delete(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.getStatus())
233 if(response.hasEntity()){
234 execution.setVariable(prefix + "sdncAdapterResponse", response.readEntity(String.class))
236 } catch (BpmnError e) {
238 } catch (Exception e) {
239 String msg = 'Caught exception in ' + method + ": " + e
240 msoLogger.debug(msg, e)
241 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
242 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
247 * Processes a callback.
249 public void processCallback(DelegateExecution execution){
250 def method = getClass().getSimpleName() + '.processCallback(' +
251 'execution=' + execution.getId() +
253 msoLogger.trace('Entered ' + method)
255 String prefix = execution.getVariable('prefix')
256 String callback = execution.getVariable('SDNCAResponse_MESSAGE')
257 String requestId = execution.getVariable("mso-request-id");
258 String serviceInstanceId = execution.getVariable("mso-service-instance-id")
259 utils.logContext(requestId, serviceInstanceId)
260 msoLogger.debug("Incoming SDNC Rest Callback is: " + callback)
263 int callbackNumber = 1
264 while (execution.getVariable(prefix + 'callback' + callbackNumber) != null) {
268 execution.setVariable(prefix + 'callback' + callbackNumber, callback)
269 execution.removeVariable('SDNCAResponse_MESSAGE')
271 String responseType = jsonUtil.getJsonRootProperty(callback)
273 // Get the ackFinalIndicator and make sure it's either Y or N. Default to Y.
274 String ackFinalIndicator = jsonUtil.getJsonValue(callback, responseType + ".ackFinalIndicator")
276 if (!'N'.equals(ackFinalIndicator)) {
277 ackFinalIndicator = 'Y'
280 execution.setVariable(prefix + "ackFinalIndicator", ackFinalIndicator)
282 if (responseType.endsWith('Error')) {
283 sdncAdapterBuildWorkflowException(execution, callback)
285 } catch (Exception e) {
286 callback = callback == null || String.valueOf(callback).isEmpty() ? "NONE" : callback
287 String msg = "Received error from SDNCAdapter: " + callback
288 msoLogger.debug(getProcessKey(execution) + ': ' + msg)
289 exceptionUtil.buildWorkflowException(execution, 5300, msg)
294 * Tries to parse the response as XML to extract the information to create
295 * a WorkflowException. If the response cannot be parsed, a more generic
296 * WorkflowException is created.
298 public void sdncAdapterBuildWorkflowException(DelegateExecution execution, String response) {
300 String responseType = jsonUtil.getJsonRootProperty(response)
301 String responseCode = jsonUtil.getJsonValue(response, responseType + ".responseCode")
302 String responseMessage = jsonUtil.getJsonValue(response, responseType + ".responseMessage")
306 if (responseCode != null && !responseCode.isEmpty()) {
307 info += " responseCode='" + responseCode + "'"
310 if (responseMessage != null && !responseMessage.isEmpty()) {
311 info += " responseMessage='" + responseMessage + "'"
314 // Note: the mapping function handles a null or empty responseCode
315 int mappedResponseCode = Integer.parseInt(exceptionUtil.MapSDNCResponseCodeToErrorCode(responseCode));
316 exceptionUtil.buildWorkflowException(execution, mappedResponseCode, "Received " + responseType +
317 " from SDNCAdapter:" + info)
318 } catch (Exception e) {
319 response = response == null || String.valueOf(response).isEmpty() ? "NONE" : response
320 exceptionUtil.buildWorkflowException(execution, 5300, "Received error from SDNCAdapter: " + response)
325 * Gets the last callback request from the execution, or null if there was no callback.
327 public String getLastCallback(DelegateExecution execution) {
328 def method = getClass().getSimpleName() + '.getLastCallback(' +
329 'execution=' + execution.getId() +
331 msoLogger.trace('Entered ' + method)
333 String prefix = execution.getVariable('prefix')
336 int callbackNumber = 1
337 String callback = null
340 String thisCallback = (String) execution.getVariable(prefix + 'callback' + callbackNumber)
342 if (thisCallback == null) {
346 callback = thisCallback
351 } catch (Exception e) {
352 String msg = 'Caught exception in ' + method + ": " + e
354 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
355 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
360 * Sets the timeout value to wait for the next notification.
362 public void setTimeoutValue(DelegateExecution execution) {
363 def method = getClass().getSimpleName() + '.setTimeoutValue(' +
364 'execution=' + execution.getId() +
366 msoLogger.trace('Entered ' + method)
368 String prefix = execution.getVariable('prefix')
371 def timeoutValue = UrnPropertiesReader.getVariable("mso.adapters.sdnc.timeout", execution)
373 if (execution.getVariable(prefix + 'callback1') != null) {
374 // Waiting for subsequent notifications
376 } catch (Exception e) {
377 String msg = 'Caught exception in ' + method + ": " + e
379 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
380 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)