KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > nightlabs > rcp > exceptionhandler > ExceptionHandlerRegistry


1 /*
2  * Created on Sep 23, 2004
3  *
4  */

5 package com.nightlabs.rcp.exceptionhandler;
6
7 import java.util.HashMap JavaDoc;
8
9 import org.apache.commons.lang.exception.ExceptionUtils;
10 import org.apache.log4j.Logger;
11 import org.eclipse.swt.widgets.Display;
12
13 import com.nightlabs.rcp.extensionpoint.EPProcessorException;
14
15 /**
16  * Maintains a Map of {@link IExceptionHandler} and is able
17  * to search the right handler for an exception.
18  * This class staticly holds a default registry as singleton static member and
19  * provides some static convenience methods statically which
20  * work with the default shared instance.
21  *
22  * @author Alexander Bieber <alex[AT]nightlabs[DOT]de>
23  */

24 public class ExceptionHandlerRegistry {
25     public static final Logger LOGGER = Logger.getLogger(ExceptionHandlerRegistry.class);
26     
27     private HashMap JavaDoc exceptionHandlers = new HashMap JavaDoc();
28
29     // Dummy object to provide thread safety
30
// IMPROVE other synchronization strategy
31
private Object JavaDoc synchronizedObject = new Object JavaDoc();
32     
33     protected HashMap JavaDoc getExceptionHandlers(){
34         return exceptionHandlers;
35     }
36     
37     public void addExceptionHandler(String JavaDoc targetType, IExceptionHandler handler){
38         synchronized(synchronizedObject){
39             ensureProcessingDone();
40             if (exceptionHandlers.containsKey(targetType))
41                 throw new DuplicateHandlerRegistryException("An exceptionHandler was already defined for "+targetType);
42             exceptionHandlers.put(targetType,handler);
43         }
44     }
45     
46     /**
47      * @param targetType
48      * @return The registered IExceptionHandler for the given targetType. Null if none registered.
49      */

50     protected IExceptionHandler getExceptionHandler(String JavaDoc targetType){
51         synchronized(synchronizedObject){
52             ensureProcessingDone();
53             if (exceptionHandlers.containsKey(targetType))
54                 return (IExceptionHandler)exceptionHandlers.get(targetType);
55             else
56                 return null;
57         }
58     }
59     
60     
61     /**
62      * Removes the registration of the given targetType
63      * @param targetType
64      */

65     public void removeExceptionHandler(String JavaDoc targetType){
66         synchronized(synchronizedObject){
67             if (exceptionHandlers.containsKey(targetType))
68                 exceptionHandlers.remove(targetType);
69         }
70     }
71     
72     /**
73      * @param targetType
74      * @return The registered IExceptionHandler for the given targetType. Null if none registered.
75      */

76     protected IExceptionHandler getExceptionHandler(Class JavaDoc targetType){
77         return getExceptionHandler(targetType.getName());
78     }
79
80     /**
81      * Checks if a IExceptionHandler is registered for a specific Class
82      * @param targetType
83      * @return
84      */

85     protected boolean haveHandler(Class JavaDoc targetType){
86         return exceptionHandlers.containsKey(targetType.getName());
87     }
88     
89     // TODO: Maybe this should be static as EPs should only be processed once
90
private ExceptionHandlerEPProcessor epProcessor = null;
91     
92     protected void ensureProcessingDone() {
93         synchronized(synchronizedObject){
94             if (epProcessor == null){
95                 try {
96                     epProcessor = new ExceptionHandlerEPProcessor();
97                     epProcessor.process();
98                 } catch (EPProcessorException e) {
99                     // TODO Add handler code here
100
e.printStackTrace();
101                 }
102             }
103         }
104     }
105     
106     public ExceptionHandlerSearchResult getTopLevelCauseHandler(Throwable JavaDoc x)
107     {
108         ExceptionHandlerSearchResult handler = null;
109         Throwable JavaDoc cause = x.getCause();
110         if(cause != null)
111             handler = getTopLevelCauseHandler(cause);
112         if((handler == null) || (cause == null)) {
113             if (haveHandler(x.getClass())) {
114                 IExceptionHandler eHandler = getExceptionHandler(x.getClass());
115                 handler = new ExceptionHandlerSearchResult();
116                 handler.setHandler(eHandler);
117                 handler.setTriggerException(x);
118             }
119         }
120         return handler;
121     }
122     
123     /**
124      * Used as result for {@link ExceptionHandlerRegistry#searchHandler(Throwable)}
125      * @author Alexander Bieber
126      */

127     public static class ExceptionHandlerSearchResult {
128         private Throwable JavaDoc triggerException;
129         private IExceptionHandler handler;
130         
131         public IExceptionHandler getHandler() {
132             return handler;
133         }
134         public void setHandler(IExceptionHandler handler) {
135             this.handler = handler;
136         }
137         public Throwable JavaDoc getTriggerException() {
138             return triggerException;
139         }
140         public void setTriggerException(Throwable JavaDoc triggerException) {
141             this.triggerException = triggerException;
142         }
143     }
144     
145     /**
146      * Finds registered ExceptionHandlers. Moves up the class hierarchy for the
147      * passed exception itself and all its nested cause exceptions to find
148      * a handler for the specific class.
149      * Returns null if no handler could be found.
150      * @param exception
151      * @return
152      */

153     public ExceptionHandlerSearchResult searchHandler(Throwable JavaDoc exception){
154         // make sure the registrations where made
155
ensureProcessingDone();
156
157         ExceptionHandlerSearchResult rootCauseResult = getTopLevelCauseHandler(exception);
158         if (rootCauseResult != null)
159             return rootCauseResult;
160         
161         Class JavaDoc classRun = exception.getClass();
162         Throwable JavaDoc exceptionRun = exception;
163         while (exceptionRun != null) {
164             
165           classRun = exceptionRun.getClass();
166           while ( (!haveHandler(classRun)) && (!classRun.equals(Throwable JavaDoc.class)) ) {
167               classRun = classRun.getSuperclass();
168           }
169             
170           if (!classRun.equals(Throwable JavaDoc.class))
171             if (haveHandler(classRun))
172                 break;
173           
174 // exceptionRun = exceptionRun.getCause();
175
exceptionRun = ExceptionUtils.getCause(exceptionRun);
176         }
177         
178         ExceptionHandlerSearchResult result = new ExceptionHandlerSearchResult();
179         result.setHandler(getExceptionHandler(classRun));
180         if (exceptionRun == null)
181             exceptionRun = exception;
182         result.setTriggerException(exceptionRun);
183         // returns null if none registered
184
return result;
185     }
186     
187     /**
188      * This method executes an ExceptionHandler on the GUI thread
189      * and does not wait for it. If this method is executed on the GUI
190      * thread, it will block, though.
191      *
192      * @param exception
193      */

194     public static void asyncHandleException(Throwable JavaDoc exception)
195     {
196         getSharedInstance().handleException(Thread.currentThread(), exception, true);
197     }
198
199     /**
200      * This method executes an ExceptionHandler on the GUI thread
201      * and does not wait for it. If this method is executed on the GUI
202      * thread, it will block, though.
203      *
204      * @param exception
205      */

206     public static boolean asyncHandleException(Thread JavaDoc thread, Throwable JavaDoc exception)
207     {
208         return getSharedInstance().handleException(thread, exception, true);
209     }
210
211     /**
212      * This method can be executed on every thread. It executes an
213      * ExceptionHandler on the GUI thread and waits for it to return.
214      *
215      * @param exception
216      */

217     public static boolean syncHandleException(Throwable JavaDoc exception)
218     {
219         return getSharedInstance().handleException(Thread.currentThread(), exception, false);
220     }
221
222     /**
223      * This method can be executed on every thread. It executes an
224      * ExceptionHandler on the GUI thread and waits for it to return.
225      *
226      * @param exception
227      */

228     public static boolean syncHandleException(Thread JavaDoc thread, Throwable JavaDoc exception)
229     {
230         return getSharedInstance().handleException(thread, exception, false);
231     }
232
233     private boolean handleException(final Thread JavaDoc thread, final Throwable JavaDoc exception, boolean async)
234     {
235         // TODO: Do we need to find out on which thread we are, or is syncExec intelligent enough?
236
Throwable JavaDoc handlingException = null;
237         final ExceptionHandlerSearchResult handlerSearch = getSharedInstance().searchHandler(exception);
238         if (handlerSearch.getHandler() != null){
239             try {
240                 Runnable JavaDoc runnable = new Runnable JavaDoc(){
241                     public void run(){
242                         try {
243                             handlerSearch.getHandler().handleException(
244                                     thread,exception, handlerSearch.getTriggerException());
245                         } catch(Throwable JavaDoc x) {
246                             LOGGER.fatal("Exception occured while handling exception on GUI thread!", x);
247                         }
248                     }
249                 };
250
251                 if (async)
252                     Display.getDefault().asyncExec(runnable);
253                 else
254                     Display.getDefault().syncExec(runnable);
255                 
256             } catch (Throwable JavaDoc ex) {
257                 LOGGER.fatal("Exception occured while handling exception on causing thread!", ex);
258           }
259             return true;
260         }
261         else {
262             LOGGER.fatal("Did not find an ExceptionHandler for this Throwable!", exception);
263             return false;
264         }
265     }
266     
267     
268     private static ExceptionHandlerRegistry sharedInstance;
269     
270     public static ExceptionHandlerRegistry getSharedInstance() {
271         if (sharedInstance == null) {
272             sharedInstance = new ExceptionHandlerRegistry();
273         }
274         return sharedInstance;
275     }
276 }
Popular Tags