package com.fitbank.common.exception; import java.io.PrintWriter; import java.io.StringWriter; import java.sql.BatchUpdateException; import java.sql.SQLException; import java.text.DecimalFormat; import java.text.MessageFormat; import java.util.Locale; import org.apache.commons.configuration.Configuration; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.hibernate.Session; import org.hibernate.dialect.Dialect; import org.hibernate.internal.SessionFactoryImpl; import com.fitbank.common.ApplicationDates; import com.fitbank.common.Helper; import com.fitbank.common.helper.FormatDates; import com.fitbank.common.logger.FitbankLogger; import com.fitbank.common.properties.PropertiesHandler; import com.fitbank.dto.GeneralResponse; import com.fitbank.hb.persistence.gene.Tresult; import com.fitbank.hb.persistence.gene.TresultKey; import com.fitbank.hb.persistence.gene.Tresultconstraints; import com.fitbank.hb.persistence.gene.TresultconstraintsKey; /** * Clase encargada del manejo de excepciones * * @author Fitbank * @version 2.0 */ public class ExceptionHandler { private static final Configuration PROPERTIES = PropertiesHandler.getConfig("commonexception"); /** * Referencia a la excepción presentanda */ private Throwable exception; private String language = "es"; private Session session; /** * Referencia al Log */ private static final Logger LOG = FitbankLogger.getLogger(); /** * Crea una nueva instancia de ExceptionHandler * * @param pException * Referencia * @param pLanguage */ public ExceptionHandler(Throwable pException, String pLanguage) { this(pException, pLanguage, null); } /** * Crea una Instancia de ExceptionHandler * * @param pException * Excepción por Manejar */ public ExceptionHandler(Throwable pException, String pLanguage, Session pSession) { this.session = pSession; this.exception = pException; this.findException(); if (pLanguage != null) { this.language = pLanguage.toLowerCase(); } } /** * Método empleado para determinar la real excepcion a manejar */ private void findException() { Throwable e = this.exception; do { if ((e instanceof FitbankException) || (e instanceof FitbankCommitableException)) { this.exception = e; break; } e = e.getCause(); if (e != null) { this.exception = e; } } while (e != null); } /** * Método empleado para determinar el código asociado a la Excepcion dada * * @return Codigo */ private String getCode() { String code = this.exception.getClass().getName(); boolean already = false; if (this.exception instanceof BatchUpdateException) { DecimalFormat df = new DecimalFormat("00000"); code = "BDD-" + df.format(((BatchUpdateException) this.exception).getErrorCode()); already = true; } if (this.exception instanceof SQLException) { DecimalFormat df = new DecimalFormat("00000"); code = "BDD-" + df.format(Math.abs(((SQLException) this.exception).getErrorCode())); // TODO: UNIFICAR CODIGOS DE BASES already = true; } if (this.exception instanceof FitbankException) { code = ((FitbankException) this.exception).getCode(); already = true; } if (this.exception instanceof FitbankCommitableException) { code = ((FitbankCommitableException) this.exception).getCode(); already = true; } if (!already) { code = this.getUnknownExceptionValue("code"); } if (StringUtils.isBlank(code)) { code = "999997"; } return code; } private String getDataBaseExceptionMessage() { String message = null; try { Integer code = null; if (this.exception instanceof BatchUpdateException) { code = ((BatchUpdateException) this.exception).getErrorCode(); } if (this.exception instanceof SQLException) { code = ((SQLException) this.exception).getErrorCode(); } if (code != null) { message = this.manageSQlException(code); } } catch (Throwable thr) { } return message; } /** * Entrega el Valor de exception * * @return Valor de exception */ public Throwable getException() { return this.exception; } private String getFitbankCommitableExceptionMessage(Locale pLocale) { FitbankCommitableException ex = (FitbankCommitableException) this.exception; String message; try { message = this.getResultMessage(ex.getCode(), ex.getParameters()); } catch (Throwable tw) { message = ex.getMessage(pLocale); } return message; } private String getFitBankExceptionMessage(Locale pLocale) { FitbankException ex = (FitbankException) this.exception; String message; try { message = this.getResultMessage(ex.getCode(), ex.getParameters()); } catch (Throwable tw) { message = ex.getMessage(pLocale); } return message; } private String getResultMessage(String pCode, Object[] pParameters) throws Exception { TresultKey k = new TresultKey(this.language.toUpperCase(), pCode, ApplicationDates.getDefaultExpiryTimestamp()); Tresult result = (Tresult) Helper.getSession().get(Tresult.class, k); if (result != null) { String msg = result.getDescripcion(); if (pParameters != null) { msg = MessageFormat.format(msg, pParameters); } return msg; } throw new Exception(); } private String getStackTrace() { try { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); this.exception.printStackTrace(pw); String data = sw.toString(); pw.close(); return data; } catch (Exception e) { ExceptionHandler.LOG.error("Error de llamada", e); return null; } } private String getTechnicalMessage() { String message = this.exception.getMessage(); if (this.exception.getCause() != null) { message = this.exception.getCause().getMessage(); } StackTraceElement[] stack = this.exception.getStackTrace(); StringBuffer sb = new StringBuffer(); for (StackTraceElement element : stack) { if ((element.getClassName().indexOf("com.fitbank") > -1) && (element.getClassName().indexOf(".UtilHB") < 0)) { sb.append(" " + element.getClassName() + " : " + element.getLineNumber()); break; } } message += sb.toString(); if (this.exception instanceof BatchUpdateException) { return "(" + ((BatchUpdateException) this.exception).getErrorCode() + ")" + message; } if (this.exception instanceof SQLException) { return "(" + ((SQLException) this.exception).getErrorCode() + ")" + message; } return message; } private String getUnknownExceptionValue(String type) { type = "code".equals(type) ? ("." + type) : ""; String value = ""; String key = this.exception.getClass().getName() + type; if (PROPERTIES.containsKey(key)) { value = PROPERTIES.getString(key); } else { String[] specialError = new String[] {this.exception.getClass().getName(), this.exception.getStackTrace()[0].getClassName(), this.exception.getStackTrace()[0].getMethodName()}; key = StringUtils.join(specialError, "#") + type; if (PROPERTIES.containsKey(key)) { value = PROPERTIES.getString(key); } else if (".code".equals(type)) { value = this.exception.getClass().getName(); } else { value = this.exception.getMessage(); } } return value; } public String getUserMessage() { String message = this.exception.getMessage(); boolean already = false; Locale locale = new Locale(this.language, Locale.getDefault().getCountry(), this.getVariant()); if (this.exception instanceof FitbankException) { message = this.getFitBankExceptionMessage(locale); already = true; } if (this.exception instanceof FitbankCommitableException) { message = this.getFitbankCommitableExceptionMessage(locale); already = true; } String sqlMessage = this.getDataBaseExceptionMessage(); if (sqlMessage != null) { message = sqlMessage; already = true; } if (!already) { message = this.getUnknownExceptionValue("message"); } return message; } private String getVariant() { StringBuffer code = new StringBuffer(); for (int i = 0; i < this.getCode().length(); i++) { if (Character.isDigit(this.getCode().charAt(i))) { break; } code.append(this.getCode().charAt(i)); } return code.toString(); } /** * Maneja la Excepción presentanda */ public GeneralResponse manage() { GeneralResponse resp = new GeneralResponse(this.getCode()); resp.setUserMessage(this.getUserMessage()); resp.setTechnicalMessage(this.getTechnicalMessage()); resp.setStackTrace(this.getStackTrace()); FitbankLogger.getLogger().info(resp.getStackTrace()); if ((this.exception instanceof FitbankException) || (this.exception instanceof FitbankCommitableException)) { resp.setUciException(true); } if ((this.exception instanceof FitbankCommitableException)) { resp.setCommitable(true); } return resp; } /** * Manejo de Excepciones para DB2 */ private String manageSQLDB2(int code) { String message = null; switch (code) { case -418: message = "ERROR EN INSERCION"; break; case -419: message = "ERROR EN UPDATE"; break; case -530: /** * Cambio : CFlores. Motivo : Buscar error de Reestriccion de FK. * Fecha : Abril 2010. */ message = ((SQLException) this.exception).getMessage(); int pos1 = message.indexOf('F'); int pos2 = message.indexOf(' ', pos1); String fk = message.substring(pos1, pos2); try { TresultconstraintsKey id = new TresultconstraintsKey(fk, this.language.toUpperCase(), FormatDates.getDefaultExpiryTimestamp()); Tresultconstraints oR = (Tresultconstraints) ((this.session == null) ? Helper.getSession() : this.session).get(Tresultconstraints.class, id); if (oR.getDescripcion() != null) { message = oR.getDescripcion(); } } catch (Exception e) { message = this.exception.getMessage(); } break; default: message = this.exception.getMessage(); break; } return message; } /** * Manejo de Excepciones deacuerdo al dialecto de la base */ private String manageSQlException(int code) throws Exception { String message = null; SessionFactoryImpl imp = (SessionFactoryImpl) Helper.getSession().getSessionFactory(); Dialect dia = imp.getDialect(); if (dia.getClass().getSimpleName().startsWith("Oracle")) { // Oracle message = this.manageSQLOracle(code); } if (dia.getClass().getSimpleName().startsWith("DB2")) { // DB2 message = this.manageSQLDB2(code); } if (dia.getClass().getSimpleName().startsWith("SqlServer")) { // SQLServer message = this.manageSQLServer(code); } return message; } /** * Manejo de Excepciones para Oracle */ private String manageSQLOracle(int code) { String message = null; if ((code == 1) || (code == 2291) || ((code == 2290) && (code == 123))) { message = ((SQLException) this.exception).getMessage(); String fk = message.substring(message.indexOf('.') + 1, message.indexOf(')')); try { TresultconstraintsKey id = new TresultconstraintsKey(fk, this.language.toUpperCase(), FormatDates.getDefaultExpiryTimestamp()); Tresultconstraints oR = (Tresultconstraints) ((this.session == null) ? Helper.getSession() : this.session).get(Tresultconstraints.class, id); if (oR.getDescripcion() != null) { message = oR.getDescripcion(); } } catch (Exception e) { // e.printStackTrace(); message = this.exception.getMessage(); } } return message; } /** * Manejo de Excepciones para SQLServer */ private String manageSQLServer(int code) { String message = null; if ((code == 2627)) { message = ((SQLException) this.exception).getMessage(); String fk = message.substring(message.indexOf('\'') + 1); fk = fk.substring(0, fk.indexOf('\'')); try { TresultconstraintsKey id = new TresultconstraintsKey(fk, this.language.toUpperCase(), FormatDates.getDefaultExpiryTimestamp()); Tresultconstraints oR = (Tresultconstraints) ((this.session == null) ? Helper.getSession() : this.session).get(Tresultconstraints.class, id); if (oR.getDescripcion() != null) { message = oR.getDescripcion(); } } catch (Exception e) { // e.printStackTrace(); message = "NO CR:(" + fk + ")" + this.exception.getMessage(); } } return message; } }