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 }