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("X-ONAP-RequestID", execution.getVariable("mso-request-id"))
212 httpClient.addAdditionalHeader("X-ONAP-InvocationID", UUID.randomUUID().toString())
213 httpClient.addAdditionalHeader("X-ONAP-PartnerName", "SO-SDNCAdapter")
214 httpClient.addAdditionalHeader("mso-request-id", execution.getVariable("mso-request-id"))
215 httpClient.addAdditionalHeader("mso-service-instance-id", execution.getVariable("mso-service-instance-id"))
216 httpClient.addAdditionalHeader("Authorization", execution.getVariable(prefix + "basicAuthHeaderValue"))
220 if ("GET".equals(sdncAdapterMethod)) {
221 response = httpClient.get()
222 } else if ("PUT".equals(sdncAdapterMethod)) {
223 response = httpClient.put(sdncAdapterRequest)
224 } else if ("POST".equals(sdncAdapterMethod)) {
225 response = httpClient.post(sdncAdapterRequest)
226 } else if ("DELETE".equals(sdncAdapterMethod)) {
227 response = httpClient.delete(sdncAdapterRequest)
229 String msg = 'Unsupported HTTP method "' + sdncAdapterMethod + '" in ' + method + ": " + e
231 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
232 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
235 execution.setVariable(prefix + "sdncAdapterStatusCode", response.getStatus())
236 if(response.hasEntity()){
237 execution.setVariable(prefix + "sdncAdapterResponse", response.readEntity(String.class))
239 } catch (BpmnError e) {
241 } catch (Exception e) {
242 String msg = 'Caught exception in ' + method + ": " + e
243 msoLogger.debug(msg, e)
244 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
245 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
250 * Processes a callback.
252 public void processCallback(DelegateExecution execution){
253 def method = getClass().getSimpleName() + '.processCallback(' +
254 'execution=' + execution.getId() +
256 msoLogger.trace('Entered ' + method)
258 String prefix = execution.getVariable('prefix')
259 String callback = execution.getVariable('SDNCAResponse_MESSAGE')
260 String requestId = execution.getVariable("mso-request-id");
261 String serviceInstanceId = execution.getVariable("mso-service-instance-id")
262 utils.logContext(requestId, serviceInstanceId)
263 msoLogger.debug("Incoming SDNC Rest Callback is: " + callback)
266 int callbackNumber = 1
267 while (execution.getVariable(prefix + 'callback' + callbackNumber) != null) {
271 execution.setVariable(prefix + 'callback' + callbackNumber, callback)
272 execution.removeVariable('SDNCAResponse_MESSAGE')
274 String responseType = jsonUtil.getJsonRootProperty(callback)
276 // Get the ackFinalIndicator and make sure it's either Y or N. Default to Y.
277 String ackFinalIndicator = jsonUtil.getJsonValue(callback, responseType + ".ackFinalIndicator")
279 if (!'N'.equals(ackFinalIndicator)) {
280 ackFinalIndicator = 'Y'
283 execution.setVariable(prefix + "ackFinalIndicator", ackFinalIndicator)
285 if (responseType.endsWith('Error')) {
286 sdncAdapterBuildWorkflowException(execution, callback)
288 } catch (Exception e) {
289 callback = callback == null || String.valueOf(callback).isEmpty() ? "NONE" : callback
290 String msg = "Received error from SDNCAdapter: " + callback
291 msoLogger.debug(getProcessKey(execution) + ': ' + msg)
292 exceptionUtil.buildWorkflowException(execution, 5300, msg)
297 * Tries to parse the response as XML to extract the information to create
298 * a WorkflowException. If the response cannot be parsed, a more generic
299 * WorkflowException is created.
301 public void sdncAdapterBuildWorkflowException(DelegateExecution execution, String response) {
303 String responseType = jsonUtil.getJsonRootProperty(response)
304 String responseCode = jsonUtil.getJsonValue(response, responseType + ".responseCode")
305 String responseMessage = jsonUtil.getJsonValue(response, responseType + ".responseMessage")
309 if (responseCode != null && !responseCode.isEmpty()) {
310 info += " responseCode='" + responseCode + "'"
313 if (responseMessage != null && !responseMessage.isEmpty()) {
314 info += " responseMessage='" + responseMessage + "'"
317 // Note: the mapping function handles a null or empty responseCode
318 int mappedResponseCode = Integer.parseInt(exceptionUtil.MapSDNCResponseCodeToErrorCode(responseCode));
319 exceptionUtil.buildWorkflowException(execution, mappedResponseCode, "Received " + responseType +
320 " from SDNCAdapter:" + info)
321 } catch (Exception e) {
322 response = response == null || String.valueOf(response).isEmpty() ? "NONE" : response
323 exceptionUtil.buildWorkflowException(execution, 5300, "Received error from SDNCAdapter: " + response)
328 * Gets the last callback request from the execution, or null if there was no callback.
330 public String getLastCallback(DelegateExecution execution) {
331 def method = getClass().getSimpleName() + '.getLastCallback(' +
332 'execution=' + execution.getId() +
334 msoLogger.trace('Entered ' + method)
336 String prefix = execution.getVariable('prefix')
339 int callbackNumber = 1
340 String callback = null
343 String thisCallback = (String) execution.getVariable(prefix + 'callback' + callbackNumber)
345 if (thisCallback == null) {
349 callback = thisCallback
354 } catch (Exception e) {
355 String msg = 'Caught exception in ' + method + ": " + e
357 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
358 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
363 * Sets the timeout value to wait for the next notification.
365 public void setTimeoutValue(DelegateExecution execution) {
366 def method = getClass().getSimpleName() + '.setTimeoutValue(' +
367 'execution=' + execution.getId() +
369 msoLogger.trace('Entered ' + method)
371 String prefix = execution.getVariable('prefix')
374 def timeoutValue = UrnPropertiesReader.getVariable("mso.adapters.sdnc.timeout", execution)
376 if (execution.getVariable(prefix + 'callback1') != null) {
377 // Waiting for subsequent notifications
379 } catch (Exception e) {
380 String msg = 'Caught exception in ' + method + ": " + e
382 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
383 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)