001 package org.springframework.richclient.exceptionhandling; 002 003 import org.apache.commons.logging.Log; 004 import org.apache.commons.logging.LogFactory; 005 import org.springframework.richclient.exceptionhandling.delegation.ExceptionPurger; 006 007 /** 008 * Superclass of logging exception handlers. 009 * It handles a throwable by logging it and notify it to the user. 010 * Subclasses determine how it's notified to the user. 011 * @author Geoffrey De Smet 012 * @since 0.3 013 */ 014 public abstract class AbstractLoggingExceptionHandler extends AbstractRegisterableExceptionHandler { 015 016 protected static final String LOG_MESSAGE = "Uncaught throwable handled"; 017 018 protected final transient Log logger = LogFactory.getLog(getClass()); 019 020 protected LogLevel logLevel = LogLevel.ERROR; 021 protected ExceptionPurger exceptionPurger = null; 022 023 /** 024 * The log level at which the throwable should be logged. 025 * The default is ERROR. 026 * @param logLevel the 027 */ 028 public void setLogLevel(LogLevel logLevel) { 029 this.logLevel = logLevel; 030 } 031 032 /** 033 * If set the throwable will first be purged before handling it. 034 * @param exceptionPurger 035 */ 036 public void setExceptionPurger(ExceptionPurger exceptionPurger) { 037 this.exceptionPurger = exceptionPurger; 038 } 039 040 /** 041 * Logs an exception and shows it to the user. 042 */ 043 public final void uncaughtException(Thread thread, Throwable throwable) { 044 try { 045 if (exceptionPurger != null) { 046 throwable = exceptionPurger.purge(throwable); 047 } 048 logException(thread, throwable); 049 notifyUserAboutException(thread, throwable); 050 } catch (Throwable t) { 051 // An exception handler must never throw a throwable itself 052 // because if it (directly or transitively) handles that throwable it can create an infinite loop 053 t.printStackTrace(); 054 // No logging because that could throw an exception 055 } 056 } 057 058 /** 059 * Log an exception 060 */ 061 public void logException(Thread thread, Throwable throwable) { 062 switch (logLevel) { 063 case TRACE: 064 logger.trace(LOG_MESSAGE, throwable); 065 break; 066 case DEBUG: 067 logger.debug(LOG_MESSAGE, throwable); 068 break; 069 case INFO: 070 logger.info(LOG_MESSAGE, throwable); 071 break; 072 case WARN: 073 logger.warn(LOG_MESSAGE, throwable); 074 break; 075 case ERROR: 076 logger.error(LOG_MESSAGE, throwable); 077 break; 078 case FATAL: 079 logger.fatal(LOG_MESSAGE, throwable); 080 break; 081 default: 082 logger.error("Unrecognized log level (" + logLevel + ") for throwable", throwable); 083 } 084 } 085 086 /** 087 * Notify user about an exception 088 */ 089 public abstract void notifyUserAboutException(Thread thread, Throwable throwable); 090 091 }