001 package org.springframework.richclient.exceptionhandling.delegation; 002 003 import org.apache.commons.logging.Log; 004 import org.apache.commons.logging.LogFactory; 005 import org.springframework.beans.factory.InitializingBean; 006 import org.springframework.richclient.exceptionhandling.AbstractRegisterableExceptionHandler; 007 import org.springframework.util.Assert; 008 009 import java.util.List; 010 011 /** 012 * An exception handler that selects an appropriate exception handler from a list 013 * based on the thrown exception and delegates the handling of the exception to it. 014 * <p/> 015 * This class works very similar to catch statements: 016 * the first delegate which can handle the exception will handle it. 017 * For example, consider 3 simple delegates for the following classes in this order: 018 * NullPointerException (1), RuntimeException (2), IllegalArgumentException (3). 019 * A thrown IllegalArgumentException will be handled by the (2) handler. The (3) handler is useless. 020 * 021 * @see ExceptionHandlerDelegate 022 * @see SimpleExceptionHandlerDelegate 023 * @author Geoffrey De Smet 024 * @since 0.3.0 025 */ 026 public class DelegatingExceptionHandler extends AbstractRegisterableExceptionHandler implements InitializingBean { 027 028 protected final transient Log logger = LogFactory.getLog(getClass()); 029 030 protected List<ExceptionHandlerDelegate> delegateList; 031 protected ExceptionPurger exceptionPurger = null; 032 033 /** 034 * Sets the list of delegates. 035 * This is not a map because the order is important 036 * and delegate selection is not a simple key based selector. 037 * @param delegateList a list of DelegatingExceptionHandlerDelegate 038 */ 039 public void setDelegateList(List<ExceptionHandlerDelegate> delegateList) { 040 this.delegateList = delegateList; 041 } 042 043 /** 044 * If set the throwable will first be purged before handling it. 045 * @param exceptionPurger 046 */ 047 public void setExceptionPurger(ExceptionPurger exceptionPurger) { 048 this.exceptionPurger = exceptionPurger; 049 } 050 051 public void afterPropertiesSet() throws Exception { 052 Assert.notEmpty(delegateList, "The delegate list must contains at least one entry."); 053 } 054 055 /** 056 * Delegates the throwable to the appropriate delegate exception handler. 057 * @param thread the thread in which the throwable occurred 058 * @param throwable the thrown throwable 059 */ 060 public void uncaughtException(Thread thread, Throwable throwable) { 061 if (exceptionPurger != null) { 062 throwable = exceptionPurger.purge(throwable); 063 } 064 for (ExceptionHandlerDelegate delegate : delegateList) { 065 if (delegate.hasAppropriateHandler(throwable)) { 066 delegate.uncaughtException(thread, throwable); 067 return; 068 } 069 } 070 // A silent exception handler should be configured if it needs to be silent 071 logger.error("No exception handler found for throwable", throwable); 072 } 073 074 }