001package jmri.util.exceptionhandler;
002
003import java.awt.GraphicsEnvironment;
004
005import jmri.util.swing.ExceptionContext;
006
007/**
008 * Class to log exceptions that rise to the top of threads, including to the top
009 * of the AWT event processing loop.
010 *
011 * Using code must install this with
012 * <pre>
013 * Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler());
014 * </pre>
015 *
016 * @author Bob Jacobsen Copyright 2003, 2010
017 */
018public class UncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
019
020    @Override
021    public void uncaughtException(Thread t, Throwable e) {
022
023        // see http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadDeath.html
024        // 
025        // The type ThreadDeath has been deprecated since version 20 and marked for removal
026        // and the warning cannot be suppressed in Java 21. But external libraries might
027        // throw the exception outside of JMRI control. So check the name of the exception
028        // instead of using "instanceof".
029        if ("java.lang.ThreadDeath".equals(e.getClass().getName())) {
030            log.info("Thread has stopped: {}", t.getName());
031            return;
032        }
033
034        log.error("Uncaught Exception caught by jmri.util.exceptionhandler.UncaughtExceptionHandler", e);
035
036        if (e instanceof Error) {
037            if (!GraphicsEnvironment.isHeadless()) {
038                jmri.util.swing.ExceptionDisplayFrame.displayExceptionDisplayFrame(null,
039                    new ErrorContext(e));
040            }
041            log.error("System Exiting");
042            systemExit();
043        }
044    }
045
046    protected void systemExit(){
047        System.exit(126);
048    }
049
050    private static class ErrorContext extends ExceptionContext {
051
052        public ErrorContext(@javax.annotation.Nonnull Throwable ex) {
053            super(ex, "", "");
054            this.prefaceString = Bundle.getMessage("UnrecoverableErrorMessage");
055        }
056
057        @Override
058        public String getTitle() {
059            return Bundle.getMessage("UnrecoverableErrorTitle");
060        }
061
062    }
063
064    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(UncaughtExceptionHandler.class);
065
066}