| | 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 xxx |
| | 32 | */ |
| | 33 | public 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 | public 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 | 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 | |
| | 78 | } |