import net.sf.openrocket.document.events.DocumentChangeEvent;
import net.sf.openrocket.document.events.DocumentChangeListener;
import net.sf.openrocket.document.events.SimulationChangeEvent;
-import net.sf.openrocket.gui.main.ExceptionHandler;
import net.sf.openrocket.gui.util.Icons;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper;
if (!undoErrorReported) {
undoErrorReported = true;
- ExceptionHandler.handleErrorCondition("Undo/Redo error: " + error);
+ Application.getExceptionHandler().handleErrorCondition("Undo/Redo error: " + error);
}
}
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
-import net.sf.openrocket.gui.main.ExceptionHandler;
+import net.sf.openrocket.startup.Application;
public abstract class ColumnTableModel extends AbstractTableModel {
private final Column[] columns;
public Object getValueAt(int row, int col) {
if ((row < 0) || (row >= getRowCount()) ||
(col < 0) || (col >= columns.length)) {
- ExceptionHandler.handleErrorCondition("Error: Requested illegal column/row, col=" + col + " row=" + row);
+ Application.getExceptionHandler().handleErrorCondition("Error: Requested illegal column/row, col=" + col + " row=" + row);
return null;
}
return columns[col].getValueAt(row);
import net.sf.openrocket.gui.adaptors.DoubleModel;
import net.sf.openrocket.gui.components.BasicSlider;
import net.sf.openrocket.gui.components.UnitSelector;
-import net.sf.openrocket.gui.main.ExceptionHandler;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper;
private void doScale() {
double mul = multiplier.getValue();
if (!(SCALE_MIN <= mul && mul <= SCALE_MAX)) {
- ExceptionHandler.handleErrorCondition("Illegal multiplier value, mul=" + mul);
+ Application.getExceptionHandler().handleErrorCondition("Illegal multiplier value, mul=" + mul);
return;
}
if (c == null) {
// Should not occur
- ExceptionHandler.handleErrorCondition("ERROR: Could not place new component.");
+ Application.getExceptionHandler().handleErrorCondition("ERROR: Could not place new component.");
updateEnabled();
return;
}
if (constructor == null) {
- ExceptionHandler.handleErrorCondition("ERROR: Construction of type not supported yet.");
+ Application.getExceptionHandler().handleErrorCondition("ERROR: Construction of type not supported yet.");
return;
}
// Insert at the end of the parent
return new Pair<RocketComponent, Integer>(parent, null);
default:
- ExceptionHandler.handleErrorCondition("ERROR: Bad position type: " + pos);
+ Application.getExceptionHandler().handleErrorCondition("ERROR: Bad position type: " + pos);
return null;
}
}
sel = 2;
break;
default:
- ExceptionHandler.handleErrorCondition("ERROR: JOptionPane returned " + sel);
+ Application.getExceptionHandler().handleErrorCondition("ERROR: JOptionPane returned " + sel);
return 0;
}
private static ImageIcon loadSmall(String file, String desc) {
URL url = ClassLoader.getSystemResource(file);
if (url == null) {
- ExceptionHandler.handleErrorCondition("ERROR: Couldn't find file: " + file);
+ Application.getExceptionHandler().handleErrorCondition("ERROR: Couldn't find file: " + file);
return null;
}
return new ImageIcon(url, desc);
bi = ImageIO.read(url);
bi2 = ImageIO.read(url); // How the fsck can one duplicate a BufferedImage???
} catch (IOException e) {
- ExceptionHandler.handleErrorCondition("ERROR: Couldn't read file: " + file, e);
+ Application.getExceptionHandler().handleErrorCondition("ERROR: Couldn't read file: " + file, e);
return new ImageIcon[] { null, null };
}
return icons;
} else {
- ExceptionHandler.handleErrorCondition("ERROR: Couldn't find file: " + file);
+ Application.getExceptionHandler().handleErrorCondition("ERROR: Couldn't find file: " + file);
return new ImageIcon[] { null, null };
}
}
+++ /dev/null
-package net.sf.openrocket.gui.main;
-
-import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
-
-import net.sf.openrocket.gui.dialogs.BugReportDialog;
-import net.sf.openrocket.logging.LogHelper;
-import net.sf.openrocket.logging.TraceException;
-import net.sf.openrocket.startup.Application;
-
-
-public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
-
- private static final LogHelper log = Application.getLogger();
-
- private static final int MEMORY_RESERVE = 512 * 1024;
-
- /**
- * A memory reserve of 0.5 MB of memory, that can be freed when showing the dialog.
- * <p>
- * This field is package-private so that the JRE cannot optimize its use away.
- */
- static volatile byte[] memoryReserve = null;
-
- private static ExceptionHandler instance = null;
-
-
- private volatile boolean handling = false;
-
-
-
-
- @Override
- public void uncaughtException(final Thread thread, final Throwable throwable) {
-
- // Free memory reserve if out of memory
- if (isOutOfMemoryError(throwable)) {
- memoryReserve = null;
- handling = false;
- log.error("Out of memory error detected", throwable);
- }
-
- if (isNonFatalJREBug(throwable)) {
- log.warn("Ignoring non-fatal JRE bug", throwable);
- return;
- }
-
- log.error("Handling uncaught exception on thread=" + thread, throwable);
- throwable.printStackTrace();
-
- if (handling) {
- log.warn("Exception is currently being handled, ignoring");
- return;
- }
-
- try {
- handling = true;
-
- // Show on the EDT
- if (SwingUtilities.isEventDispatchThread()) {
- log.info("Exception handler running on EDT, showing dialog");
- showDialog(thread, throwable);
- } else {
- log.info("Exception handler not on EDT, invoking dialog on EDT");
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- showDialog(thread, throwable);
- }
- });
- }
-
- } catch (Throwable ex) {
-
- // Make sure the handler does not throw any exceptions
- try {
- log.error("Caught exception while handling exception", ex);
- System.err.println("Exception in exception handler, dumping exception:");
- ex.printStackTrace();
- } catch (Exception ignore) {
- }
-
- } finally {
- // Mark handling as completed
- handling = false;
- }
-
- }
-
-
- /**
- * Handle an error condition programmatically without throwing an exception.
- * This can be used in cases where recovery of the error is desirable.
- * <p>
- * This method is guaranteed never to throw an exception, and can thus be safely
- * used in finally blocks.
- *
- * @param message the error message.
- */
- public static void handleErrorCondition(String message) {
- log.error(1, message, new TraceException());
- handleErrorCondition(new InternalException(message));
- }
-
-
- /**
- * Handle an error condition programmatically without throwing an exception.
- * This can be used in cases where recovery of the error is desirable.
- * <p>
- * This method is guaranteed never to throw an exception, and can thus be safely
- * used in finally blocks.
- *
- * @param message the error message.
- * @param exception the exception that occurred.
- */
- public static void handleErrorCondition(String message, Throwable exception) {
- log.error(1, message, exception);
- handleErrorCondition(new InternalException(message, exception));
- }
-
-
- /**
- * Handle an error condition programmatically without throwing an exception.
- * This can be used in cases where recovery of the error is desirable.
- * <p>
- * This method is guaranteed never to throw an exception, and can thus be safely
- * used in finally blocks.
- *
- * @param exception the exception that occurred.
- */
- public static void handleErrorCondition(final Throwable exception) {
- try {
- if (!(exception instanceof InternalException)) {
- log.error(1, "Error occurred", exception);
- }
- final Thread thread = Thread.currentThread();
- final ExceptionHandler handler = instance;
-
- if (handler == null) {
- log.error("Error condition occurred before exception handling has been initialized", exception);
- return;
- }
-
- if (SwingUtilities.isEventDispatchThread()) {
- log.info("Running in EDT, showing dialog");
- handler.showDialog(thread, exception);
- } else {
- log.info("Not in EDT, invoking dialog later");
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- handler.showDialog(thread, exception);
- }
- });
- }
- } catch (Exception e) {
- log.error("Exception occurred in error handler", e);
- }
- }
-
-
- /**
- * The actual handling routine.
- *
- * @param t the thread that caused the exception, or <code>null</code>.
- * @param e the exception.
- */
- private void showDialog(Thread t, Throwable e) {
-
- // Out of memory
- if (isOutOfMemoryError(e)) {
- log.info("Showing out-of-memory dialog");
- JOptionPane.showMessageDialog(null,
- new Object[] {
- "OpenRocket is out of available memory!",
- "You should immediately close unnecessary design windows,",
- "save any unsaved designs and restart OpenRocket!"
- }, "Out of memory", JOptionPane.ERROR_MESSAGE);
- return;
- }
-
- // Create the message
- String msg = e.getClass().getSimpleName() + ": " + e.getMessage();
- if (msg.length() > 90) {
- msg = msg.substring(0, 80) + "...";
- }
-
- // Unknown Error
- if (!(e instanceof Exception) && !(e instanceof LinkageError)) {
- log.info("Showing Error dialog");
- JOptionPane.showMessageDialog(null,
- new Object[] {
- "An unknown Java error occurred:",
- msg,
- "<html>You should immediately close unnecessary design windows,<br>" +
- "save any unsaved designs and restart OpenRocket!"
- }, "Unknown Java error", JOptionPane.ERROR_MESSAGE);
- return;
- }
-
-
- // Normal exception, show question dialog
- log.info("Showing Exception dialog");
- int selection = JOptionPane.showOptionDialog(null, new Object[] {
- "OpenRocket encountered an uncaught exception. This typically signifies " +
- "a bug in the software.",
- "<html><em> " + msg + "</em>",
- " ",
- "Please take a moment to report this bug to the developers.",
- "This can be done automatically if you have an Internet connection."
- }, "Uncaught exception", JOptionPane.DEFAULT_OPTION,
- JOptionPane.ERROR_MESSAGE, null,
- new Object[] { "View bug report", "Close" }, "View bug report");
-
- if (selection != 0) {
- // User cancelled
- log.user("User chose not to fill bug report");
- return;
- }
-
- // Show bug report dialog
- log.user("User requested sending bug report");
- BugReportDialog.showExceptionDialog(null, t, e);
- }
-
-
-
- /**
- * Registers the uncaught exception handler. This should be used to ensure that
- * all necessary registrations are performed.
- */
- public static void registerExceptionHandler() {
-
- if (instance == null) {
- instance = new ExceptionHandler();
- Thread.setDefaultUncaughtExceptionHandler(instance);
-
- // Handler for modal dialogs of Sun's Java implementation
- // See bug ID 4499199.
- System.setProperty("sun.awt.exception.handler", AwtHandler.class.getName());
-
- reserveMemory();
- }
-
- }
-
-
- /**
- * Reserve the buffer memory that is freed in case an OutOfMemoryError occurs.
- */
- private static void reserveMemory() {
- memoryReserve = new byte[MEMORY_RESERVE];
- for (int i = 0; i < MEMORY_RESERVE; i++) {
- memoryReserve[i] = (byte) i;
- }
- }
-
-
-
- /**
- * Return whether this throwable was caused by an OutOfMemoryError
- * condition. An exception is deemed to be caused by OutOfMemoryError
- * if the throwable or any of its causes is of the type OutOfMemoryError.
- * <p>
- * This method is required because Apple's JRE implementation sometimes
- * masks OutOfMemoryErrors within RuntimeExceptions. Idiots.
- *
- * @param t the throwable to examine.
- * @return whether this is an out-of-memory condition.
- */
- private boolean isOutOfMemoryError(Throwable t) {
- while (t != null) {
- if (t instanceof OutOfMemoryError)
- return true;
- t = t.getCause();
- }
- return false;
- }
-
-
-
- /**
- * Handler used in modal dialogs by Sun Java implementation.
- */
- public static class AwtHandler {
- public void handle(Throwable t) {
- if (instance != null) {
- instance.uncaughtException(Thread.currentThread(), t);
- }
- }
- }
-
-
- /**
- * Detect various non-fatal Sun JRE bugs.
- *
- * @param t the throwable
- * @return whether this exception should be ignored
- */
- private static boolean isNonFatalJREBug(Throwable t) {
-
- // NOTE: Calling method logs the entire throwable, so log only message here
-
-
- /*
- * Detect and ignore bug 6826104 in Sun JRE.
- */
- if (t instanceof NullPointerException) {
- StackTraceElement[] trace = t.getStackTrace();
-
- if (trace.length > 3 &&
- trace[0].getClassName().equals("sun.awt.X11.XWindowPeer") &&
- trace[0].getMethodName().equals("restoreTransientFor") &&
-
- trace[1].getClassName().equals("sun.awt.X11.XWindowPeer") &&
- trace[1].getMethodName().equals("removeFromTransientFors") &&
-
- trace[2].getClassName().equals("sun.awt.X11.XWindowPeer") &&
- trace[2].getMethodName().equals("setModalBlocked")) {
- log.warn("Ignoring Sun JRE bug (6826104): http://bugs.sun.com/view_bug.do?bug_id=6826104" + t);
- return true;
- }
-
- }
-
-
- /*
- * Detect and ignore bug 6828938 in Sun JRE 1.6.0_14 - 1.6.0_16.
- */
- if (t instanceof ArrayIndexOutOfBoundsException) {
- final String buggyClass = "sun.font.FontDesignMetrics";
- StackTraceElement[] elements = t.getStackTrace();
- if (elements.length >= 3 &&
- (buggyClass.equals(elements[0].getClassName()) ||
- buggyClass.equals(elements[1].getClassName()) ||
- buggyClass.equals(elements[2].getClassName()))) {
- log.warn("Ignoring Sun JRE bug 6828938: " +
- "(see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6828938): " + t);
- return true;
- }
- }
-
- /*
- * Detect and ignore bug 6561072 in Sun JRE 1.6.0_?
- */
- if (t instanceof NullPointerException) {
- StackTraceElement[] trace = t.getStackTrace();
-
- if (trace.length > 3 &&
- trace[0].getClassName().equals("javax.swing.JComponent") &&
- trace[0].getMethodName().equals("repaint") &&
-
- trace[1].getClassName().equals("sun.swing.FilePane$2") &&
- trace[1].getMethodName().equals("repaintListSelection") &&
-
- trace[2].getClassName().equals("sun.swing.FilePane$2") &&
- trace[2].getMethodName().equals("repaintSelection")) {
- log.warn("Ignoring Sun JRE bug 6561072 " +
- "(see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6561072): " + t);
- return true;
- }
- }
-
-
- /*
- * Detect and ignore bug 6933331 in Sun JRE 1.6.0_18 and others
- */
- if (t instanceof IllegalStateException) {
- StackTraceElement[] trace = t.getStackTrace();
-
- if (trace.length > 1 &&
- trace[0].getClassName().equals("sun.awt.windows.WComponentPeer") &&
- trace[0].getMethodName().equals("getBackBuffer")) {
- log.warn("Ignoring Sun JRE bug 6933331 " +
- "(see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6933331): " + t);
- return true;
- }
- }
-
- /*
- * Detect and ignore bug in Sun JRE 1.6.0_19
- */
- if (t instanceof NullPointerException) {
- StackTraceElement[] trace = t.getStackTrace();
-
- if (trace.length > 3 &&
- trace[0].getClassName().equals("sun.awt.shell.Win32ShellFolder2") &&
- trace[0].getMethodName().equals("pidlsEqual") &&
-
- trace[1].getClassName().equals("sun.awt.shell.Win32ShellFolder2") &&
- trace[1].getMethodName().equals("equals") &&
-
- trace[2].getClassName().equals("sun.awt.shell.Win32ShellFolderManager2") &&
- trace[2].getMethodName().equals("isFileSystemRoot")) {
- log.warn("Ignoring Sun JRE bug " +
- "(see http://forums.sun.com/thread.jspa?threadID=5435324): " + t);
- return true;
- }
- }
-
- /*
- * Detect Sun JRE bug in D3D
- */
- if (t instanceof ClassCastException) {
- if (t.getMessage().equals("sun.awt.Win32GraphicsConfig cannot be cast to sun.java2d.d3d.D3DGraphicsConfig")) {
- log.warn("Ignoring Sun JRE bug " +
- "(see http://forums.sun.com/thread.jspa?threadID=5440525): " + t);
- return true;
- }
- }
-
- return false;
- }
-
-
- @SuppressWarnings("unused")
- private static class InternalException extends Exception {
- public InternalException() {
- super();
- }
-
- public InternalException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public InternalException(String message) {
- super(message);
- }
-
- public InternalException(Throwable cause) {
- super(cause);
- }
- }
-}
} else {
- ExceptionHandler.handleErrorCondition("An exception occurred during the simulation", t);
+ Application.getExceptionHandler().handleErrorCondition("An exception occurred during the simulation", t);
}
simulationDone();
--- /dev/null
+package net.sf.openrocket.gui.main;
+
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+
+import net.sf.openrocket.gui.dialogs.BugReportDialog;
+import net.sf.openrocket.logging.LogHelper;
+import net.sf.openrocket.logging.TraceException;
+import net.sf.openrocket.startup.Application;
+
+
+public class SwingExceptionHandler implements Thread.UncaughtExceptionHandler, net.sf.openrocket.startup.ExceptionHandler {
+
+ private static final LogHelper log = Application.getLogger();
+
+ private static final int MEMORY_RESERVE = 512 * 1024;
+
+ /**
+ * A memory reserve of 0.5 MB of memory, that can be freed when showing the dialog.
+ * <p>
+ * This field is package-private so that the JRE cannot optimize its use away.
+ */
+ volatile byte[] memoryReserve = null;
+
+ private volatile boolean handling = false;
+
+
+
+
+ @Override
+ public void uncaughtException(final Thread thread, final Throwable throwable) {
+
+ // Free memory reserve if out of memory
+ if (isOutOfMemoryError(throwable)) {
+ memoryReserve = null;
+ handling = false;
+ log.error("Out of memory error detected", throwable);
+ }
+
+ if (isNonFatalJREBug(throwable)) {
+ log.warn("Ignoring non-fatal JRE bug", throwable);
+ return;
+ }
+
+ log.error("Handling uncaught exception on thread=" + thread, throwable);
+ throwable.printStackTrace();
+
+ if (handling) {
+ log.warn("Exception is currently being handled, ignoring");
+ return;
+ }
+
+ try {
+ handling = true;
+
+ // Show on the EDT
+ if (SwingUtilities.isEventDispatchThread()) {
+ log.info("Exception handler running on EDT, showing dialog");
+ showDialog(thread, throwable);
+ } else {
+ log.info("Exception handler not on EDT, invoking dialog on EDT");
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ showDialog(thread, throwable);
+ }
+ });
+ }
+
+ } catch (Throwable ex) {
+
+ // Make sure the handler does not throw any exceptions
+ try {
+ log.error("Caught exception while handling exception", ex);
+ System.err.println("Exception in exception handler, dumping exception:");
+ ex.printStackTrace();
+ } catch (Exception ignore) {
+ }
+
+ } finally {
+ // Mark handling as completed
+ handling = false;
+ }
+
+ }
+
+
+ /**
+ * Handle an error condition programmatically without throwing an exception.
+ * This can be used in cases where recovery of the error is desirable.
+ * <p>
+ * This method is guaranteed never to throw an exception, and can thus be safely
+ * used in finally blocks.
+ *
+ * @param message the error message.
+ */
+ @Override
+ public void handleErrorCondition(String message) {
+ log.error(1, message, new TraceException());
+ handleErrorCondition(new InternalException(message));
+ }
+
+
+ /**
+ * Handle an error condition programmatically without throwing an exception.
+ * This can be used in cases where recovery of the error is desirable.
+ * <p>
+ * This method is guaranteed never to throw an exception, and can thus be safely
+ * used in finally blocks.
+ *
+ * @param message the error message.
+ * @param exception the exception that occurred.
+ */
+ @Override
+ public void handleErrorCondition(String message, Throwable exception) {
+ log.error(1, message, exception);
+ handleErrorCondition(new InternalException(message, exception));
+ }
+
+
+ /**
+ * Handle an error condition programmatically without throwing an exception.
+ * This can be used in cases where recovery of the error is desirable.
+ * <p>
+ * This method is guaranteed never to throw an exception, and can thus be safely
+ * used in finally blocks.
+ *
+ * @param exception the exception that occurred.
+ */
+ @Override
+ public void handleErrorCondition(final Throwable exception) {
+ try {
+ if (!(exception instanceof InternalException)) {
+ log.error(1, "Error occurred", exception);
+ }
+ final Thread thread = Thread.currentThread();
+
+ if (SwingUtilities.isEventDispatchThread()) {
+ log.info("Running in EDT, showing dialog");
+ this.showDialog(thread, exception);
+ } else {
+ log.info("Not in EDT, invoking dialog later");
+ final SwingExceptionHandler instance = this;
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ instance.showDialog(thread, exception);
+ }
+ });
+ }
+ } catch (Exception e) {
+ log.error("Exception occurred in error handler", e);
+ }
+ }
+
+
+ /**
+ * The actual handling routine.
+ *
+ * @param t the thread that caused the exception, or <code>null</code>.
+ * @param e the exception.
+ */
+ private void showDialog(Thread t, Throwable e) {
+
+ // Out of memory
+ if (isOutOfMemoryError(e)) {
+ log.info("Showing out-of-memory dialog");
+ JOptionPane.showMessageDialog(null,
+ new Object[] {
+ "OpenRocket is out of available memory!",
+ "You should immediately close unnecessary design windows,",
+ "save any unsaved designs and restart OpenRocket!"
+ }, "Out of memory", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ // Create the message
+ String msg = e.getClass().getSimpleName() + ": " + e.getMessage();
+ if (msg.length() > 90) {
+ msg = msg.substring(0, 80) + "...";
+ }
+
+ // Unknown Error
+ if (!(e instanceof Exception) && !(e instanceof LinkageError)) {
+ log.info("Showing Error dialog");
+ JOptionPane.showMessageDialog(null,
+ new Object[] {
+ "An unknown Java error occurred:",
+ msg,
+ "<html>You should immediately close unnecessary design windows,<br>" +
+ "save any unsaved designs and restart OpenRocket!"
+ }, "Unknown Java error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+
+ // Normal exception, show question dialog
+ log.info("Showing Exception dialog");
+ int selection = JOptionPane.showOptionDialog(null, new Object[] {
+ "OpenRocket encountered an uncaught exception. This typically signifies " +
+ "a bug in the software.",
+ "<html><em> " + msg + "</em>",
+ " ",
+ "Please take a moment to report this bug to the developers.",
+ "This can be done automatically if you have an Internet connection."
+ }, "Uncaught exception", JOptionPane.DEFAULT_OPTION,
+ JOptionPane.ERROR_MESSAGE, null,
+ new Object[] { "View bug report", "Close" }, "View bug report");
+
+ if (selection != 0) {
+ // User cancelled
+ log.user("User chose not to fill bug report");
+ return;
+ }
+
+ // Show bug report dialog
+ log.user("User requested sending bug report");
+ BugReportDialog.showExceptionDialog(null, t, e);
+ }
+
+
+
+ /**
+ * Registers the uncaught exception handler. This should be used to ensure that
+ * all necessary registrations are performed.
+ */
+ public void registerExceptionHandler() {
+
+ Thread.setDefaultUncaughtExceptionHandler(this);
+
+ // Handler for modal dialogs of Sun's Java implementation
+ // See bug ID 4499199.
+ System.setProperty("sun.awt.exception.handler", AwtHandler.class.getName());
+
+ reserveMemory();
+
+ }
+
+
+ /**
+ * Reserve the buffer memory that is freed in case an OutOfMemoryError occurs.
+ */
+ private void reserveMemory() {
+ memoryReserve = new byte[MEMORY_RESERVE];
+ for (int i = 0; i < MEMORY_RESERVE; i++) {
+ memoryReserve[i] = (byte) i;
+ }
+ }
+
+
+
+ /**
+ * Return whether this throwable was caused by an OutOfMemoryError
+ * condition. An exception is deemed to be caused by OutOfMemoryError
+ * if the throwable or any of its causes is of the type OutOfMemoryError.
+ * <p>
+ * This method is required because Apple's JRE implementation sometimes
+ * masks OutOfMemoryErrors within RuntimeExceptions. Idiots.
+ *
+ * @param t the throwable to examine.
+ * @return whether this is an out-of-memory condition.
+ */
+ private boolean isOutOfMemoryError(Throwable t) {
+ while (t != null) {
+ if (t instanceof OutOfMemoryError)
+ return true;
+ t = t.getCause();
+ }
+ return false;
+ }
+
+
+
+ /**
+ * Handler used in modal dialogs by Sun Java implementation.
+ */
+ public static class AwtHandler {
+ public void handle(Throwable t) {
+ Application.getExceptionHandler().uncaughtException(Thread.currentThread(), t);
+ }
+ }
+
+
+ /**
+ * Detect various non-fatal Sun JRE bugs.
+ *
+ * @param t the throwable
+ * @return whether this exception should be ignored
+ */
+ private boolean isNonFatalJREBug(Throwable t) {
+
+ // NOTE: Calling method logs the entire throwable, so log only message here
+
+
+ /*
+ * Detect and ignore bug 6826104 in Sun JRE.
+ */
+ if (t instanceof NullPointerException) {
+ StackTraceElement[] trace = t.getStackTrace();
+
+ if (trace.length > 3 &&
+ trace[0].getClassName().equals("sun.awt.X11.XWindowPeer") &&
+ trace[0].getMethodName().equals("restoreTransientFor") &&
+
+ trace[1].getClassName().equals("sun.awt.X11.XWindowPeer") &&
+ trace[1].getMethodName().equals("removeFromTransientFors") &&
+
+ trace[2].getClassName().equals("sun.awt.X11.XWindowPeer") &&
+ trace[2].getMethodName().equals("setModalBlocked")) {
+ log.warn("Ignoring Sun JRE bug (6826104): http://bugs.sun.com/view_bug.do?bug_id=6826104" + t);
+ return true;
+ }
+
+ }
+
+
+ /*
+ * Detect and ignore bug 6828938 in Sun JRE 1.6.0_14 - 1.6.0_16.
+ */
+ if (t instanceof ArrayIndexOutOfBoundsException) {
+ final String buggyClass = "sun.font.FontDesignMetrics";
+ StackTraceElement[] elements = t.getStackTrace();
+ if (elements.length >= 3 &&
+ (buggyClass.equals(elements[0].getClassName()) ||
+ buggyClass.equals(elements[1].getClassName()) ||
+ buggyClass.equals(elements[2].getClassName()))) {
+ log.warn("Ignoring Sun JRE bug 6828938: " +
+ "(see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6828938): " + t);
+ return true;
+ }
+ }
+
+ /*
+ * Detect and ignore bug 6561072 in Sun JRE 1.6.0_?
+ */
+ if (t instanceof NullPointerException) {
+ StackTraceElement[] trace = t.getStackTrace();
+
+ if (trace.length > 3 &&
+ trace[0].getClassName().equals("javax.swing.JComponent") &&
+ trace[0].getMethodName().equals("repaint") &&
+
+ trace[1].getClassName().equals("sun.swing.FilePane$2") &&
+ trace[1].getMethodName().equals("repaintListSelection") &&
+
+ trace[2].getClassName().equals("sun.swing.FilePane$2") &&
+ trace[2].getMethodName().equals("repaintSelection")) {
+ log.warn("Ignoring Sun JRE bug 6561072 " +
+ "(see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6561072): " + t);
+ return true;
+ }
+ }
+
+
+ /*
+ * Detect and ignore bug 6933331 in Sun JRE 1.6.0_18 and others
+ */
+ if (t instanceof IllegalStateException) {
+ StackTraceElement[] trace = t.getStackTrace();
+
+ if (trace.length > 1 &&
+ trace[0].getClassName().equals("sun.awt.windows.WComponentPeer") &&
+ trace[0].getMethodName().equals("getBackBuffer")) {
+ log.warn("Ignoring Sun JRE bug 6933331 " +
+ "(see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6933331): " + t);
+ return true;
+ }
+ }
+
+ /*
+ * Detect and ignore bug in Sun JRE 1.6.0_19
+ */
+ if (t instanceof NullPointerException) {
+ StackTraceElement[] trace = t.getStackTrace();
+
+ if (trace.length > 3 &&
+ trace[0].getClassName().equals("sun.awt.shell.Win32ShellFolder2") &&
+ trace[0].getMethodName().equals("pidlsEqual") &&
+
+ trace[1].getClassName().equals("sun.awt.shell.Win32ShellFolder2") &&
+ trace[1].getMethodName().equals("equals") &&
+
+ trace[2].getClassName().equals("sun.awt.shell.Win32ShellFolderManager2") &&
+ trace[2].getMethodName().equals("isFileSystemRoot")) {
+ log.warn("Ignoring Sun JRE bug " +
+ "(see http://forums.sun.com/thread.jspa?threadID=5435324): " + t);
+ return true;
+ }
+ }
+
+ /*
+ * Detect Sun JRE bug in D3D
+ */
+ if (t instanceof ClassCastException) {
+ if (t.getMessage().equals("sun.awt.Win32GraphicsConfig cannot be cast to sun.java2d.d3d.D3DGraphicsConfig")) {
+ log.warn("Ignoring Sun JRE bug " +
+ "(see http://forums.sun.com/thread.jspa?threadID=5440525): " + t);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ @SuppressWarnings("unused")
+ private static class InternalException extends Exception {
+ public InternalException() {
+ super();
+ }
+
+ public InternalException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public InternalException(String message) {
+ super(message);
+ }
+
+ public InternalException(Throwable cause) {
+ super(cause);
+ }
+ }
+}
import javax.swing.tree.TreePath;
import net.sf.openrocket.document.OpenRocketDocument;
-import net.sf.openrocket.gui.main.ExceptionHandler;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
- ExceptionHandler.handleErrorCondition(e);
+ Application.getExceptionHandler().handleErrorCondition(e);
}
});
return false;
import java.awt.Shape;
-import net.sf.openrocket.gui.main.ExceptionHandler;
import net.sf.openrocket.gui.scalefigure.RocketFigure;
+import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.Transformation;
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation t) {
// no-op
- ExceptionHandler.handleErrorCondition("ERROR: RocketComponent.getShapesSide called with "
+ Application.getExceptionHandler().handleErrorCondition("ERROR: RocketComponent.getShapesSide called with "
+ component);
return new Shape[0];
}
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation t) {
// no-op
- ExceptionHandler.handleErrorCondition("ERROR: RocketComponent.getShapesBack called with "
+ Application.getExceptionHandler().handleErrorCondition("ERROR: RocketComponent.getShapesBack called with "
+component);
return new Shape[0];
}
import java.util.LinkedHashSet;
import net.sf.openrocket.gui.figureelements.FigureElement;
-import net.sf.openrocket.gui.main.ExceptionHandler;
import net.sf.openrocket.gui.util.ColorConversion;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.motor.Motor;
}
if (m == null) {
- ExceptionHandler.handleErrorCondition("ERROR: Rocket figure paint method not found for "
+ Application.getExceptionHandler().handleErrorCondition("ERROR: Rocket figure paint method not found for "
+ component);
return new Shape[0];
}
import javax.swing.ImageIcon;
import net.sf.openrocket.document.Simulation;
-import net.sf.openrocket.gui.main.ExceptionHandler;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.startup.Application;
URL url = ClassLoader.getSystemResource(file);
if (url == null) {
- ExceptionHandler.handleErrorCondition("Image file " + file + " not found, ignoring.");
+ Application.getExceptionHandler().handleErrorCondition("Image file " + file + " not found, ignoring.");
return null;
}
return new ImageIcon(url, name);
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.RocketLoader;
-import net.sf.openrocket.gui.main.ExceptionHandler;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.MathUtil;
try {
is.close();
} catch (Exception e) {
- ExceptionHandler.handleErrorCondition("Error closing file", e);
+ Application.getExceptionHandler().handleErrorCondition("Error closing file", e);
}
}
}
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.file.CSVExport;
import net.sf.openrocket.gui.dialogs.SwingWorkerDialog;
-import net.sf.openrocket.gui.main.ExceptionHandler;
import net.sf.openrocket.simulation.FlightDataBranch;
import net.sf.openrocket.simulation.FlightDataType;
+import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.Unit;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.ProgressOutputStream;
try {
os.close();
} catch (Exception e) {
- ExceptionHandler.handleErrorCondition("Error closing file", e);
+ Application.getExceptionHandler().handleErrorCondition("Error closing file", e);
}
}
return null;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.RocketSaver;
-import net.sf.openrocket.gui.main.ExceptionHandler;
+import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.ProgressOutputStream;
public class SaveFileWorker extends SwingWorker<Void, Void> {
try {
os.close();
} catch (Exception e) {
- ExceptionHandler.handleErrorCondition("Error closing file", e);
+ Application.getExceptionHandler().handleErrorCondition("Error closing file", e);
}
}
return null;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import net.sf.openrocket.arch.SystemInfo;
import net.sf.openrocket.document.Simulation;
-import net.sf.openrocket.gui.main.ExceptionHandler;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.material.Material;
-import net.sf.openrocket.rocketcomponent.BodyComponent;
-import net.sf.openrocket.rocketcomponent.FinSet;
-import net.sf.openrocket.rocketcomponent.InternalComponent;
-import net.sf.openrocket.rocketcomponent.LaunchLug;
-import net.sf.openrocket.rocketcomponent.MassObject;
-import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.rocketcomponent.Rocket;
-import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.simulation.FlightDataType;
import net.sf.openrocket.simulation.RK4SimulationStepper;
import net.sf.openrocket.simulation.SimulationOptions;
}
} catch (BackingStoreException e) {
- ExceptionHandler.handleErrorCondition(e);
+ Application.getExceptionHandler().handleErrorCondition(e);
}
}
import java.util.Locale;
import java.util.MissingResourceException;
-import net.sf.openrocket.gui.main.ExceptionHandler;
+import net.sf.openrocket.startup.Application;
/**
* A translator that suppresses MissingResourceExceptions and handles them gracefully.
private static synchronized void handleError(String key, MissingResourceException e) {
if (!errorReported) {
errorReported = true;
- ExceptionHandler.handleErrorCondition("Can not find translation for '" + key + "' locale=" + Locale.getDefault(), e);
+ Application.getExceptionHandler().handleErrorCondition("Can not find translation for '" + key + "' locale=" + Locale.getDefault(), e);
}
}
import java.util.List;
import java.util.UUID;
-import net.sf.openrocket.gui.main.ExceptionHandler;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.motor.Motor;
freezeList = new LinkedList<ComponentChangeEvent>();
log.debug("Freezing Rocket");
} else {
- ExceptionHandler.handleErrorCondition("Attempting to freeze Rocket when it is already frozen, " +
+ Application.getExceptionHandler().handleErrorCondition("Attempting to freeze Rocket when it is already frozen, " +
"freezeList=" + freezeList);
}
}
public void thaw() {
checkState();
if (freezeList == null) {
- ExceptionHandler.handleErrorCondition("Attempting to thaw Rocket when it is not frozen");
+ Application.getExceptionHandler().handleErrorCondition("Attempting to thaw Rocket when it is not frozen");
return;
}
if (freezeList.size() == 0) {
package net.sf.openrocket.startup;
import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
+import net.sf.openrocket.gui.main.SwingExceptionHandler;
import net.sf.openrocket.l10n.ClassBasedTranslator;
import net.sf.openrocket.l10n.DebugTranslator;
import net.sf.openrocket.l10n.ExceptionSuppressingTranslator;
private static ThrustCurveMotorSetDatabase motorSetDatabase;
private static Preferences preferences;
+
+ private static SwingExceptionHandler exceptionHandler;
// Initialize the logger to something sane for testing without executing Startup
static {
Application.preferences = preferences;
}
+ /**
+ * @return the exceptionHandler
+ */
+ public static SwingExceptionHandler getExceptionHandler() {
+ return exceptionHandler;
+ }
+
+ /**
+ * @param exceptionHandler the exceptionHandler to set
+ */
+ public static void setExceptionHandler(SwingExceptionHandler exceptionHandler) {
+ Application.exceptionHandler = exceptionHandler;
+ }
+
/**
* Return the database of all thrust curves loaded into the system.
*/
--- /dev/null
+package net.sf.openrocket.startup;\r
+\r
+public interface ExceptionHandler {\r
+\r
+ public void handleErrorCondition(String message);\r
+ public void handleErrorCondition(String message, Throwable exception);\r
+ public void handleErrorCondition(final Throwable exception);\r
+\r
+ \r
+ public void uncaughtException(final Thread thread, final Throwable throwable);\r
+ \r
+}\r
import net.sf.openrocket.file.motor.MotorLoaderHelper;
import net.sf.openrocket.gui.dialogs.UpdateInfoDialog;
import net.sf.openrocket.gui.main.BasicFrame;
-import net.sf.openrocket.gui.main.ExceptionHandler;
import net.sf.openrocket.gui.main.Splash;
+import net.sf.openrocket.gui.main.SwingExceptionHandler;
import net.sf.openrocket.gui.util.GUIUtil;
-import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.gui.util.SimpleFileFilter;
+import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.ThrustCurveMotor;
// Setup the uncaught exception handler
log.info("Registering exception handler");
- ExceptionHandler.registerExceptionHandler();
+ SwingExceptionHandler exceptionHandler = new SwingExceptionHandler();
+ Application.setExceptionHandler(exceptionHandler);
+ exceptionHandler.registerExceptionHandler();
// Start update info fetching
final UpdateInfoRetriever updateInfo;
import java.util.LinkedList;
-import net.sf.openrocket.gui.main.ExceptionHandler;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.logging.TraceException;
import net.sf.openrocket.startup.Application;
try {
if (location == null) {
- ExceptionHandler.handleErrorCondition("location is null");
+ Application.getExceptionHandler().handleErrorCondition("location is null");
location = "";
}
checkState(false);
}
return true;
} catch (Exception e) {
- ExceptionHandler.handleErrorCondition("An exception occurred while unlocking a mutex, " +
+ Application.getExceptionHandler().handleErrorCondition("An exception occurred while unlocking a mutex, " +
"locking thread=" + lockingThread + " locations=" + locations, e);
return false;
}
if (!errorReported) {
errorReported = true;
- ExceptionHandler.handleErrorCondition(ex);
+ Application.getExceptionHandler().handleErrorCondition(ex);
} else {
log.error(message, ex);
}