updates for 0.9.3
[debian/openrocket] / src / net / sf / openrocket / gui / main / ExceptionHandler.java
1 package net.sf.openrocket.gui.main;
2
3 import javax.swing.JOptionPane;
4 import javax.swing.SwingUtilities;
5
6 import net.sf.openrocket.gui.dialogs.BugReportDialog;
7
8
9 public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
10
11         private static final int MEMORY_RESERVE = 512*1024;
12         
13         /**
14          * A memory reserve of 0.5 MB of memory, that can be freed when showing the dialog.
15          */
16         private static volatile byte[] memoryReserve = null;
17         
18         private static ExceptionHandler instance = null;
19         
20         
21         private volatile boolean handling = false;
22         
23         
24         
25         
26         @Override
27         public void uncaughtException(final Thread t, final Throwable e) {
28                 
29                 // Free memory reserve if out of memory
30                 if (e instanceof OutOfMemoryError) {
31                         memoryReserve = null;
32                         handling = false;
33                 }
34
35                 try {
36                         
37                         if (handling) {
38                                 System.err.println("Exception is currently being handled, " +
39                                                 "dumping exception instead:");
40                                 e.printStackTrace();
41                                 return;
42                         }
43                         
44                         handling = true;
45                         
46                         // Show on the EDT
47                         if (SwingUtilities.isEventDispatchThread()) {
48                                 showDialog(t, e);
49                         } else {
50                     SwingUtilities.invokeAndWait(new Runnable() {
51                         public void run() {
52                             showDialog(t, e);
53                         }
54                     });
55                         }
56                         
57                 } catch (Throwable ex) {
58                         
59                         // Make sure the handler does not throw any exceptions
60                         try {
61                                 System.err.println("Exception in exception handler, dumping exception:");
62                                 ex.printStackTrace();
63                         } catch (Throwable ignore) { }
64                         
65                 } finally {
66                         // Mark handling as completed
67                         handling = false;
68                 }
69                 
70         }
71
72         
73         /**
74          * The actual handling routine.
75          * 
76          * @param t             the thread that caused the exception, or <code>null</code>.
77          * @param e             the exception.
78          */
79         private void showDialog(Thread t, Throwable e) {
80                 
81                 // Out of memory
82                 if (e instanceof OutOfMemoryError) {
83                         JOptionPane.showMessageDialog(null, 
84                                         new Object[] { 
85                                                 "Out of memory!",
86                                                 "<html>You should immediately close unnecessary design windows,<br>" +
87                                                 "save any unsaved designs and restart OpenRocket!"
88                                         }, "Out of memory", JOptionPane.ERROR_MESSAGE);
89                         return;
90                 }
91                 
92                 // Unknown Error
93                 if (!(e instanceof Exception)) {
94                         JOptionPane.showMessageDialog(null, 
95                                         new Object[] { 
96                                                 "An unknown Java error occurred:",
97                                                 e.getMessage(),
98                                                 "<html>You should immediately close unnecessary design windows,<br>" +
99                                                 "save any unsaved designs and restart OpenRocket!"
100                                         }, "Unknown Java error", JOptionPane.ERROR_MESSAGE);
101                         return;
102                 }
103                 
104                 
105                 // Normal exception, show question dialog
106                 
107                 int selection = JOptionPane.showOptionDialog(null, new Object[] {
108                                 "OpenRocket encountered an uncaught exception.  This typically signifies " +
109                                 "a bug in the software.", " ",
110                                 "Please take a moment to report this bug to the developers.",
111                                 "This can be done automatically if you have an Internet connection."
112                                 }, "Uncaught exception", JOptionPane.DEFAULT_OPTION, 
113                                 JOptionPane.ERROR_MESSAGE, null, 
114                                 new Object[] { "View bug report", "Close" }, "View bug report");
115                 
116                 if (selection != 0) {
117                         // User cancelled
118                         return;
119                 }
120                 
121                 // Show bug report dialog
122                 BugReportDialog.showExceptionDialog(null, t, e);
123
124         }
125         
126         
127         
128         /**
129          * Registers the uncaught exception handler.  This should be used to ensure that
130          * all necessary registrations are performed.
131          */
132         public static void registerExceptionHandler() {
133                 
134                 if (instance == null) {
135                         instance = new ExceptionHandler();
136                         Thread.setDefaultUncaughtExceptionHandler(instance);
137                         
138                         // Handler for modal dialogs of Sun's Java implementation
139                         // See bug ID 4499199.
140                         System.setProperty("sun.awt.exception.handler", AwtHandler.class.getName());
141                         
142                         reserveMemory();
143                 }
144                 
145         }
146         
147         
148         private static void reserveMemory() {
149                 memoryReserve = new byte[MEMORY_RESERVE];
150                 for (int i=0; i<MEMORY_RESERVE; i++) {
151                         memoryReserve[i] = (byte)i;
152                 }
153         }
154
155         
156         /**
157          * Handler used in modal dialogs by Sun Java implementation.
158          */
159         public static class AwtHandler {
160                 public void handle(Throwable t) {
161                         if (instance != null) {
162                                 instance.uncaughtException(Thread.currentThread(), t);
163                         }
164                 }
165         }
166 }