source: josm/trunk/src/org/openstreetmap/josm/tools/bugreport/BugReportQueue.java@ 12538

Last change on this file since 12538 was 11535, checked in by Don-vip, 7 years ago

sonar - squid:S2142 - "InterruptedException" should not be ignored

  • Property svn:eol-style set to native
File size: 5.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.tools.bugreport;
3
4import java.awt.GraphicsEnvironment;
5import java.util.ArrayList;
6import java.util.LinkedList;
7import java.util.concurrent.CopyOnWriteArrayList;
8import java.util.function.BiFunction;
9import java.util.function.Predicate;
10
11import org.openstreetmap.josm.Main;
12import org.openstreetmap.josm.tools.Logging;
13
14/**
15 * This class handles the display of the bug report dialog.
16 * @author Michael Zangl
17 * @since 10819
18 */
19public class BugReportQueue {
20
21 private static final BugReportQueue INSTANCE = new BugReportQueue();
22
23 private final LinkedList<ReportedException> reportsToDisplay = new LinkedList<>();
24 private boolean suppressAllMessages;
25 private final ArrayList<ReportedException> suppressFor = new ArrayList<>();
26 private Thread displayThread;
27 private final BiFunction<ReportedException, Integer, SuppressionMode> bugReportHandler = getBestHandler();
28 private final CopyOnWriteArrayList<Predicate<ReportedException>> handlers = new CopyOnWriteArrayList<>();
29 private int displayedErrors;
30
31 private boolean inReportDialog;
32
33 /**
34 * The suppression mode that should be used after the dialog was closed.
35 */
36 public enum SuppressionMode {
37 /**
38 * Suppress no dialogs.
39 */
40 NONE,
41 /**
42 * Suppress only the ones that are for the same error
43 */
44 SAME,
45 /**
46 * Suppress all report dialogs
47 */
48 ALL
49 }
50
51 /**
52 * Submit a new error to be displayed
53 * @param report The error to display
54 */
55 public synchronized void submit(ReportedException report) {
56 Logging.logWithStackTrace(Logging.LEVEL_ERROR, "Handled by bug report queue", report.getCause());
57 if (suppressAllMessages || suppressFor.stream().anyMatch(report::isSame)) {
58 Main.info("User requested to skip error " + report);
59 } else if (reportsToDisplay.size() > 100 || reportsToDisplay.stream().filter(report::isSame).count() >= 10) {
60 Main.warn("Too many errors. Dropping " + report);
61 } else {
62 reportsToDisplay.add(report);
63 if (displayThread == null) {
64 displayThread = new Thread(new BugReportDisplayRunnable(), "bug-report-display");
65 displayThread.start();
66 }
67 notifyAll();
68 }
69 }
70
71 private class BugReportDisplayRunnable implements Runnable {
72
73 private volatile boolean running = true;
74
75 @Override
76 public void run() {
77 try {
78 while (running) {
79 ReportedException e = getNext();
80 handleDialogResult(e, displayFor(e));
81 }
82 } catch (InterruptedException e) {
83 displayFor(BugReport.intercept(e));
84 Thread.currentThread().interrupt();
85 }
86 }
87 }
88
89 private synchronized void handleDialogResult(ReportedException e, SuppressionMode suppress) {
90 if (suppress == SuppressionMode.ALL) {
91 suppressAllMessages = true;
92 reportsToDisplay.clear();
93 } else if (suppress == SuppressionMode.SAME) {
94 suppressFor.add(e);
95 reportsToDisplay.removeIf(e::isSame);
96 }
97 displayedErrors++;
98 inReportDialog = false;
99 }
100
101 private synchronized ReportedException getNext() throws InterruptedException {
102 while (reportsToDisplay.isEmpty()) {
103 wait();
104 }
105 inReportDialog = true;
106 return reportsToDisplay.removeFirst();
107 }
108
109 private SuppressionMode displayFor(ReportedException e) {
110 if (handlers.stream().anyMatch(p -> p.test(e))) {
111 Main.trace("Intercepted by handler.");
112 return SuppressionMode.NONE;
113 }
114 return bugReportHandler.apply(e, getDisplayedErrors());
115 }
116
117 private synchronized int getDisplayedErrors() {
118 return displayedErrors;
119 }
120
121 /**
122 * Check if the dialog is shown. Should only be used for e.g. debugging.
123 * @return <code>true</code> if the exception handler is still showing the exception to the user.
124 */
125 public synchronized boolean exceptionHandlingInProgress() {
126 return !reportsToDisplay.isEmpty() || inReportDialog;
127 }
128
129 private static BiFunction<ReportedException, Integer, SuppressionMode> getBestHandler() {
130 if (GraphicsEnvironment.isHeadless()) {
131 return (e, index) -> {
132 e.printStackTrace();
133 return SuppressionMode.NONE;
134 };
135 } else {
136 return BugReportDialog::showFor;
137 }
138 }
139
140 /**
141 * Allows you to peek or even intersect the bug reports.
142 * @param handler The handler. It can return false to stop all further handling of the exception.
143 * @since 10886
144 */
145 public void addBugReportHandler(Predicate<ReportedException> handler) {
146 handlers.add(handler);
147 }
148
149 /**
150 * Gets the global bug report queue
151 * @return The queue
152 * @since 10886
153 */
154 public static BugReportQueue getInstance() {
155 return INSTANCE;
156 }
157}
Note: See TracBrowser for help on using the repository browser.