Merge "added check for null object"
[so.git] / bpmn / MSOCommonBPMN / src / main / groovy / org / onap / so / bpmn / common / scripts / SDNCAdapterRestV2.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.so.bpmn.common.scripts
22
23 import java.text.SimpleDateFormat
24 import java.net.URLEncoder
25
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
30
31 import groovy.json.*
32
33 import org.json.JSONObject
34
35 import org.onap.so.bpmn.core.WorkflowException
36 import org.onap.so.bpmn.core.json.JsonUtils
37 import org.onap.so.bpmn.core.UrnPropertiesReader
38 import org.onap.so.logger.MessageEnum
39 import org.onap.so.logger.MsoLogger
40
41
42
43 /**
44  * This version of SDNCAdapterRest allows for interim notifications to be sent for
45  * any non-final response received from SDNC.
46  */
47 class SDNCAdapterRestV2 extends SDNCAdapterRestV1 {
48         private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, SDNCAdapterRestV2.class);
49
50
51         ExceptionUtil exceptionUtil = new ExceptionUtil()
52         JsonUtils jsonUtil = new JsonUtils()
53
54         /**
55          * Processes the incoming request.
56          */
57         public void preProcessRequest (DelegateExecution execution) {
58                 def method = getClass().getSimpleName() + '.preProcessRequest(' +
59                         'execution=' + execution.getId() +
60                         ')'
61                 msoLogger.trace('Entered ' + method)
62
63                 def prefix="SDNCREST_"
64                 execution.setVariable("prefix", prefix)
65                 setSuccessIndicator(execution, false)
66
67                 try {
68                         // Determine the request type and log the request
69
70                         String request = validateRequest(execution, "mso-request-id")
71                         String requestType = jsonUtil.getJsonRootProperty(request)
72                         execution.setVariable(prefix + 'requestType', requestType)
73                         msoLogger.debug(getProcessKey(execution) + ': ' + prefix + 'requestType = ' + requestType)
74                         msoLogger.debug('SDNCAdapterRestV2, request: ' + request)
75
76                         // Determine the SDNCAdapter endpoint
77
78                         String sdncAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.sdnc.rest.endpoint",execution)
79
80                         if (sdncAdapterEndpoint == null || sdncAdapterEndpoint.isEmpty()) {
81                                 String msg = getProcessKey(execution) + ': mso:adapters:sdnc:rest:endpoint URN mapping is not defined'
82                                 msoLogger.debug(msg)
83                                 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
84                                 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
85                         }
86
87                         while (sdncAdapterEndpoint.endsWith('/')) {
88                                 sdncAdapterEndpoint = sdncAdapterEndpoint.substring(0, sdncAdapterEndpoint.length()-1)
89                         }
90
91                         String sdncAdapterMethod = null
92                         String sdncAdapterUrl = null
93                         String sdncAdapterRequest = request
94
95                         if ('SDNCServiceRequest'.equals(requestType)) {
96                                 // Get the sdncRequestId from the request
97
98                                 String sdncRequestId = jsonUtil.getJsonValue(request, requestType + ".sdncRequestId")
99
100                                 if (sdncRequestId == null || sdncRequestId.isEmpty()) {
101                                         String msg = getProcessKey(execution) + ': no sdncRequestId in ' + requestType
102                                         msoLogger.debug(msg)
103                                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
104                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
105                                 }
106
107                                 execution.setVariable('SDNCAResponse_CORRELATOR', sdncRequestId)
108                                 msoLogger.debug(getProcessKey(execution) + ': SDNCAResponse_CORRELATOR = ' + sdncRequestId)
109
110                                 // Get the bpNotificationUrl from the request (just to make sure it's there)
111
112                                 String bpNotificationUrl = jsonUtil.getJsonValue(request, requestType + ".bpNotificationUrl")
113
114                                 if (bpNotificationUrl == null || bpNotificationUrl.isEmpty()) {
115                                         String msg = getProcessKey(execution) + ': no bpNotificationUrl in ' + requestType
116                                         msoLogger.debug(msg)
117                                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
118                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
119                                 }
120
121                                 sdncAdapterMethod = 'POST'
122                                 sdncAdapterUrl = sdncAdapterEndpoint
123
124                         } else {
125                                 String msg = getProcessKey(execution) + ': Unsupported request type: ' + requestType
126                                 msoLogger.debug(msg)
127                                 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
128                                 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
129                         }
130
131                         execution.setVariable(prefix + 'sdncAdapterMethod', sdncAdapterMethod)
132                         msoLogger.debug(getProcessKey(execution) + ': ' + prefix + 'sdncAdapterMethod = ' + sdncAdapterMethod)
133                         execution.setVariable(prefix + 'sdncAdapterUrl', sdncAdapterUrl)
134                         msoLogger.debug(getProcessKey(execution) + ': ' + prefix + 'sdncAdapterUrl = ' + sdncAdapterUrl)
135                         execution.setVariable(prefix + 'sdncAdapterRequest', sdncAdapterRequest)
136                         msoLogger.debug(getProcessKey(execution) + ': ' + prefix + 'sdncAdapterRequest = \n' + sdncAdapterRequest)
137
138                         // Get the Basic Auth credentials for the SDNCAdapter (yes... we ARE using the PO adapters credentials)
139
140                         String basicAuthValue = UrnPropertiesReader.getVariable("mso.adapters.po.auth",execution)
141
142                         if (basicAuthValue == null || basicAuthValue.isEmpty()) {
143                                 msoLogger.debug(getProcessKey(execution) + ": mso:adapters:po:auth URN mapping is not defined")
144                                 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, getProcessKey(execution) + ": mso:adapters:po:auth URN mapping is not defined", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
145                         } else {
146                                 try {
147                                         def encodedString = utils.getBasicAuth(basicAuthValue, UrnPropertiesReader.getVariable("mso.msoKey", execution))
148                                         execution.setVariable(prefix + 'basicAuthHeaderValue', encodedString)
149                                 } catch (IOException ex) {
150                                         msoLogger.debug(getProcessKey(execution) + ": Unable to encode BasicAuth credentials for SDNCAdapter")
151                                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, getProcessKey(execution) + ": Unable to encode BasicAuth credentials for SDNCAdapter", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
152                                 }
153                         }
154
155                         // Set the timeout value, e.g. PT5M. It may be specified in the request as the
156                         // bpTimeout value.  If it's not in the request, use the URN mapping value.
157
158                         String timeout = jsonUtil.getJsonValue(request, requestType + ".bpTimeout")
159
160                         // in addition to null/empty, also need to verify that the timer value is a valid duration "P[n]T[n]H|M|S"
161                         String timerRegex = "PT[0-9]+[HMS]";
162                         if (timeout == null || timeout.isEmpty() || !timeout.matches(timerRegex)) {
163                                 msoLogger.debug(getProcessKey(execution) + ': preProcessRequest(): null/empty/invalid bpTimeout value. Using "mso.adapters.sdnc.timeout"')
164                                 timeout = UrnPropertiesReader.getVariable("mso.adapters.sdnc.timeout", execution)
165                         }
166
167                         // the timeout could still be null at this point if the config parm is missing/undefined
168                         // forced to log (so OPs can fix the config) and temporarily use a hard coded value of 10 seconds
169                         if (timeout == null) {
170                                 msoLogger.warnSimple('preProcessRequest()', 'property "mso.adapters.sdnc.timeout" is missing/undefined. Using "PT10S"')
171                                 timeout = "PT10S"
172                         }
173
174                         execution.setVariable(prefix + 'timeout', timeout)
175                         msoLogger.debug(getProcessKey(execution) + ': ' + prefix + 'timeout = ' + timeout)
176                 } catch (BpmnError e) {
177                         throw e
178                 } catch (Exception e) {
179                         String msg = 'Caught exception in ' + method + ": " + e
180                         msoLogger.debug(msg)
181                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
182                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
183                 }
184         }
185
186         /**
187          * Processes a callback. Check for possible interim notification.
188          */
189         public void processCallback(DelegateExecution execution){
190                 def method = getClass().getSimpleName() + '.processCallback(' +
191                         'execution=' + execution.getId() +
192                         ')'
193                 msoLogger.trace('Entered ' + method)
194
195                 String prefix = execution.getVariable('prefix')
196                 String callback = execution.getVariable('SDNCAResponse_MESSAGE')
197                 msoLogger.debug("Incoming SDNC Rest Callback is: " + callback)
198
199                 try {
200                         msoLogger.debug(getProcessKey(execution) + ": received callback:\n" + callback)
201
202                         int callbackNumber = 1
203                         while (execution.getVariable(prefix + 'callback' + callbackNumber) != null) {
204                                 ++callbackNumber
205                         }
206
207                         execution.setVariable(prefix + 'callback' + callbackNumber, callback)
208                         execution.removeVariable('SDNCAResponse_MESSAGE')
209
210                         String responseType = jsonUtil.getJsonRootProperty(callback)
211
212                         // Get the ackFinalIndicator and make sure it's either Y or N.  Default to Y.
213                         String ackFinalIndicator = jsonUtil.getJsonValue(callback, responseType + ".ackFinalIndicator")
214
215                         if (!'N'.equals(ackFinalIndicator)) {
216                                 ackFinalIndicator = 'Y'
217                         }
218
219                         execution.setVariable(prefix + "ackFinalIndicator", ackFinalIndicator)
220
221                         if (responseType.endsWith('Error')) {
222                                 sdncAdapterBuildWorkflowException(execution, callback)
223                         }
224
225                         // Check for possible interim notification
226                         execution.setVariable(prefix + "interimNotification", null)
227                         execution.setVariable(prefix + "doInterimNotification", false)
228                         if ('N'.equals(ackFinalIndicator)) {
229                                 def interimNotification = execution.getVariable(prefix + "InterimNotification" + callbackNumber)
230                                 if (interimNotification != null) {
231                                         execution.setVariable(prefix + "interimNotification", interimNotification)
232                                         execution.setVariable(prefix + "doInterimNotification", true)
233                                 }
234                         }
235
236                 } catch (Exception e) {
237                         callback = callback == null || String.valueOf(callback).isEmpty() ? "NONE" : callback
238                         String msg = "Received error from SDNCAdapter: " + callback
239                         msoLogger.debug(getProcessKey(execution) + ': ' + msg)
240                         exceptionUtil.buildWorkflowException(execution, 5300, msg)
241                 }
242         }
243
244         /**
245          * Prepare to send an interim notification by extracting the variable/value definitions
246          * in the interimNotification JSON object and placing them in the execution.  These
247          * variable/value definitions will be passed to the notification service.
248          */
249         public void prepareInterimNotification(DelegateExecution execution) {
250                 def method = getClass().getSimpleName() + '.prepareInterimNotification(' +
251                         'execution=' + execution.getId() +
252                         ')'
253                 msoLogger.trace('Entered ' + method)
254
255                 String prefix = execution.getVariable('prefix')
256                 msoLogger.debug("Preparing Interim Notification")
257
258                 try {
259                         def interimNotification = execution.getVariable(prefix + "interimNotification")
260                         msoLogger.debug("Preparing Interim Notification:\n" + JsonUtils.prettyJson(interimNotification))
261
262                         for (int i = 0; ; i++) {
263                                 def variable = JsonUtils.getJsonParamValue(interimNotification, 'variableList', 'variable', i)
264
265                                 if (variable == null) {
266                                         break
267                                 }
268
269                                 def String variableName = JsonUtils.getJsonValue(variable, "name")
270                                 if ((variableName != null) && !variableName.isEmpty()) {
271                                         def variableValue = JsonUtils.getJsonValue(variable, "value")
272                                         execution.setVariable(variableName, variableValue)
273                                         msoLogger.debug("Setting "+ variableName + "=" + variableValue)
274                                 }
275                         }
276
277                 } catch (Exception e) {
278                         String msg = "Error preparing interim notification"
279                         msoLogger.debug(getProcessKey(execution) + ': ' + msg)
280                         exceptionUtil.buildWorkflowException(execution, 5300, msg)
281                 }
282         }
283 }