source: josm/trunk/src/org/openstreetmap/josm/tools/BugReportExceptionHandler.java@ 655

Last change on this file since 655 was 655, checked in by ramack, 16 years ago

patch by bruce89, closes #812; thanks bruce

  • Property svn:eol-style set to native
File size: 6.9 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.tools;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.GridBagLayout;
7import java.awt.Toolkit;
8import java.awt.datatransfer.Clipboard;
9import java.awt.datatransfer.ClipboardOwner;
10import java.awt.datatransfer.StringSelection;
11import java.awt.datatransfer.Transferable;
12import java.io.BufferedReader;
13import java.io.File;
14import java.io.InputStreamReader;
15import java.io.PrintWriter;
16import java.io.StringWriter;
17import java.net.URL;
18import java.text.DateFormat;
19import java.text.SimpleDateFormat;
20import java.util.Arrays;
21import java.util.Date;
22import java.util.LinkedList;
23
24import javax.swing.JLabel;
25import javax.swing.JOptionPane;
26import javax.swing.JPanel;
27import javax.swing.JScrollPane;
28import javax.swing.JTextArea;
29
30import org.openstreetmap.josm.Main;
31import org.openstreetmap.josm.plugins.PluginException;
32import org.openstreetmap.josm.plugins.PluginProxy;
33
34/**
35 * An exception handler that asks the user to send a bug report.
36 *
37 * @author imi
38 */
39public final class BugReportExceptionHandler implements Thread.UncaughtExceptionHandler {
40
41 public void uncaughtException(Thread t, Throwable e) {
42 e.printStackTrace();
43 if (Main.parent != null) {
44 if (e instanceof OutOfMemoryError) {
45 // do not translate the string, as translation may raise an exception
46 JOptionPane.showMessageDialog(Main.parent, "You are out of memory. Strange things may happen.\nPlease restart JOSM and load smaller data sets.");
47 return;
48 }
49
50 PluginProxy plugin = null;
51
52 // Check for an explicit problem when calling a plugin function
53 if (e instanceof PluginException)
54 plugin = ((PluginException)e).plugin;
55
56 if (plugin == null)
57 plugin = guessPlugin(e);
58
59 if (plugin != null) {
60 int answer = JOptionPane.showConfirmDialog(
61 Main.parent,
62 tr("An unexpected exception occurred that may have come from the ''{0}'' plugin.", plugin.info.name)+"\n"+
63 (plugin.info.author != null ? tr("According to the information within the plugin, the author is {0}.", plugin.info.author) : "")+"\n"+
64 tr("Should the plugin be disabled?"),
65 tr("Disable plugin"),
66 JOptionPane.YES_NO_OPTION);
67 if (answer == JOptionPane.OK_OPTION) {
68 LinkedList<String> plugins = new LinkedList<String>(Arrays.asList(Main.pref.get("plugins").split(",")));
69 if (plugins.contains(plugin.info.name)) {
70 while (plugins.remove(plugin.info.name)) {}
71 String p = "";
72 for (String s : plugins)
73 p += ","+s;
74 if (p.length() > 0)
75 p = p.substring(1);
76 Main.pref.put("plugins", p);
77 JOptionPane.showMessageDialog(Main.parent, tr("The plugin has been removed from the configuration. Please restart JOSM to unload the plugin."));
78 } else {
79 JOptionPane.showMessageDialog(Main.parent, tr("The plugin could not be removed. Please tell the people you got JOSM from about the problem."));
80 }
81 return;
82 }
83 }
84
85 Object[] options = new String[]{tr("Do nothing"), tr("Report Bug")};
86 int answer = JOptionPane.showOptionDialog(Main.parent, tr("An unexpected exception occurred.\n\n" +
87 "This is always a coding error. If you are running the latest\n" +
88 "version of JOSM, please consider being kind and file a bug report."),
89 tr("Unexpected Exception"), JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE,
90 null, options, options[0]);
91 if (answer == 1) {
92 try {
93 StringWriter stack = new StringWriter();
94 e.printStackTrace(new PrintWriter(stack));
95
96 URL revUrl = Main.class.getResource("/REVISION");
97 StringBuilder sb = new StringBuilder();
98 if (revUrl == null) {
99 sb.append("Development version. Unknown revision.");
100 File f = new File("org/openstreetmap/josm/Main.class");
101 if (!f.exists())
102 f = new File("bin/org/openstreetmap/josm/Main.class");
103 if (!f.exists())
104 f = new File("build/org/openstreetmap/josm/Main.class");
105 if (f.exists()) {
106 DateFormat sdf = SimpleDateFormat.getDateTimeInstance();
107 sb.append("\nMain.class build on "+sdf.format(new Date(f.lastModified())));
108 sb.append("\n");
109 }
110 } else {
111 BufferedReader in = new BufferedReader(new InputStreamReader(revUrl.openStream()));
112 for (String line = in.readLine(); line != null; line = in.readLine()) {
113 sb.append(line);
114 sb.append('\n');
115 }
116 }
117 sb.append("\n"+stack.getBuffer().toString());
118
119 JPanel p = new JPanel(new GridBagLayout());
120 p.add(new JLabel(tr("Please report a ticket at http://josm.openstreetmap.de/newticket, including your steps to get to\n" +
121 "the error and be sure to include the following information")), GBC.eol());
122 try {
123 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(sb.toString()), new ClipboardOwner(){
124 public void lostOwnership(Clipboard clipboard, Transferable contents) {}
125 });
126 p.add(new JLabel(tr("The text has already been copied to your clipboard.")), GBC.eop());
127 } catch (RuntimeException x) {
128 }
129
130 JTextArea info = new JTextArea(sb.toString(), 20, 60);
131 info.setCaretPosition(0);
132 info.setEditable(false);
133 p.add(new JScrollPane(info), GBC.eop());
134
135 JOptionPane.showMessageDialog(Main.parent, p);
136 } catch (Exception e1) {
137 e1.printStackTrace();
138 }
139 }
140 }
141 }
142
143 private PluginProxy guessPlugin(Throwable e) {
144 String name = guessPluginName(e);
145 for (PluginProxy p : Main.plugins)
146 if (p.info.name.equals(name))
147 return p;
148 return null;
149 }
150
151 /**
152 * Analyze the stack of the argument and return a name of a plugin, if
153 * some known problem pattern has been found or <code>null</code>, if
154 * the stack does not contain plugin-code.
155 *
156 * Note: This heuristic is not meant as discrimination against specific
157 * plugins, but only to stop the flood of similar bug reports about plugins.
158 * Of course, plugin writers are free to install their own version of
159 * an exception handler with their email address listed to receive
160 * bug reports ;-).
161 */
162 private String guessPluginName(Throwable e) {
163 for (StackTraceElement element : e.getStackTrace()) {
164 String c = element.getClassName();
165
166 if (c.contains("wmsplugin.") || c.contains(".WMSLayer"))
167 return "wmsplugin";
168 if (c.contains("landsat.") || c.contains(".LandsatLayer"))
169 return "landsat";
170 if (c.contains("livegps."))
171 return "livegps";
172 if (c.contains("mappaint."))
173 return "mappaint";
174 if (c.contains("annotationtester."))
175 return "annotation-tester";
176 if (c.startsWith("UtilsPlugin."))
177 return "UtilsPlugin";
178
179 if (c.startsWith("org.openstreetmap.josm.plugins.")) {
180 String p = c.substring("org.openstreetmap.josm.plugins.".length());
181 if (p.indexOf('.') != -1 && p.matches("[a-z].*")) {
182 return p.substring(0,p.indexOf('.'));
183 }
184 }
185 }
186 return null;
187 }
188}
Note: See TracBrowser for help on using the repository browser.