Initial OpenECOMP MSO commit
[so.git] / bpmn / MSOGammaBPMN / src / main / groovy / com / att / bpm / scripts / ExceptionUtil.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * OPENECOMP - MSO
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 com.att.bpm.scripts
22
23 import org.openecomp.mso.bpmn.core.WorkflowException
24
25 import org.camunda.bpm.engine.delegate.BpmnError
26 import org.camunda.bpm.engine.runtime.Execution
27 import org.apache.commons.lang3.*
28
29 import static org.apache.commons.lang3.StringUtils.*;
30
31 /**
32  * @version 1.0
33  */
34 class ExceptionUtil extends AbstractServiceTaskProcessor {
35
36         /**
37          *
38          * @Deprecated
39          *
40          * Instead use <method>MapAAIExceptionToWorkflowException</method>
41          *
42          * To Be Removed Once Refactoring Main Flow Error Handling Is Complete
43          *
44          *
45          */
46         @Deprecated
47         String MapAAIExceptionToWorkflowExceptionOld(String response, Execution execution)
48         {
49                 def utils=new MsoUtils()
50                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
51                 def prefix=execution.getVariable("prefix")
52                 def errorMsg = execution.getVariable(prefix+"ErrorResponse")
53                 utils.log("DEBUG","=========== Begin MapAAIExceptionToWorkflowException ===========",isDebugEnabled)
54                 String text = null
55                 def variables
56                 String errorCode = '5000'
57                 utils.log("DEBUG","response: " + response, isDebugEnabled)
58                 try {
59                         //String msg = utils.getNodeXml(response, "Fault")
60                          variables = utils.getMultNodes(response, "variable")
61                          text = utils.getNodeText1(response, "text")
62                 } catch (Exception ex) {
63                         //Ignore the exception - cases include non xml payload
64                         utils.log("DEBUG","error mapping error, ignoring: " + ex,isDebugEnabled)
65                 }
66
67                 if(text != null) {
68                         if(variables.size()>=4){
69                                 text = text.replaceFirst("%1", variables[0])
70                                 text = text.replaceFirst("%2", variables[1])
71                                 text = text.replaceFirst("%3", variables[2])
72                                 text = text.replaceFirst("%4", variables[3])
73                         }
74                         String modifiedErrorMessage = 'Received error from A&amp;AI (' + text +')'
75                         utils.log("DEBUG", "ModifiedErrorMessage " + modifiedErrorMessage, isDebugEnabled)
76                         // let $ModifiedErrorMessage := concat( 'Received error from A',$exceptionaai:ampersand,'AI (' ,functx:replace-multi($ErrorMessage,$from,$Variables ),')')
77                         String message = """<aetgt:WorkflowException xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1">
78                                 <aetgt:ErrorMessage>$modifiedErrorMessage</aetgt:ErrorMessage>
79                                 <aetgt:ErrorCode>$errorCode</aetgt:ErrorCode>
80                         </aetgt:WorkflowException>"""
81                          execution.setVariable(prefix+"ErrorResponse",message)
82                          utils.log("ERROR","Fault:"+ execution.getVariable(prefix+"ErrorResponse"))
83                          return message
84                 } else {
85                         try {
86                                 errorCode = MapErrorCode(errorMsg)
87                                 String mappedErrorMessage = MapErrorMessage(errorMsg, errorCode)
88
89                                 String message = """<aetgt:WorkflowException xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1">
90                                         <aetgt:ErrorMessage>$mappedErrorMessage</aetgt:ErrorMessage>
91                                         <aetgt:ErrorCode>$errorCode</aetgt:ErrorCode>
92                                 </aetgt:WorkflowException>"""
93                                 utils.log("DEBUG", "mappedErrorMessage " + mappedErrorMessage, isDebugEnabled)
94                                  execution.setVariable(prefix+"ErrorResponse",message)
95                                  utils.log("ERROR","Fault:"+ execution.getVariable(prefix+"ErrorResponse"))
96                                  return message
97                         } catch(Exception ex) {
98                                 utils.log("DEBUG","error mapping error, return null: " + ex,isDebugEnabled)
99                                 return null
100
101                         }
102                 }
103         }
104
105         /**
106          * This error handling method maps an AAI Exception response to a
107          * WorkflowException Object.  It then sets the WorkflowException Object
108          * on the execution as "WorkflowException".
109          *
110          * This method formats the exception from AAI into the WorkflowException's
111          * errorMessage that CCD expects.
112          *
113          * @param execution the execution
114          * @param response the aai exception
115          */
116         WorkflowException MapAAIExceptionToWorkflowException(String response, Execution execution)
117         {
118                 def utils=new MsoUtils()
119                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
120                 def prefix=execution.getVariable("prefix")
121                 def errorMsg = execution.getVariable(prefix+"ErrorResponse")
122                 utils.log("DEBUG","=========== Begin MapAAIExceptionToWorkflowException ===========",isDebugEnabled)
123                 String text = null
124                 def variables
125                 String errorCode = '5000'
126                 WorkflowException wfex
127                 utils.log("DEBUG","response: " + response, isDebugEnabled)
128                 try {
129                         //String msg = utils.getNodeXml(response, "Fault")
130                         variables = utils.getMultNodes(response, "variable")
131                         text = utils.getNodeText1(response, "text")
132                 } catch (Exception ex) {
133                         //Ignore the exception - cases include non xml payload
134                         utils.log("DEBUG","error mapping error, ignoring: " + ex,isDebugEnabled)
135                 }
136
137                 if(text != null) {
138                         if(variables.size()>=4){
139                                 text = text.replaceFirst("%1", variables[0])
140                                 text = text.replaceFirst("%2", variables[1])
141                                 text = text.replaceFirst("%3", variables[2])
142                                 text = text.replaceFirst("%4", variables[3])
143                         }
144                         String modifiedErrorMessage = 'Received error from A&amp;AI (' + text +')'
145                         utils.log("DEBUG", "ModifiedErrorMessage " + modifiedErrorMessage, isDebugEnabled)
146                         // let $ModifiedErrorMessage := concat( 'Received error from A',$exceptionaai:ampersand,'AI (' ,functx:replace-multi($ErrorMessage,$from,$Variables ),')')
147                         buildWorkflowException(execution, 5000, modifiedErrorMessage)
148
149                         wfex = execution.getVariable("WorkflowException")
150                         utils.log("ERROR","Fault:"+ wfex)
151                         return wfex
152                 } else {
153                         try {
154                                 errorCode = MapErrorCode(errorMsg)
155                                 String mappedErrorMessage = MapErrorMessage(errorMsg, errorCode)
156
157                                 int errorCodeInt = Integer.parseInt(errorCode)
158                                 buildWorkflowException(execution, errorCodeInt, mappedErrorMessage)
159
160                                 utils.log("DEBUG", "mappedErrorMessage " + mappedErrorMessage, isDebugEnabled)
161                                 wfex = execution.getVariable("WorkflowException")
162                                 utils.log("ERROR","Fault:"+ wfex, isDebugEnabled)
163                                 return wfex
164                         } catch(Exception ex) {
165                                 utils.log("DEBUG","error mapping error, return null: " + ex, isDebugEnabled)
166                                 return null
167
168                         }
169                 }
170         }
171
172         /**
173          * This error handling method maps an AAI Exception response to a
174          * WorkflowException Object.  It then sets the WorkflowException Object
175          * on the execution as "WorkflowException".
176          *
177          * This method takes the exact exception inside the <Fault> tags from AAI Response
178          * and puts it into the WorkflowException's errorMessage.
179          *
180          * @param execution the execution
181          * @param response the aai exception
182          */
183         WorkflowException MapAAIExceptionToWorkflowExceptionGeneric(Execution execution, String response, int resCode){
184                 def utils=new MsoUtils()
185                 def isDebugLogEnabled = execution.getVariable("isDebugLogEnabled")
186                 utils.log("DEBUG", "Start MapAAIExceptionToWorkflowExceptionGeneric Process", isDebugLogEnabled)
187
188                 WorkflowException wfex
189                 try {
190                         if(utils.nodeExists(response, "Fault")){
191                                 String fault = utils.getNodeXml(response, "Fault")
192                                 fault = utils.removeXmlPreamble(fault)
193                                 fault = fault.replace("<Fault>", "").replace("</Fault>", "")
194                                 fault = fault.replaceAll("\\s+\\s+", "") // Removes extra white spaces
195                                 buildWorkflowException(execution, resCode, fault)
196                         }else if(utils.nodeExists(response, "RESTFault")){
197                                 String rFault = utils.getNodeXml(response, "RESTFault")
198                                 buildWorkflowException(execution, resCode, rFault)
199                         }else{
200                                 buildWorkflowException(execution, resCode, "Received a bad response from AAI")
201                         }
202                 } catch (Exception ex) {
203                         utils.log("DEBUG", "Exception Occured during MapAAIExceptionToWorkflowExceptionGeneric: " + ex, isDebugLogEnabled)
204                         buildWorkflowException(execution, resCode, "Internal Error - Occured in MapAAIExceptionToWorkflowExceptionGeneric")
205
206                 }
207                 utils.log("DEBUG", "Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"), isDebugLogEnabled)
208                 utils.log("DEBUG", "Completed MapAAIExceptionToWorkflowExceptionGeneric Process", isDebugLogEnabled)
209         }
210
211         /**
212          *
213          *This method build a WorkflowException using the adapters response.
214          *
215          *@param String response
216          *@param String adapter
217          *
218          *@return WorkflowException wfex
219          */
220         WorkflowException MapAdapterExecptionToWorkflowException(String response, Execution execution, String adapter){
221                 def utils=new MsoUtils()
222                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
223                 def prefix=execution.getVariable("prefix")
224                 utils.log("DEBUG","=========== Start MapAdapterExecptionToWorkflowException Process ===========",isDebugEnabled)
225
226                 String errorCode
227                 def errorMessage
228                 WorkflowException wfex
229                 try {
230                         errorCode = MapCategoryToErrorCode(utils.getNodeText(response, "category"))
231                         errorMessage = MapAdapterErrorMessage(utils.getNodeText(response, "message"), errorCode, adapter)
232
233                         int errorCodeInt = Integer.parseInt(errorCode)
234                         buildWorkflowException(execution, errorCodeInt, errorMessage)
235                 }catch (Exception ex) {
236                         utils.log("DEBUG", "Exception Occured during MapAdapterExecptionToWorkflowException: " + ex, isDebugEnabled)
237                         buildWorkflowException(execution, 2500, "Internal Error - Occured in MapAdapterExecptionToWorkflowException")
238                 }
239                 wfex = execution.getVariable("WorkflowException")
240                 return wfex
241                 utils.log("DEBUG","=========== Completed MapAdapterExecptionToWorkflowException Process ===========",isDebugEnabled)
242         }
243
244
245         /**
246          *
247          * @Deprecated
248          *
249          * Instead use <method>buildWorkflowException(Execution execution, int errorCode, String errorMessage)</method> method below
250          *
251          * To Be Removed Once Refactoring Of Main Flow Error Handling Is Complete
252          *
253          */
254         @Deprecated
255         String buildWorkflowExceptionXml(String errorCode, String errorMessage) {
256                 return """<aetgt:WorkflowException xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1">
257                                         <aetgt:ErrorMessage>${errorMessage}</aetgt:ErrorMessage>
258                                         <aetgt:ErrorCode>${errorCode}</aetgt:ErrorCode>
259                                   </aetgt:WorkflowException>"""
260         }
261
262         /**
263          * This method takes a WorkflowException Object and builds
264          * WorkflowException Xml. This method should only be used
265          * for the purpose of sending an error response.
266          *
267          *@param - WorkflowException Object
268          *
269          *@return - String WorkflowException Xml
270          *
271          *
272          */
273         String buildErrorResponseXml(WorkflowException wfex) {
274                 String xml
275                 if(wfex != null){
276                         String mes = wfex.getErrorMessage()
277                         int code = wfex.getErrorCode()
278                         xml =
279                         """<aetgt:WorkflowException xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1">
280                                         <aetgt:ErrorMessage>${mes}</aetgt:ErrorMessage>
281                                         <aetgt:ErrorCode>${code}</aetgt:ErrorCode>
282                                   </aetgt:WorkflowException>"""
283
284                 }else{
285                         xml =
286                         """<aetgt:WorkflowException xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1">
287                                         <aetgt:ErrorMessage>Internal Error</aetgt:ErrorMessage>
288                                         <aetgt:ErrorCode>2500</aetgt:ErrorCode>
289                                   </aetgt:WorkflowException>"""
290                 }
291                 return xml
292         }
293
294         /*
295         5000    Received error from A&AI ($A&AI_ERROR)  Asynchronous    During orchestration of the recipe, A&AI returned an error. The error returned by A&AI is passed through in $A&AI_ERROR.
296         5010    Could not communicate with A&AI Asynchronous    During orchestration of the recipe, a connection with A&AI could not be established.
297         5020    No response from A&AI   Asynchronous    During orchestration of the recipe, communication was established with A&AI, but no response was received within the configured timeout.
298         */
299         String MapErrorCode(String errorMessage)
300         {
301                 if(errorMessage==null){
302                         return '5000'
303                 }
304                 errorMessage = errorMessage.toLowerCase();
305                 if(errorMessage.contains('timed out') || errorMessage.contains('timeout'))
306                         return '5020'
307                 else if (errorMessage.contains('connection'))
308                         return '5010'
309                 else
310                         return '5000'
311         }
312
313         String MapErrorMessage(String errorMessage, String errorCode)
314         {
315                 if(errorMessage == null){
316                         errorMessage=""
317                 }
318                 if( errorCode.equals('5010'))
319                                         return 'Could not communicate with A&amp;AI'
320                 else if (errorCode.equals('5020'))
321                         return 'No response from A&amp;AI'
322                 else
323                         return 'Received error from A&amp;AI (' +errorMessage +')'
324         }
325
326         String MapCategoryToErrorCode(String errorCategory)
327         {
328                 if(errorCategory.equals('OPENSTACK'))
329                         return '5100'
330                 else if (errorCategory.equals('IO'))
331                         return '5110'
332                 else if (errorCategory.equals('INTERNAL'))
333                         return '7020'
334                 else if (errorCategory.equals('USERDATA'))
335                         return '7020'
336                 else
337                         return '7020'
338         }
339
340
341         String MapAdapterErrorMessage(String errorMessage, String errorCode, String adapter)
342         {
343                 if(errorCode.equals('5100'))
344                         return 'Received error from Platform Orchestrator: ' + errorMessage
345                 else if(errorCode.equals('5110'))
346                     return 'Could not communicate with Platform Orchestrator'
347                 else
348                     return 'Received error from ' + adapter + ': ' + errorMessage
349         }
350
351         String MapSDNCResponseCodeToErrorCode(String sdncResponseCode)
352         {
353                 if (sdncResponseCode == '500') {
354                         return '5310'
355                 } else if ( sdncResponseCode == '408') {
356                          return '5320'
357                 } else if ( sdncResponseCode == '60010') {
358                          return '5350'
359                 } else {
360                    return '5300'
361                 }
362         }
363
364         /**
365          * This error handling method builds a WorkflowException Object.  It sets it on
366          * the execution as "WorkflowException".
367          *
368          * @param execution the execution
369          * @param errorCode the error code
370          * @param errorMessage the error message
371          */
372         public void buildWorkflowException(Execution execution, int errorCode, String errorMessage) {
373                 MsoUtils utils = new MsoUtils()
374                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
375                 String processKey = getProcessKey(execution);
376                 utils.log("DEBUG", "Building a WorkflowException for " + processKey, isDebugLogEnabled)
377
378                 WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage);
379                 execution.setVariable("WorkflowException", exception);
380                 utils.log("DEBUG", "Outgoing WorkflowException is " + exception, isDebugLogEnabled)
381         }
382
383         /**
384          * This error handling method builds a WorkflowException Object and throws a
385          * MSOWorkflowException.  It throws a "MSOWorkflowException" BpmnError after
386          * setting the WorkflowException Object on the execution as "WorkflowException".
387          *
388          * @param execution the execution
389          * @param errorCode the error code
390          * @param errorMessage the error message
391          */
392         public void buildAndThrowWorkflowException(Execution execution, int errorCode, String errorMessage) {
393                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
394                 String processKey = getProcessKey(execution);
395                 utils.log("Building a WorkflowException for Subflow " + processKey, isDebugLogEnabled)
396
397                 WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage);
398                 execution.setVariable("WorkflowException", exception);
399                 utils.log("DEBUG", "Outgoing WorkflowException is " + exception, isDebugLogEnabled)
400                 utils.log("DEBUG", "Throwing MSOWorkflowException", isDebugLogEnabled)
401                 throw new BpmnError("MSOWorkflowException")
402         }
403
404         /**
405          * This method is executed after an MSOWorkflowException is caught by a
406          * subflow (during subflows "Error Handling Sub Process").
407          * It ensures the WorkflowException variable is populated before ending the
408          * subflow and also logs the subflows outgoing WorkflowException Variable.
409          *
410          * @param - execution
411          *
412          */
413         public void processSubflowsBPMNException(Execution execution){
414                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
415                 String processKey = getProcessKey(execution)
416                 try{
417                         utils.log("DEBUG", "Started ProcessSubflowsBPMNException Method", isDebugEnabled)
418                         if(execution.getVariable("WorkflowException") == null){
419                                 buildWorkflowException(execution, 2500, "Internal Error - Occured During " + processKey)
420                         }
421
422                         utils.log("DEBUG", processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"), isDebugEnabled)
423                 }catch(Exception e){
424                         utils.log("DEBUG", "Caught Exception during ProcessSubflowsBPMNException Method: " + e, isDebugEnabled)
425                 }
426                 utils.log("DEBUG", "Completed ProcessSubflowsBPMNException Method", isDebugEnabled)
427         }
428
429         /**
430          * This method is executed after an MSOWorkflowException is caught by a
431          * Mainflow. It builds and returns a FalloutHandler Request. It also
432          * verifies the WorkflowException variable is populated.
433          *
434          * @param - execution
435          * @param - requestInfo
436          *
437          * @return - falloutHandlerRequest
438          *
439          */
440         public String processMainflowsBPMNException(Execution execution, String requestInfo){
441                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
442                 String processKey = getProcessKey(execution)
443                 try{
444                         utils.log("DEBUG", "Started ProcessMainflowBPMNException Method", isDebugEnabled)
445                         if(execution.getVariable("WorkflowException") == null || isBlank(requestInfo)){
446                                 buildWorkflowException(execution, 2500, "Internal Error - WorkflowException Object and/or RequestInfo is null! " + processKey)
447                         }
448                         requestInfo = utils.removeXmlPreamble(requestInfo)
449                         WorkflowException wfex = execution.getVariable("WorkflowException")
450                         String errorMessage = wfex.getErrorMessage()
451                         int errorCode = wfex.getErrorCode()
452
453                         String falloutHandlerRequest =
454                         """<aetgt:FalloutHandlerRequest xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1"
455                                                                      xmlns:ns="http://ecomp.att.com/mso/request/types/v1"
456                                                                      xmlns:wfsch="http://ecomp.att.com/mso/workflow/schema/v1">
457                                            ${requestInfo}
458                                                 <aetgt:WorkflowException xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1">
459                                                         <aetgt:ErrorMessage>${errorMessage}</aetgt:ErrorMessage>
460                                                         <aetgt:ErrorCode>${errorCode}</aetgt:ErrorCode>
461                                                 </aetgt:WorkflowException>
462                                         </aetgt:FalloutHandlerRequest>"""
463
464                         utils.log("DEBUG", processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"), isDebugEnabled)
465                         utils.log("DEBUG", processKey + " Outgoing FalloutHandler Request is: " + falloutHandlerRequest, isDebugEnabled)
466
467                         return falloutHandlerRequest
468
469                 }catch(Exception e){
470                         utils.log("DEBUG", "Caught Exception during ProcessMainflowBPMNException Method: " + e, isDebugEnabled)
471                         return null
472                 }
473                 utils.log("DEBUG", "Completed ProcessMainflowBPMNException Method", isDebugEnabled)
474         }
475
476         /**
477          * This method is executed after an Java Exception is caught.
478          * It sets the WorkflowException variable and throws an MSOWorkflowException.
479          *
480          * @param - execution
481          *
482          */
483         public void processSubflowsJavaException(Execution execution){
484                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
485                 String processKey = getProcessKey(execution)
486                 try{
487                         utils.log("DEBUG", "Caught a Java Exception in " + processKey, isDebugEnabled)
488                         utils.log("DEBUG", "Started processJavaException Method", isDebugEnabled)
489                         buildAndThrowWorkflowException(execution, 2500, "Catch a Java Lang Exception in " + processKey)
490
491                 }catch(BpmnError b){
492                         throw b
493                 }catch(Exception e){
494                         utils.log("DEBUG", "Caught Exception during processJavaException Method: " + e, isDebugEnabled)
495                         buildAndThrowWorkflowException(execution, 2500, "Internal Error - During Process Java Exception")
496                 }
497                 utils.log("DEBUG", "Completed processJavaException Method", isDebugEnabled)
498         }
499
500
501         public void preProcessRequest(Execution execution) {
502                 // TODO Auto-generated method stub
503
504         }
505
506
507
508
509 }