GriffonExceptionHandler.java
01 /*
02  * Copyright 2008-2012 the original author or authors.
03  *
04  * Licensed under the Apache License, Version 2.0 (the "License");
05  * you may not use this file except in compliance with the License.
06  * You may obtain a copy of the License at
07  *
08  *      http://www.apache.org/licenses/LICENSE-2.0
09  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package griffon.util;
17 
18 import griffon.core.GriffonApplication;
19 import org.codehaus.groovy.runtime.StackTraceUtils;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22 
23 import java.util.Map;
24 
25 import static java.util.Arrays.asList;
26 
27 /**
28  * Catches and sanitizes all uncaught exceptions.
29  *
30  @author Danno Ferrin
31  @author Andres Almiray
32  */
33 public class GriffonExceptionHandler implements Thread.UncaughtExceptionHandler {
34     /**
35      * "griffon.full.stacktrace"
36      */
37     public static final String GRIFFON_FULL_STACKTRACE = "griffon.full.stacktrace";
38     /**
39      * "griffon.exception.output"
40      */
41     public static final String GRIFFON_EXCEPTION_OUTPUT = "griffon.exception.output";
42 
43     private static final Logger LOG = LoggerFactory.getLogger(GriffonExceptionHandler.class);
44     private static final String[] CONFIG_OPTIONS = {
45             GRIFFON_FULL_STACKTRACE,
46             GRIFFON_EXCEPTION_OUTPUT
47     };
48 
49     public void uncaughtException(Thread t, Throwable e) {
50         handle(e);
51     }
52 
53     public void handle(Throwable throwable) {
54         try {
55             sanitize(throwable);
56             if (isOutputEnabled()) throwable.printStackTrace(System.err);
57             GriffonApplication app = ApplicationHolder.getApplication();
58             if (app != null) {
59                 LOG.error("Uncaught Exception", throwable);
60                 app.event("Uncaught" + GriffonNameUtils.getShortName(throwable.getClass()), asList(throwable));
61                 app.event(GriffonApplication.Event.UNCAUGHT_EXCEPTION_THROWN.getName(), asList(throwable));
62             }
63         catch (Throwable t) {
64             sanitize(t);
65             if (isOutputEnabled()) t.printStackTrace(System.err);
66             LOG.error("An error occurred while handling uncaught exception " + throwable, t);
67         }
68     }
69 
70     public static Throwable sanitize(Throwable throwable) {
71         try {
72             if (!Boolean.getBoolean(GRIFFON_FULL_STACKTRACE)) StackTraceUtils.deepSanitize(throwable);
73         catch (Throwable t) {
74             // don't let the exception get thrown out, will cause infinite looping!
75         }
76         return throwable;
77     }
78 
79     public static boolean isOutputEnabled() {
80         return Boolean.getBoolean(GRIFFON_EXCEPTION_OUTPUT);
81     }
82 
83     public static void configure(Map config) {
84         for (String option : CONFIG_OPTIONS) {
85             if (config.containsKey(option)) {
86                 System.setProperty(option, String.valueOf(config.get(option)));
87             }
88         }
89     }
90 
91     public static void registerExceptionHandler() {
92         Thread.setDefaultUncaughtExceptionHandler(new GriffonExceptionHandler());
93         System.setProperty("sun.awt.exception.handler", GriffonExceptionHandler.class.getName());
94     }
95 }