package com.bugsnag.android; import java.lang.Thread.UncaughtExceptionHandler; import java.util.WeakHashMap; /** * Provides automatic notification hooks for unhandled exceptions. */ class ExceptionHandler implements UncaughtExceptionHandler { private final UncaughtExceptionHandler originalHandler; final WeakHashMap<Client, Boolean> clientMap = new WeakHashMap<Client, Boolean>(); static void enable(Client client) { UncaughtExceptionHandler currentHandler = Thread.getDefaultUncaughtExceptionHandler(); // Find or create the Bugsnag ExceptionHandler ExceptionHandler bugsnagHandler; if(currentHandler instanceof ExceptionHandler) { bugsnagHandler = (ExceptionHandler)currentHandler; } else { bugsnagHandler = new ExceptionHandler(currentHandler); Thread.setDefaultUncaughtExceptionHandler(bugsnagHandler); } // Subscribe this client to uncaught exceptions bugsnagHandler.clientMap.put(client, true); } static void disable(Client client) { // Find the Bugsnag ExceptionHandler UncaughtExceptionHandler currentHandler = Thread.getDefaultUncaughtExceptionHandler(); if(currentHandler instanceof ExceptionHandler) { // Unsubscribe this client from uncaught exceptions ExceptionHandler bugsnagHandler = (ExceptionHandler)currentHandler; bugsnagHandler.clientMap.remove(client); // Remove the Bugsnag ExceptionHandler if no clients are subscribed if(bugsnagHandler.clientMap.size() == 0) { Thread.setDefaultUncaughtExceptionHandler(bugsnagHandler.originalHandler); } } } public ExceptionHandler(UncaughtExceptionHandler originalHandler) { this.originalHandler = originalHandler; } public void uncaughtException(Thread t, Throwable e) { // Notify any subscribed clients of the uncaught exception for(Client client : clientMap.keySet()) { client.cacheAndNotify(e, Severity.ERROR); } // Pass exception on to original exception handler if(originalHandler != null) { originalHandler.uncaughtException(t, e); } else { System.err.printf("Exception in thread \"%s\" ", t.getName()); e.printStackTrace(System.err); } } }