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 }
|