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    }