1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.tools.bugreport;
|
---|
3 |
|
---|
4 | /**
|
---|
5 | * This class contains utility methods to create and handle a bug report.
|
---|
6 | * <p>
|
---|
7 | * It allows you to configure the format and request to send the bug report.
|
---|
8 | * <p>
|
---|
9 | * It also contains the main entry point for all components to use the bug report system: Call {@link #intercept(Throwable)} to start handling an
|
---|
10 | * exception.
|
---|
11 | * <h1> Handling Exceptions </h1>
|
---|
12 | * In your code, you should add try...catch blocks for any runtime exceptions that might happen. It is fine to catch throwable there.
|
---|
13 | * <p>
|
---|
14 | * You should then add some debug information there. This can be the OSM ids that caused the error, information on the data you were working on
|
---|
15 | * or other local variables. Make sure that no excpetions may occur while computing the values. It is best to send plain local variables to
|
---|
16 | * put(...). Then simply throw the throwable you got from the bug report. The global exception handler will do the rest.
|
---|
17 | * <pre>
|
---|
18 | * int id = ...;
|
---|
19 | * String tag = "...";
|
---|
20 | * try {
|
---|
21 | * ... your code ...
|
---|
22 | * } catch (Throwable t) {
|
---|
23 | * throw BugReport.intercept(t).put("id", id).put("tag", tag);
|
---|
24 | * }
|
---|
25 | * </pre>
|
---|
26 | *
|
---|
27 | * Instead of re-throwing, you can call {@link ReportedException#warn()}. This will display a warning to the user and allow it to either report
|
---|
28 | * the execption or ignore it.
|
---|
29 | *
|
---|
30 | * @author Michael Zangl
|
---|
31 | * @since 10285
|
---|
32 | */
|
---|
33 | public final class BugReport {
|
---|
34 | /**
|
---|
35 | * Create a new bug report
|
---|
36 | * @param e The {@link ReportedException} to use. No more data should be added after creating the report.
|
---|
37 | */
|
---|
38 | private BugReport(ReportedException e) {
|
---|
39 | // TODO: Use this class to create the bug report.
|
---|
40 | }
|
---|
41 |
|
---|
42 | /**
|
---|
43 | * This should be called whenever you want to add more information to a given exception.
|
---|
44 | * @param t The throwable that was thrown.
|
---|
45 | * @return A {@link ReportedException} to which you can add additional information.
|
---|
46 | */
|
---|
47 | public static ReportedException intercept(Throwable t) {
|
---|
48 | ReportedException e;
|
---|
49 | if (t instanceof ReportedException) {
|
---|
50 | e = (ReportedException) t;
|
---|
51 | } else {
|
---|
52 | e = new ReportedException(t);
|
---|
53 | }
|
---|
54 | e.startSection(getCallingMethod(2));
|
---|
55 | return e;
|
---|
56 | }
|
---|
57 |
|
---|
58 | /**
|
---|
59 | * Find the method that called us.
|
---|
60 | *
|
---|
61 | * @param offset
|
---|
62 | * How many methods to look back in the stack trace. 1 gives the method calling this method, 0 gives you getCallingMethod().
|
---|
63 | * @return The method name.
|
---|
64 | */
|
---|
65 | public static String getCallingMethod(int offset) {
|
---|
66 | StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
---|
67 | String className = BugReport.class.getName();
|
---|
68 | for (int i = 0; i < stackTrace.length - offset; i++) {
|
---|
69 | StackTraceElement element = stackTrace[i];
|
---|
70 | if (className.equals(element.getClassName()) && "getCallingMethod".equals(element.getMethodName())) {
|
---|
71 | StackTraceElement toReturn = stackTrace[i + offset];
|
---|
72 | return toReturn.getClassName().replaceFirst(".*\\.", "") + '#' + toReturn.getMethodName();
|
---|
73 | }
|
---|
74 | }
|
---|
75 | return "?";
|
---|
76 | }
|
---|
77 | }
|
---|