/** * Copyright (C) 2008-2010, Squale Project - http://www.squale.org * * This file is part of Squale. * * Squale is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or any later version. * * Squale is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Squale. If not, see <http://www.gnu.org/licenses/>. */ package org.squale.squaleweb.util; import java.io.IOException; import java.io.PrintWriter; import java.util.MissingResourceException; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.Globals; import org.squale.jraf.commons.exception.JrafException; /** * Traitement des exceptions Cette classe permet de remonter des exceptions au niveau de l'utilisateur via une JSP Une * clef de configuration permet d'activer la g�n�ration du StackTrace au niveau de la r�ponse renvoy�e par la JSP. */ public class ExceptionWrapper { /** Logger */ // On n'utilise pas de logger JRAF car cette classe // peut �tre appel�e pendant la phase d'initialisation private static Log logger = LogFactory.getLog( ExceptionWrapper.class ); /** Nom du bundle pour les exceptions */ private static final String EXCEPTION_BUNDLE_NAME = "org.squale.squaleweb.util.exception"; /** Nom de la clef pour l'activation du dump */ private static final String DUMP_EXCEPTION_KEY = "dumpExceptionInJsp"; /** Bool�en d'�tat de dump des exceptions */ static private Boolean dumpException = null; /** * @return true si le dump est activ� */ static private boolean isDumpEnabled() { // Init lazy if ( dumpException == null ) { try { // Lecture du fichier de ressources contenant la valeur ResourceBundle bundle = PropertyResourceBundle.getBundle( EXCEPTION_BUNDLE_NAME ); String conf = bundle.getString( DUMP_EXCEPTION_KEY ); if ( ( conf != null ) && ( conf.equals( "true" ) ) ) { dumpException = Boolean.TRUE; } else { dumpException = Boolean.FALSE; } } catch ( MissingResourceException e ) { logger.fatal( "Impossible d'obtenir " + EXCEPTION_BUNDLE_NAME, e ); // Valeur par d�faut dumpException = Boolean.FALSE; } } return dumpException.booleanValue(); } /** * Sauvegarde de l'exception * * @param pRequest requ�te * @param pException exception */ static public void saveException( HttpServletRequest pRequest, Exception pException ) { pRequest.setAttribute( Globals.EXCEPTION_KEY, pException ); } /** * R�cup�ration des d�tails de l'exception * * @param pRequest requ�te * @return d�tails de l'exception */ static public String getExceptionDetail( HttpServletRequest pRequest ) { // Obtention de l'exception Exception exception = (Exception) pRequest.getAttribute( Globals.EXCEPTION_KEY ); return getExceptionDetail( exception ); } /** * Obtention du d�tail d'une exception * * @param pException exception � d�tailler * @return d�tail de l'exception (au format HTML) en fonction de la configuration (@see #isDumpEnabled()) */ static public String getExceptionDetail( Throwable pException ) { // On log l'exception au cas o� logger.error( "Exception survenue ", pException ); java.io.StringWriter sw = new java.io.StringWriter(); java.io.PrintWriter pw = new java.io.PrintWriter( sw ); if ( isDumpEnabled() ) { fillExceptionTrace( pException, pw ); } try { sw.close(); } catch ( IOException e ) { // Impossible � obtenir sur un StringWriter.close } pw.close(); return sw.toString(); } /** * R�cup�ration des d�tails de l'exception * * @param pRequest requ�te * @param pException exception * @return d�tails de l'exception */ static public String getExceptionDetail( HttpServletRequest pRequest, Throwable pException ) { Throwable exception = pException; if ( exception == null ) { // Obtention de l'exception exception = (Exception) pRequest.getAttribute( Globals.EXCEPTION_KEY ); } return getExceptionDetail( exception ); } /** * Extraction du d�tail de l'exception * * @param pException exception * @param pw writer */ private static void fillExceptionTrace( Throwable pException, PrintWriter pw ) { // Certains contextes d'appel peuvent d�clencher le test suivant if ( pException == null ) { return; } // Extraction des informations sur l'exception elle-m�me dumpException( pException, pw ); // Extraction du cha�nage d'exception en fonction de son type if ( pException instanceof ServletException ) { fillExceptionTrace( ( (ServletException) pException ).getRootCause(), pw ); } else if ( pException instanceof JspException ) { fillExceptionTrace( ( (JspException) pException ).getRootCause(), pw ); } else if ( pException instanceof JrafException ) { fillExceptionTrace( ( (JrafException) pException ).getCause(), pw ); } else { // Rappel r�cursif sur la cause elle-m�me // Certaines exceptions remont�es par websphere // ont la particularit� de boucler sur la cause if ( ( pException.getCause() != null ) && ( pException.getCause() != pException ) ) { fillExceptionTrace( pException.getCause(), pw ); } } } /** * Extraction des informations d'une exception * * @param pException exception * @param pw writer */ private static void dumpException( Throwable pException, PrintWriter pw ) { pw.println( "<BR><BR><B>Error Message: </B>" + pException.getMessage() + "<BR>" ); pw.println( "<B>Error Stack: </B><BR>" ); pw.println( pException.getClass().getName() + ": " + pException.getMessage() ); StackTraceElement[] elements = pException.getStackTrace(); for ( int i = 0; i < elements.length; i++ ) { pw.println( "<BR>    " + elements[i] ); } } }