/*- * ============LICENSE_START======================================================= * OPENECOMP - MSO * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= */ package com.att.bpm.scripts import org.openecomp.mso.bpmn.core.WorkflowException import org.camunda.bpm.engine.delegate.BpmnError import org.camunda.bpm.engine.runtime.Execution import org.apache.commons.lang3.* import static org.apache.commons.lang3.StringUtils.*; /** * @version 1.0 */ class ExceptionUtil extends AbstractServiceTaskProcessor { /** * * @Deprecated * * Instead use MapAAIExceptionToWorkflowException * * To Be Removed Once Refactoring Main Flow Error Handling Is Complete * * */ @Deprecated String MapAAIExceptionToWorkflowExceptionOld(String response, Execution execution) { def utils=new MsoUtils() def isDebugEnabled=execution.getVariable("isDebugLogEnabled") def prefix=execution.getVariable("prefix") def errorMsg = execution.getVariable(prefix+"ErrorResponse") utils.log("DEBUG","=========== Begin MapAAIExceptionToWorkflowException ===========",isDebugEnabled) String text = null def variables String errorCode = '5000' utils.log("DEBUG","response: " + response, isDebugEnabled) try { //String msg = utils.getNodeXml(response, "Fault") variables = utils.getMultNodes(response, "variable") text = utils.getNodeText1(response, "text") } catch (Exception ex) { //Ignore the exception - cases include non xml payload utils.log("DEBUG","error mapping error, ignoring: " + ex,isDebugEnabled) } if(text != null) { if(variables.size()>=4){ text = text.replaceFirst("%1", variables[0]) text = text.replaceFirst("%2", variables[1]) text = text.replaceFirst("%3", variables[2]) text = text.replaceFirst("%4", variables[3]) } String modifiedErrorMessage = 'Received error from A&AI (' + text +')' utils.log("DEBUG", "ModifiedErrorMessage " + modifiedErrorMessage, isDebugEnabled) // let $ModifiedErrorMessage := concat( 'Received error from A',$exceptionaai:ampersand,'AI (' ,functx:replace-multi($ErrorMessage,$from,$Variables ),')') String message = """ $modifiedErrorMessage $errorCode """ execution.setVariable(prefix+"ErrorResponse",message) utils.log("ERROR","Fault:"+ execution.getVariable(prefix+"ErrorResponse")) return message } else { try { errorCode = MapErrorCode(errorMsg) String mappedErrorMessage = MapErrorMessage(errorMsg, errorCode) String message = """ $mappedErrorMessage $errorCode """ utils.log("DEBUG", "mappedErrorMessage " + mappedErrorMessage, isDebugEnabled) execution.setVariable(prefix+"ErrorResponse",message) utils.log("ERROR","Fault:"+ execution.getVariable(prefix+"ErrorResponse")) return message } catch(Exception ex) { utils.log("DEBUG","error mapping error, return null: " + ex,isDebugEnabled) return null } } } /** * This error handling method maps an AAI Exception response to a * WorkflowException Object. It then sets the WorkflowException Object * on the execution as "WorkflowException". * * This method formats the exception from AAI into the WorkflowException's * errorMessage that CCD expects. * * @param execution the execution * @param response the aai exception */ WorkflowException MapAAIExceptionToWorkflowException(String response, Execution execution) { def utils=new MsoUtils() def isDebugEnabled=execution.getVariable("isDebugLogEnabled") def prefix=execution.getVariable("prefix") def errorMsg = execution.getVariable(prefix+"ErrorResponse") utils.log("DEBUG","=========== Begin MapAAIExceptionToWorkflowException ===========",isDebugEnabled) String text = null def variables String errorCode = '5000' WorkflowException wfex utils.log("DEBUG","response: " + response, isDebugEnabled) try { //String msg = utils.getNodeXml(response, "Fault") variables = utils.getMultNodes(response, "variable") text = utils.getNodeText1(response, "text") } catch (Exception ex) { //Ignore the exception - cases include non xml payload utils.log("DEBUG","error mapping error, ignoring: " + ex,isDebugEnabled) } if(text != null) { if(variables.size()>=4){ text = text.replaceFirst("%1", variables[0]) text = text.replaceFirst("%2", variables[1]) text = text.replaceFirst("%3", variables[2]) text = text.replaceFirst("%4", variables[3]) } String modifiedErrorMessage = 'Received error from A&AI (' + text +')' utils.log("DEBUG", "ModifiedErrorMessage " + modifiedErrorMessage, isDebugEnabled) // let $ModifiedErrorMessage := concat( 'Received error from A',$exceptionaai:ampersand,'AI (' ,functx:replace-multi($ErrorMessage,$from,$Variables ),')') buildWorkflowException(execution, 5000, modifiedErrorMessage) wfex = execution.getVariable("WorkflowException") utils.log("ERROR","Fault:"+ wfex) return wfex } else { try { errorCode = MapErrorCode(errorMsg) String mappedErrorMessage = MapErrorMessage(errorMsg, errorCode) int errorCodeInt = Integer.parseInt(errorCode) buildWorkflowException(execution, errorCodeInt, mappedErrorMessage) utils.log("DEBUG", "mappedErrorMessage " + mappedErrorMessage, isDebugEnabled) wfex = execution.getVariable("WorkflowException") utils.log("ERROR","Fault:"+ wfex, isDebugEnabled) return wfex } catch(Exception ex) { utils.log("DEBUG","error mapping error, return null: " + ex, isDebugEnabled) return null } } } /** * This error handling method maps an AAI Exception response to a * WorkflowException Object. It then sets the WorkflowException Object * on the execution as "WorkflowException". * * This method takes the exact exception inside the tags from AAI Response * and puts it into the WorkflowException's errorMessage. * * @param execution the execution * @param response the aai exception */ WorkflowException MapAAIExceptionToWorkflowExceptionGeneric(Execution execution, String response, int resCode){ def utils=new MsoUtils() def isDebugLogEnabled = execution.getVariable("isDebugLogEnabled") utils.log("DEBUG", "Start MapAAIExceptionToWorkflowExceptionGeneric Process", isDebugLogEnabled) WorkflowException wfex try { if(utils.nodeExists(response, "Fault")){ String fault = utils.getNodeXml(response, "Fault") fault = utils.removeXmlPreamble(fault) fault = fault.replace("", "").replace("", "") fault = fault.replaceAll("\\s+\\s+", "") // Removes extra white spaces buildWorkflowException(execution, resCode, fault) }else if(utils.nodeExists(response, "RESTFault")){ String rFault = utils.getNodeXml(response, "RESTFault") buildWorkflowException(execution, resCode, rFault) }else{ buildWorkflowException(execution, resCode, "Received a bad response from AAI") } } catch (Exception ex) { utils.log("DEBUG", "Exception Occured during MapAAIExceptionToWorkflowExceptionGeneric: " + ex, isDebugLogEnabled) buildWorkflowException(execution, resCode, "Internal Error - Occured in MapAAIExceptionToWorkflowExceptionGeneric") } utils.log("DEBUG", "Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"), isDebugLogEnabled) utils.log("DEBUG", "Completed MapAAIExceptionToWorkflowExceptionGeneric Process", isDebugLogEnabled) } /** * *This method build a WorkflowException using the adapters response. * *@param String response *@param String adapter * *@return WorkflowException wfex */ WorkflowException MapAdapterExecptionToWorkflowException(String response, Execution execution, String adapter){ def utils=new MsoUtils() def isDebugEnabled=execution.getVariable("isDebugLogEnabled") def prefix=execution.getVariable("prefix") utils.log("DEBUG","=========== Start MapAdapterExecptionToWorkflowException Process ===========",isDebugEnabled) String errorCode def errorMessage WorkflowException wfex try { errorCode = MapCategoryToErrorCode(utils.getNodeText(response, "category")) errorMessage = MapAdapterErrorMessage(utils.getNodeText(response, "message"), errorCode, adapter) int errorCodeInt = Integer.parseInt(errorCode) buildWorkflowException(execution, errorCodeInt, errorMessage) }catch (Exception ex) { utils.log("DEBUG", "Exception Occured during MapAdapterExecptionToWorkflowException: " + ex, isDebugEnabled) buildWorkflowException(execution, 2500, "Internal Error - Occured in MapAdapterExecptionToWorkflowException") } wfex = execution.getVariable("WorkflowException") return wfex utils.log("DEBUG","=========== Completed MapAdapterExecptionToWorkflowException Process ===========",isDebugEnabled) } /** * * @Deprecated * * Instead use buildWorkflowException(Execution execution, int errorCode, String errorMessage) method below * * To Be Removed Once Refactoring Of Main Flow Error Handling Is Complete * */ @Deprecated String buildWorkflowExceptionXml(String errorCode, String errorMessage) { return """ ${errorMessage} ${errorCode} """ } /** * This method takes a WorkflowException Object and builds * WorkflowException Xml. This method should only be used * for the purpose of sending an error response. * *@param - WorkflowException Object * *@return - String WorkflowException Xml * * */ String buildErrorResponseXml(WorkflowException wfex) { String xml if(wfex != null){ String mes = wfex.getErrorMessage() int code = wfex.getErrorCode() xml = """ ${mes} ${code} """ }else{ xml = """ Internal Error 2500 """ } return xml } /* 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. 5010 Could not communicate with A&AI Asynchronous During orchestration of the recipe, a connection with A&AI could not be established. 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. */ String MapErrorCode(String errorMessage) { if(errorMessage==null){ return '5000' } errorMessage = errorMessage.toLowerCase(); if(errorMessage.contains('timed out') || errorMessage.contains('timeout')) return '5020' else if (errorMessage.contains('connection')) return '5010' else return '5000' } String MapErrorMessage(String errorMessage, String errorCode) { if(errorMessage == null){ errorMessage="" } if( errorCode.equals('5010')) return 'Could not communicate with A&AI' else if (errorCode.equals('5020')) return 'No response from A&AI' else return 'Received error from A&AI (' +errorMessage +')' } String MapCategoryToErrorCode(String errorCategory) { if(errorCategory.equals('OPENSTACK')) return '5100' else if (errorCategory.equals('IO')) return '5110' else if (errorCategory.equals('INTERNAL')) return '7020' else if (errorCategory.equals('USERDATA')) return '7020' else return '7020' } String MapAdapterErrorMessage(String errorMessage, String errorCode, String adapter) { if(errorCode.equals('5100')) return 'Received error from Platform Orchestrator: ' + errorMessage else if(errorCode.equals('5110')) return 'Could not communicate with Platform Orchestrator' else return 'Received error from ' + adapter + ': ' + errorMessage } String MapSDNCResponseCodeToErrorCode(String sdncResponseCode) { if (sdncResponseCode == '500') { return '5310' } else if ( sdncResponseCode == '408') { return '5320' } else if ( sdncResponseCode == '60010') { return '5350' } else { return '5300' } } /** * This error handling method builds a WorkflowException Object. It sets it on * the execution as "WorkflowException". * * @param execution the execution * @param errorCode the error code * @param errorMessage the error message */ public void buildWorkflowException(Execution execution, int errorCode, String errorMessage) { MsoUtils utils = new MsoUtils() def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled') String processKey = getProcessKey(execution); utils.log("DEBUG", "Building a WorkflowException for " + processKey, isDebugLogEnabled) WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage); execution.setVariable("WorkflowException", exception); utils.log("DEBUG", "Outgoing WorkflowException is " + exception, isDebugLogEnabled) } /** * This error handling method builds a WorkflowException Object and throws a * MSOWorkflowException. It throws a "MSOWorkflowException" BpmnError after * setting the WorkflowException Object on the execution as "WorkflowException". * * @param execution the execution * @param errorCode the error code * @param errorMessage the error message */ public void buildAndThrowWorkflowException(Execution execution, int errorCode, String errorMessage) { def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled') String processKey = getProcessKey(execution); utils.log("Building a WorkflowException for Subflow " + processKey, isDebugLogEnabled) WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage); execution.setVariable("WorkflowException", exception); utils.log("DEBUG", "Outgoing WorkflowException is " + exception, isDebugLogEnabled) utils.log("DEBUG", "Throwing MSOWorkflowException", isDebugLogEnabled) throw new BpmnError("MSOWorkflowException") } /** * This method is executed after an MSOWorkflowException is caught by a * subflow (during subflows "Error Handling Sub Process"). * It ensures the WorkflowException variable is populated before ending the * subflow and also logs the subflows outgoing WorkflowException Variable. * * @param - execution * */ public void processSubflowsBPMNException(Execution execution){ def isDebugEnabled=execution.getVariable("isDebugLogEnabled") String processKey = getProcessKey(execution) try{ utils.log("DEBUG", "Started ProcessSubflowsBPMNException Method", isDebugEnabled) if(execution.getVariable("WorkflowException") == null){ buildWorkflowException(execution, 2500, "Internal Error - Occured During " + processKey) } utils.log("DEBUG", processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"), isDebugEnabled) }catch(Exception e){ utils.log("DEBUG", "Caught Exception during ProcessSubflowsBPMNException Method: " + e, isDebugEnabled) } utils.log("DEBUG", "Completed ProcessSubflowsBPMNException Method", isDebugEnabled) } /** * This method is executed after an MSOWorkflowException is caught by a * Mainflow. It builds and returns a FalloutHandler Request. It also * verifies the WorkflowException variable is populated. * * @param - execution * @param - requestInfo * * @return - falloutHandlerRequest * */ public String processMainflowsBPMNException(Execution execution, String requestInfo){ def isDebugEnabled=execution.getVariable("isDebugLogEnabled") String processKey = getProcessKey(execution) try{ utils.log("DEBUG", "Started ProcessMainflowBPMNException Method", isDebugEnabled) if(execution.getVariable("WorkflowException") == null || isBlank(requestInfo)){ buildWorkflowException(execution, 2500, "Internal Error - WorkflowException Object and/or RequestInfo is null! " + processKey) } requestInfo = utils.removeXmlPreamble(requestInfo) WorkflowException wfex = execution.getVariable("WorkflowException") String errorMessage = wfex.getErrorMessage() int errorCode = wfex.getErrorCode() String falloutHandlerRequest = """ ${requestInfo} ${errorMessage} ${errorCode} """ utils.log("DEBUG", processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"), isDebugEnabled) utils.log("DEBUG", processKey + " Outgoing FalloutHandler Request is: " + falloutHandlerRequest, isDebugEnabled) return falloutHandlerRequest }catch(Exception e){ utils.log("DEBUG", "Caught Exception during ProcessMainflowBPMNException Method: " + e, isDebugEnabled) return null } utils.log("DEBUG", "Completed ProcessMainflowBPMNException Method", isDebugEnabled) } /** * This method is executed after an Java Exception is caught. * It sets the WorkflowException variable and throws an MSOWorkflowException. * * @param - execution * */ public void processSubflowsJavaException(Execution execution){ def isDebugEnabled=execution.getVariable("isDebugLogEnabled") String processKey = getProcessKey(execution) try{ utils.log("DEBUG", "Caught a Java Exception in " + processKey, isDebugEnabled) utils.log("DEBUG", "Started processJavaException Method", isDebugEnabled) buildAndThrowWorkflowException(execution, 2500, "Catch a Java Lang Exception in " + processKey) }catch(BpmnError b){ throw b }catch(Exception e){ utils.log("DEBUG", "Caught Exception during processJavaException Method: " + e, isDebugEnabled) buildAndThrowWorkflowException(execution, 2500, "Internal Error - During Process Java Exception") } utils.log("DEBUG", "Completed processJavaException Method", isDebugEnabled) } public void preProcessRequest(Execution execution) { // TODO Auto-generated method stub } }