Groovy scripts header correction
[so.git] / bpmn / MSOCommonBPMN / src / main / groovy / org / openecomp / mso / bpmn / common / scripts / ExceptionUtil.groovy
1 /*-\r
2  * ============LICENSE_START=======================================================\r
3  * ONAP - SO\r
4  * ================================================================================\r
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.\r
6  * ================================================================================\r
7  * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * you may not use this file except in compliance with the License.\r
9  * You may obtain a copy of the License at\r
10  * \r
11  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  * \r
13  * Unless required by applicable law or agreed to in writing, software\r
14  * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * See the License for the specific language governing permissions and\r
17  * limitations under the License.\r
18  * ============LICENSE_END=========================================================\r
19  */\r
20 \r
21 package org.openecomp.mso.bpmn.common.scripts\r
22 \r
23 import static org.apache.commons.lang3.StringUtils.*\r
24 \r
25 import org.apache.commons.lang3.*\r
26 import org.camunda.bpm.engine.delegate.BpmnError\r
27 import org.camunda.bpm.engine.runtime.Execution\r
28 import org.openecomp.mso.bpmn.core.WorkflowException\r
29 \r
30 /**\r
31  * @version 1.0\r
32  */\r
33 class ExceptionUtil extends AbstractServiceTaskProcessor {\r
34 \r
35 \r
36         /**\r
37          * This error handling method maps an AAI Exception response to a\r
38          * WorkflowException Object.  It then sets the WorkflowException Object\r
39          * on the execution as "WorkflowException".\r
40          *\r
41          * This method formats the exception from AAI into the WorkflowException's\r
42          * errorMessage that CCD expects.\r
43          *\r
44          * @param execution the execution\r
45          * @param response the aai exception\r
46          */\r
47         WorkflowException MapAAIExceptionToWorkflowException(String response, Execution execution)\r
48         {\r
49                 def utils=new MsoUtils()\r
50                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")\r
51                 def prefix=execution.getVariable("prefix")\r
52                 def errorMsg = execution.getVariable(prefix+"ErrorResponse")\r
53                 utils.log("DEBUG","=========== Begin MapAAIExceptionToWorkflowException ===========",isDebugEnabled)\r
54                 String text = null\r
55                 def variables\r
56                 String errorCode = '5000'\r
57                 WorkflowException wfex\r
58                 utils.log("DEBUG","response: " + response, isDebugEnabled)\r
59                 try{\r
60                 try {\r
61                         //String msg = utils.getNodeXml(response, "Fault")\r
62                         variables = utils.getMultNodes(response, "variable")\r
63                         text = utils.getNodeText1(response, "text")\r
64                 } catch (Exception ex) {\r
65                         //Ignore the exception - cases include non xml payload\r
66                         utils.log("DEBUG","error mapping error, ignoring: " + ex,isDebugEnabled)\r
67                 }\r
68 \r
69                 if(text != null) {\r
70                         if(variables.size()>=4){\r
71                                 text = text.replaceFirst("%1", variables[0])\r
72                                 text = text.replaceFirst("%2", variables[1])\r
73                                 text = text.replaceFirst("%3", variables[2])\r
74                                 text = text.replaceFirst("%4", variables[3])\r
75                         }\r
76                         String modifiedErrorMessage = 'Received error from A&AI (' + text +')'\r
77                         utils.log("DEBUG", "ModifiedErrorMessage " + modifiedErrorMessage, isDebugEnabled)\r
78                         // let $ModifiedErrorMessage := concat( 'Received error from A',$exceptionaai:ampersand,'AI (' ,functx:replace-multi($ErrorMessage,$from,$Variables ),')')\r
79                         buildWorkflowException(execution, 5000, modifiedErrorMessage)\r
80 \r
81                         wfex = execution.getVariable("WorkflowException")\r
82                         utils.log("ERROR","Fault:"+ wfex)\r
83                         return wfex\r
84                 } else {\r
85                         try {\r
86                                 errorCode = MapErrorCode(errorMsg)\r
87                                 String mappedErrorMessage = MapErrorMessage(errorMsg, errorCode)\r
88 \r
89                                 int errorCodeInt = Integer.parseInt(errorCode)\r
90                                 buildWorkflowException(execution, errorCodeInt, mappedErrorMessage)\r
91 \r
92                                 utils.log("DEBUG", "mappedErrorMessage " + mappedErrorMessage, isDebugEnabled)\r
93                                 wfex = execution.getVariable("WorkflowException")\r
94                                 utils.log("ERROR","Fault:"+ wfex, isDebugEnabled)\r
95                                 return wfex\r
96                         } catch(Exception ex) {\r
97                                 utils.log("DEBUG","error mapping error, return null: " + ex, isDebugEnabled)\r
98                                 return null\r
99 \r
100                         }\r
101                 }\r
102                 }catch(Exception e){\r
103                         utils.log("DEBUG", "Exception occured during MapAAIExceptionToWorkflowException: " + e, isDebugEnabled)\r
104                         buildWorkflowException(execution, 5000, "Error mapping AAI Response to WorkflowException")\r
105                 }\r
106         }\r
107 \r
108         /**\r
109          * This error handling method maps an AAI Exception response to a\r
110          * WorkflowException Object.  It then sets the WorkflowException Object\r
111          * on the execution as "WorkflowException".\r
112          *\r
113          * This method takes the exact exception inside the <Fault> tags from AAI Response\r
114          * and puts it into the WorkflowException's errorMessage.\r
115          *\r
116          * @param execution the execution\r
117          * @param response the aai exception\r
118          */\r
119         WorkflowException MapAAIExceptionToWorkflowExceptionGeneric(Execution execution, String response, int resCode){\r
120                 def utils=new MsoUtils()\r
121                 def isDebugLogEnabled = execution.getVariable("isDebugLogEnabled")\r
122                 utils.log("DEBUG", "Start MapAAIExceptionToWorkflowExceptionGeneric Process", isDebugLogEnabled)\r
123 \r
124                 WorkflowException wfex\r
125                 try {\r
126                         if(utils.nodeExists(response, "Fault")){\r
127                                 String fault = utils.getNodeXml(response, "Fault")\r
128                                 fault = utils.removeXmlPreamble(fault)\r
129                                 fault = fault.replace("<Fault>", "").replace("</Fault>", "")\r
130                                 fault = fault.replaceAll("\\s+\\s+", "") // Removes extra white spaces\r
131                                 buildWorkflowException(execution, resCode, fault)\r
132                         }else if(utils.nodeExists(response, "RESTFault")){\r
133                                 String rFault = utils.getNodeXml(response, "RESTFault")\r
134                                 buildWorkflowException(execution, resCode, rFault)\r
135                         }else{\r
136                                 buildWorkflowException(execution, resCode, "Received a bad response from AAI")\r
137                         }\r
138                 } catch (Exception ex) {\r
139                         utils.log("DEBUG", "Exception Occured during MapAAIExceptionToWorkflowExceptionGeneric: " + ex, isDebugLogEnabled)\r
140                         buildWorkflowException(execution, resCode, "Internal Error - Occured in MapAAIExceptionToWorkflowExceptionGeneric")\r
141 \r
142                 }\r
143                 utils.log("DEBUG", "Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"), isDebugLogEnabled)\r
144                 utils.log("DEBUG", "Completed MapAAIExceptionToWorkflowExceptionGeneric Process", isDebugLogEnabled)\r
145         }\r
146 \r
147         /**\r
148          * This method takes a WorkflowException Object and builds\r
149          * WorkflowException Xml. This method should only be used\r
150          * for the purpose of sending a sync error response or for\r
151          * creating a FalloutHandler request.\r
152          *\r
153          *@param - WorkflowException Object\r
154          *\r
155          *@return - String WorkflowException Xml\r
156          *\r
157          *\r
158          */\r
159         String buildErrorResponseXml(WorkflowException wfex) {\r
160                 String xml\r
161                 if(wfex != null){\r
162                         String mes = wfex.getErrorMessage()\r
163                         int code = wfex.getErrorCode()\r
164                         xml =\r
165                         """<aetgt:WorkflowException xmlns:aetgt="http://org.openecomp/mso/workflow/schema/v1">\r
166                                         <aetgt:ErrorMessage>${mes}</aetgt:ErrorMessage>\r
167                                         <aetgt:ErrorCode>${code}</aetgt:ErrorCode>\r
168                                   </aetgt:WorkflowException>"""\r
169 \r
170                 }else{\r
171                         xml =\r
172                         """<aetgt:WorkflowException xmlns:aetgt="http://org.openecomp/mso/workflow/schema/v1">\r
173                                         <aetgt:ErrorMessage>Internal Error</aetgt:ErrorMessage>\r
174                                         <aetgt:ErrorCode>2500</aetgt:ErrorCode>\r
175                                   </aetgt:WorkflowException>"""\r
176                 }\r
177                 return xml\r
178         }\r
179 \r
180         /*\r
181         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.\r
182         5010    Could not communicate with A&AI Asynchronous    During orchestration of the recipe, a connection with A&AI could not be established.\r
183         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.\r
184         */\r
185         /**\r
186          *\r
187          * Utility Method for MapAAIExceptionToWorkflowException\r
188          *\r
189          *@param - String ErrorMessage\r
190          *\r
191          *@return - String ErrorCode\r
192          *\r
193          */\r
194         private String MapErrorCode(String errorMessage)\r
195         {\r
196                 if(errorMessage==null){\r
197                         return '5000'\r
198                 }\r
199                 errorMessage = errorMessage.toLowerCase();\r
200                 if(errorMessage.contains('timed out') || errorMessage.contains('timeout'))\r
201                         return '5020'\r
202                 else if (errorMessage.contains('connection'))\r
203                         return '5010'\r
204                 else\r
205                         return '5000'\r
206         }\r
207 \r
208         /**\r
209          *\r
210          * Utility Method for MapAAIExceptionToWorkflowException\r
211          *\r
212          *@param - String ErrorMessage\r
213          *@param - String ErrorCode\r
214          *\r
215          *@return - String ErrorMessage\r
216          *\r
217          */\r
218         private String MapErrorMessage(String errorMessage, String errorCode)\r
219         {\r
220                 if(errorMessage == null){\r
221                         errorMessage=""\r
222                 }\r
223                 if( errorCode.equals('5010')){\r
224                                         return 'Could not communicate with A&amp;AI'\r
225                 }else if (errorCode.equals('5020')){\r
226                         return 'No response from A&amp;AI'\r
227                 }else{\r
228                         errorMessage = errorMessage.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")\r
229                         return 'Received error from A&amp;AI (' +errorMessage +')'\r
230                 }\r
231         }\r
232 \r
233         /**\r
234          *\r
235          * Utility Method for Mapping SDNC\r
236          * Adapter Response Codes\r
237          *\r
238          *@param - String sdncResponseCode\r
239          *\r
240          *@return - String code\r
241          *\r
242          */\r
243         String MapSDNCResponseCodeToErrorCode(String sdncResponseCode)\r
244         {\r
245                 if (sdncResponseCode == '500') {\r
246                         return '5310'\r
247                 } else if ( sdncResponseCode == '408') {\r
248                          return '5320'\r
249                 } else if ( sdncResponseCode == '60010') {\r
250                          return '5350'\r
251                 } else {\r
252                    return '5300'\r
253                 }\r
254         }\r
255 \r
256         /**\r
257          * This error handling method builds a WorkflowException Object.  It sets it on\r
258          * the execution as "WorkflowException".\r
259          *\r
260          * @param execution the execution\r
261          * @param errorCode the error code\r
262          * @param errorMessage the error message\r
263          */\r
264         public void buildWorkflowException(Execution execution, int errorCode, String errorMessage) {\r
265                 MsoUtils utils = new MsoUtils()\r
266                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')\r
267                 String processKey = getProcessKey(execution);\r
268                 utils.log("DEBUG", "Building a WorkflowException for " + processKey, isDebugLogEnabled)\r
269 \r
270                 WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage);\r
271                 execution.setVariable("WorkflowException", exception);\r
272                 utils.log("DEBUG", "Outgoing WorkflowException is " + exception, isDebugLogEnabled)\r
273         }\r
274 \r
275         /**\r
276          * This error handling method builds a WorkflowException Object and throws a\r
277          * MSOWorkflowException.  It throws a "MSOWorkflowException" BpmnError after\r
278          * setting the WorkflowException Object on the execution as "WorkflowException".\r
279          *\r
280          * @param execution the execution\r
281          * @param errorCode the error code\r
282          * @param errorMessage the error message\r
283          */\r
284         public void buildAndThrowWorkflowException(Execution execution, int errorCode, String errorMessage) {\r
285                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')\r
286                 String processKey = getProcessKey(execution);\r
287                 utils.log("Building a WorkflowException for Subflow " + processKey, isDebugLogEnabled)\r
288 \r
289                 WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage);\r
290                 execution.setVariable("WorkflowException", exception);\r
291                 utils.log("DEBUG", "Outgoing WorkflowException is " + exception, isDebugLogEnabled)\r
292                 utils.log("DEBUG", "Throwing MSOWorkflowException", isDebugLogEnabled)\r
293                 throw new BpmnError("MSOWorkflowException")\r
294         }\r
295 \r
296         /**\r
297          * This method is executed after an MSOWorkflowException is caught by a\r
298          * subflow (during subflows "Error Handling Sub Process").\r
299          * It ensures the WorkflowException variable is populated before ending the\r
300          * subflow and also logs the subflows outgoing WorkflowException Variable.\r
301          *\r
302          * @param - execution\r
303          *\r
304          */\r
305         public void processSubflowsBPMNException(Execution execution){\r
306                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")\r
307                 String processKey = getProcessKey(execution)\r
308                 try{\r
309                         utils.log("DEBUG", "Started ProcessSubflowsBPMNException Method", isDebugEnabled)\r
310                         if(execution.getVariable("WorkflowException") == null){\r
311                                 buildWorkflowException(execution, 2500, "Internal Error - Occured During " + processKey)\r
312                         }\r
313 \r
314                         utils.log("DEBUG", processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"), isDebugEnabled)\r
315                 }catch(Exception e){\r
316                         utils.log("DEBUG", "Caught Exception during ProcessSubflowsBPMNException Method: " + e, isDebugEnabled)\r
317                 }\r
318                 utils.log("DEBUG", "Completed ProcessSubflowsBPMNException Method", isDebugEnabled)\r
319         }\r
320 \r
321         /**\r
322          * This method is executed after an MSOWorkflowException is caught by a\r
323          * Mainflow. It builds and returns a FalloutHandler Request. It also\r
324          * verifies the WorkflowException variable is populated.\r
325          *\r
326          * @param - execution\r
327          * @param - requestInfo\r
328          *\r
329          * @return - falloutHandlerRequest\r
330          *\r
331          */\r
332         public String processMainflowsBPMNException(Execution execution, String requestInfo){\r
333                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")\r
334                 String processKey = getProcessKey(execution)\r
335                 try{\r
336                         utils.log("DEBUG", "Started ProcessMainflowBPMNException Method", isDebugEnabled)\r
337                         if(execution.getVariable("WorkflowException") == null || isBlank(requestInfo)){\r
338                                 buildWorkflowException(execution, 2500, "Internal Error - WorkflowException Object and/or RequestInfo is null! " + processKey)\r
339                         }\r
340                         requestInfo = utils.removeXmlPreamble(requestInfo)\r
341                         WorkflowException wfex = execution.getVariable("WorkflowException")\r
342                         String errorMessage = wfex.getErrorMessage()\r
343                         int errorCode = wfex.getErrorCode()\r
344 \r
345                         String falloutHandlerRequest =\r
346                         """<aetgt:FalloutHandlerRequest xmlns:aetgt="http://org.openecomp/mso/workflow/schema/v1"\r
347                                                                      xmlns:ns="http://org.openecomp/mso/request/types/v1"\r
348                                                                      xmlns:wfsch="http://org.openecomp/mso/workflow/schema/v1">\r
349                                            ${requestInfo}\r
350                                                 <aetgt:WorkflowException xmlns:aetgt="http://org.openecomp/mso/workflow/schema/v1">\r
351                                                         <aetgt:ErrorMessage>${errorMessage}</aetgt:ErrorMessage>\r
352                                                         <aetgt:ErrorCode>${errorCode}</aetgt:ErrorCode>\r
353                                                 </aetgt:WorkflowException>\r
354                                         </aetgt:FalloutHandlerRequest>"""\r
355 \r
356                         utils.log("DEBUG", processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"), isDebugEnabled)\r
357                         utils.log("DEBUG", processKey + " Outgoing FalloutHandler Request is: " + falloutHandlerRequest, isDebugEnabled)\r
358 \r
359                         return falloutHandlerRequest\r
360 \r
361                 }catch(Exception e){\r
362                         utils.log("DEBUG", "Caught Exception during ProcessMainflowBPMNException Method: " + e, isDebugEnabled)\r
363                         return null\r
364                 }\r
365                 utils.log("DEBUG", "Completed ProcessMainflowBPMNException Method", isDebugEnabled)\r
366         }\r
367 \r
368         /**\r
369          *\r
370          * This method is executed after an Java Exception is caught\r
371          * It sets the WorkflowException variable. The method can be used in either mainflow or subflows.\r
372          *\r
373          * @param - execution\r
374          *\r
375          */\r
376         public void processJavaException(Execution execution){\r
377                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")\r
378                 String processKey = getProcessKey(execution)\r
379                 try{\r
380                         utils.log("DEBUG", "Caught a Java Exception in " + processKey, isDebugEnabled)\r
381                         utils.log("DEBUG", "Started processJavaException Method", isDebugEnabled)\r
382                         buildWorkflowException(execution, 2500, "Catch a Java Lang Exception in " + processKey)\r
383 \r
384                 }catch(BpmnError b){\r
385                         throw b\r
386                 }catch(Exception e){\r
387                         utils.log("DEBUG", "Caught Exception during processJavaException Method: " + e, isDebugEnabled)\r
388                         buildWorkflowException(execution, 2500, "Internal Error - During Process Java Exception")\r
389                 }\r
390                 utils.log("DEBUG", "Completed processJavaException Method", isDebugEnabled)\r
391         }\r
392 \r
393 \r
394         public void preProcessRequest(Execution execution) {\r
395                 // TODO Auto-generated method stub\r
396 \r
397         }\r
398 }\r