Containerization feature of SO
[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.rest.APIResponse
38 import org.onap.so.rest.RESTClient
39 import org.onap.so.rest.RESTConfig
40 import org.onap.so.bpmn.core.UrnPropertiesReader
41 import org.onap.so.logger.MessageEnum
42 import org.onap.so.logger.MsoLogger
43
44
45
46 /**
47  * This version of SDNCAdapterRest allows for interim notifications to be sent for
48  * any non-final response received from SDNC.
49  */
50 class SDNCAdapterRestV2 extends SDNCAdapterRestV1 {
51         private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, SDNCAdapterRestV2.class);
52
53
54         ExceptionUtil exceptionUtil = new ExceptionUtil()
55         JsonUtils jsonUtil = new JsonUtils()
56
57         /**
58          * Processes the incoming request.
59          */
60         public void preProcessRequest (DelegateExecution execution) {
61                 def method = getClass().getSimpleName() + '.preProcessRequest(' +
62                         'execution=' + execution.getId() +
63                         ')'
64                 msoLogger.trace('Entered ' + method)
65
66                 def prefix="SDNCREST_"
67                 execution.setVariable("prefix", prefix)
68                 setSuccessIndicator(execution, false)
69
70                 try {
71                         // Determine the request type and log the request
72
73                         String request = validateRequest(execution, "mso-request-id")
74                         String requestType = jsonUtil.getJsonRootProperty(request)
75                         execution.setVariable(prefix + 'requestType', requestType)
76                         msoLogger.debug(getProcessKey(execution) + ': ' + prefix + 'requestType = ' + requestType)
77                         msoLogger.debug('SDNCAdapterRestV2, request: ' + request)
78
79                         // Determine the SDNCAdapter endpoint
80
81                         String sdncAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.sdnc.rest.endpoint",execution)
82
83                         if (sdncAdapterEndpoint == null || sdncAdapterEndpoint.isEmpty()) {
84                                 String msg = getProcessKey(execution) + ': mso:adapters:sdnc:rest:endpoint URN mapping is not defined'
85                                 msoLogger.debug(msg)
86                                 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
87                                 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
88                         }
89
90                         while (sdncAdapterEndpoint.endsWith('/')) {
91                                 sdncAdapterEndpoint = sdncAdapterEndpoint.substring(0, sdncAdapterEndpoint.length()-1)
92                         }
93
94                         String sdncAdapterMethod = null
95                         String sdncAdapterUrl = null
96                         String sdncAdapterRequest = request
97
98                         if ('SDNCServiceRequest'.equals(requestType)) {
99                                 // Get the sdncRequestId from the request
100
101                                 String sdncRequestId = jsonUtil.getJsonValue(request, requestType + ".sdncRequestId")
102
103                                 if (sdncRequestId == null || sdncRequestId.isEmpty()) {
104                                         String msg = getProcessKey(execution) + ': no sdncRequestId in ' + requestType
105                                         msoLogger.debug(msg)
106                                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
107                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
108                                 }
109
110                                 execution.setVariable('SDNCAResponse_CORRELATOR', sdncRequestId)
111                                 msoLogger.debug(getProcessKey(execution) + ': SDNCAResponse_CORRELATOR = ' + sdncRequestId)
112
113                                 // Get the bpNotificationUrl from the request (just to make sure it's there)
114
115                                 String bpNotificationUrl = jsonUtil.getJsonValue(request, requestType + ".bpNotificationUrl")
116
117                                 if (bpNotificationUrl == null || bpNotificationUrl.isEmpty()) {
118                                         String msg = getProcessKey(execution) + ': no bpNotificationUrl in ' + requestType
119                                         msoLogger.debug(msg)
120                                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
121                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
122                                 }
123
124                                 sdncAdapterMethod = 'POST'
125                                 sdncAdapterUrl = sdncAdapterEndpoint
126
127                         } else {
128                                 String msg = getProcessKey(execution) + ': Unsupported request type: ' + requestType
129                                 msoLogger.debug(msg)
130                                 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
131                                 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
132                         }
133
134                         execution.setVariable(prefix + 'sdncAdapterMethod', sdncAdapterMethod)
135                         msoLogger.debug(getProcessKey(execution) + ': ' + prefix + 'sdncAdapterMethod = ' + sdncAdapterMethod)
136                         execution.setVariable(prefix + 'sdncAdapterUrl', sdncAdapterUrl)
137                         msoLogger.debug(getProcessKey(execution) + ': ' + prefix + 'sdncAdapterUrl = ' + sdncAdapterUrl)
138                         execution.setVariable(prefix + 'sdncAdapterRequest', sdncAdapterRequest)
139                         msoLogger.debug(getProcessKey(execution) + ': ' + prefix + 'sdncAdapterRequest = \n' + sdncAdapterRequest)
140
141                         // Get the Basic Auth credentials for the SDNCAdapter (yes... we ARE using the PO adapters credentials)
142
143                         String basicAuthValue = UrnPropertiesReader.getVariable("mso.adapters.po.auth",execution)
144
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, "");
148                         } else {
149                                 try {
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, "");
155                                 }
156                         }
157
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.
160
161                         String timeout = jsonUtil.getJsonValue(request, requestType + ".bpTimeout")
162
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)
168                         }
169
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"')
174                                 timeout = "PT10S"
175                         }
176
177                         execution.setVariable(prefix + 'timeout', timeout)
178                         msoLogger.debug(getProcessKey(execution) + ': ' + prefix + 'timeout = ' + timeout)
179                 } catch (BpmnError e) {
180                         throw e
181                 } catch (Exception e) {
182                         String msg = 'Caught exception in ' + method + ": " + e
183                         msoLogger.debug(msg)
184                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
185                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
186                 }
187         }
188
189         /**
190          * Processes a callback. Check for possible interim notification.
191          */
192         public void processCallback(DelegateExecution execution){
193                 def method = getClass().getSimpleName() + '.processCallback(' +
194                         'execution=' + execution.getId() +
195                         ')'
196                 msoLogger.trace('Entered ' + method)
197
198                 String prefix = execution.getVariable('prefix')
199                 String callback = execution.getVariable('SDNCAResponse_MESSAGE')
200                 msoLogger.debug("Incoming SDNC Rest Callback is: " + callback)
201
202                 try {
203                         msoLogger.debug(getProcessKey(execution) + ": received callback:\n" + callback)
204
205                         int callbackNumber = 1
206                         while (execution.getVariable(prefix + 'callback' + callbackNumber) != null) {
207                                 ++callbackNumber
208                         }
209
210                         execution.setVariable(prefix + 'callback' + callbackNumber, callback)
211                         execution.removeVariable('SDNCAResponse_MESSAGE')
212
213                         String responseType = jsonUtil.getJsonRootProperty(callback)
214
215                         // Get the ackFinalIndicator and make sure it's either Y or N.  Default to Y.
216                         String ackFinalIndicator = jsonUtil.getJsonValue(callback, responseType + ".ackFinalIndicator")
217
218                         if (!'N'.equals(ackFinalIndicator)) {
219                                 ackFinalIndicator = 'Y'
220                         }
221
222                         execution.setVariable(prefix + "ackFinalIndicator", ackFinalIndicator)
223
224                         if (responseType.endsWith('Error')) {
225                                 sdncAdapterBuildWorkflowException(execution, callback)
226                         }
227                         
228                         // Check for possible interim notification
229                         execution.setVariable(prefix + "interimNotification", null)
230                         execution.setVariable(prefix + "doInterimNotification", false)
231                         if ('N'.equals(ackFinalIndicator)) {
232                                 def interimNotification = execution.getVariable(prefix + "InterimNotification" + callbackNumber)
233                                 if (interimNotification != null) {
234                                         execution.setVariable(prefix + "interimNotification", interimNotification)
235                                         execution.setVariable(prefix + "doInterimNotification", true)
236                                 }
237                         }
238                         
239                 } catch (Exception e) {
240                         callback = callback == null || String.valueOf(callback).isEmpty() ? "NONE" : callback
241                         String msg = "Received error from SDNCAdapter: " + callback
242                         msoLogger.debug(getProcessKey(execution) + ': ' + msg)
243                         exceptionUtil.buildWorkflowException(execution, 5300, msg)
244                 }
245         }
246         
247         /**
248          * Prepare to send an interim notification by extracting the variable/value definitions
249          * in the interimNotification JSON object and placing them in the execution.  These
250          * variable/value definitions will be passed to the notification service.
251          */
252         public void prepareInterimNotification(DelegateExecution execution) {
253                 def method = getClass().getSimpleName() + '.prepareInterimNotification(' +
254                         'execution=' + execution.getId() +
255                         ')'
256                 msoLogger.trace('Entered ' + method)
257                 
258                 String prefix = execution.getVariable('prefix')
259                 msoLogger.debug("Preparing Interim Notification")
260
261                 try {
262                         def interimNotification = execution.getVariable(prefix + "interimNotification")
263                         msoLogger.debug("Preparing Interim Notification:\n" + JsonUtils.prettyJson(interimNotification))
264                         
265                         for (int i = 0; ; i++) {
266                                 def variable = JsonUtils.getJsonParamValue(interimNotification, 'variableList', 'variable', i)
267                                 
268                                 if (variable == null) {
269                                         break
270                                 }
271                                 
272                                 def String variableName = JsonUtils.getJsonValue(variable, "name")
273                                 if ((variableName != null) && !variableName.isEmpty()) {
274                                         def variableValue = JsonUtils.getJsonValue(variable, "value")
275                                         execution.setVariable(variableName, variableValue)
276                                         msoLogger.debug("Setting "+ variableName + "=" + variableValue)
277                                 }
278                         }
279                         
280                 } catch (Exception e) {
281                         String msg = "Error preparing interim notification"
282                         msoLogger.debug(getProcessKey(execution) + ': ' + msg)
283                         exceptionUtil.buildWorkflowException(execution, 5300, msg)
284                 }
285         }
286 }