File Source: ErrorManager.java
1 /*
2 * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 package com.dmdirc.logger;
24
25 import com.dmdirc.config.ConfigManager;
26 import com.dmdirc.config.IdentityManager;
27 import com.dmdirc.interfaces.ConfigChangeListener;
28 import com.dmdirc.ui.FatalErrorDialog;
29 import com.dmdirc.util.ListenerList;
30
31 import java.awt.GraphicsEnvironment;
32 import java.io.Serializable;
33 import java.util.Date;
34 import java.util.LinkedList;
35 import java.util.List;
36 import java.util.concurrent.BlockingQueue;
37 import java.util.concurrent.LinkedBlockingQueue;
38 import java.util.concurrent.atomic.AtomicLong;
39
40 /**
41 * Error manager.
42 */
43 public final class ErrorManager implements Serializable, ConfigChangeListener {
44
45 /**
46 * A version number for this class. It should be changed whenever the class
47 * structure is changed (or anything else that would prevent serialized
48 * objects being unserialized with the new class).
49 */
50 private static final long serialVersionUID = 4;
51
52 /** Previously instantiated instance of ErrorManager. */
/*
P/P * Method: com.dmdirc.logger.ErrorManager__static_init
*
* Postconditions:
* BANNED_EXCEPTIONS == &new Class[](ErrorManager__static_init#2)
* me == &new ErrorManager(ErrorManager__static_init#1)
* new AtomicLong(ErrorManager#4) num objects == 1
* new Class[](ErrorManager__static_init#2) num objects == 1
* new ErrorManager(ErrorManager__static_init#1) num objects == 1
* new LinkedBlockingQueue(ErrorManager#1) num objects == 1
* new LinkedList(ErrorManager#3) num objects == 1
* new ListenerList(ErrorManager#2) num objects == 1
* BANNED_EXCEPTIONS.length == 5
* me.errorListeners == &new ListenerList(ErrorManager#2)
* ...
*/
53 private static final ErrorManager me = new ErrorManager();
54
55 /** A list of exceptions which we don't consider bugs and thus don't report. */
56 private static final Class[] BANNED_EXCEPTIONS = new Class[]{
57 NoSuchMethodError.class, NoClassDefFoundError.class,
58 UnsatisfiedLinkError.class, AbstractMethodError.class,
59 IllegalAccessError.class,
60 };
61
62 /** Whether or not to send error reports. */
63 private boolean sendReports;
64
65 /** Whether or not to log error reports. */
66 private boolean logReports;
67
68 /** Queue of errors to be reported. */
69 private final BlockingQueue<ProgramError> reportQueue = new LinkedBlockingQueue<ProgramError>();
70
71 /** Thread used for sending errors. */
72 private volatile Thread reportThread;
73
74 /** Error list. */
75 private final List<ProgramError> errors;
76
77 /** Listener list. */
78 private final ListenerList errorListeners = new ListenerList();
79
80 /** Next error ID. */
81 private AtomicLong nextErrorID;
82
83 /** Creates a new instance of ErrorListDialog. */
/*
P/P * Method: void com.dmdirc.logger.ErrorManager()
*
* Presumptions:
* com.dmdirc.config.IdentityManager:getGlobalConfig(...)@88 != null
*
* Postconditions:
* this.errorListeners == &new ListenerList(ErrorManager#2)
* this.errors == &new LinkedList(ErrorManager#3)
* init'ed(this.logReports)
* this.nextErrorID == &new AtomicLong(ErrorManager#4)
* this.reportQueue == &new LinkedBlockingQueue(ErrorManager#1)
* init'ed(this.sendReports)
* new AtomicLong(ErrorManager#4) num objects == 1
* new LinkedBlockingQueue(ErrorManager#1) num objects == 1
* new LinkedList(ErrorManager#3) num objects == 1
* new ListenerList(ErrorManager#2) num objects == 1
*/
84 private ErrorManager() {
85 errors = new LinkedList<ProgramError>();
86 nextErrorID = new AtomicLong();
87
88 final ConfigManager config = IdentityManager.getGlobalConfig();
89
90 config.addChangeListener("general", "logerrors", this);
91 config.addChangeListener("general", "submitErrors", this);
92 config.addChangeListener("temp", "noerrorreporting", this);
93
94 updateSettings();
95 }
96
97 /**
98 * Returns the instance of ErrorManager.
99 *
100 * @return Instance of ErrorManager
101 */
102 public static ErrorManager getErrorManager() {
/*
P/P * Method: ErrorManager getErrorManager()
*
* Postconditions:
* return_value == &new ErrorManager(ErrorManager__static_init#1)
*/
103 synchronized (me) {
104 return me;
105 }
106 }
107
108 /**
109 * Adds a new error to the manager with the specified details. It is
110 * assumed that errors without exceptions or details are not application
111 * errors.
112 *
113 * @param level The severity of the error
114 * @param message The error message
115 * @since 0.6.3m1
116 */
117 protected void addError(final ErrorLevel level, final String message) {
/*
P/P * Method: void addError(ErrorLevel, String)
*
* Preconditions:
* level != null
* message != null
* this.errors != null
* init'ed(this.logReports)
* this.nextErrorID != null
* (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[...])
* (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
* (soft) init'ed(this.reportThread)
* (soft) this.errorListeners != null
* (soft) this.reportQueue != null
* ...
*
* Postconditions:
* com/dmdirc/logger/ProgramError.errorDir == One-of{old com/dmdirc/logger/ProgramError.errorDir, &new File(getErrorFile#1)}
* init'ed(com/dmdirc/logger/ProgramError.errorDir)
* this.reportThread == old this.reportThread
* init'ed(this.reportThread)
* new ErrorReportingThread(sendError#1) num objects == 0
* init'ed(new ErrorReportingThread(sendError#1).queue)
* new File(getErrorFile#1) num objects <= 1
*/
118 addError(level, message, new String[0], false);
119 }
120
121 /**
122 * Adds a new error to the manager with the specified details.
123 *
124 * @param level The severity of the error
125 * @param message The error message
126 * @param exception The exception that caused this error
127 * @param appError Whether or not this is an application error
128 * @since 0.6.3m1
129 */
130 protected void addError(final ErrorLevel level, final String message,
131 final Throwable exception, final boolean appError) {
/*
P/P * Method: void addError(ErrorLevel, String, Throwable, bool)
*
* Preconditions:
* level != null
* message != null
* this.errors != null
* init'ed(this.logReports)
* this.nextErrorID != null
* (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[...])
* (soft) BANNED_EXCEPTIONS[...] != null
* (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
* (soft) init'ed(this.reportThread)
* (soft) this.errorListeners != null
* ...
*
* Presumptions:
* getTrace(...).length <= 232-1
*
* Postconditions:
* com/dmdirc/logger/ProgramError.errorDir == One-of{old com/dmdirc/logger/ProgramError.errorDir, &new File(getErrorFile#1)}
* init'ed(com/dmdirc/logger/ProgramError.errorDir)
* this.reportThread == One-of{old this.reportThread, &new ErrorReportingThread(sendError#1)}
* init'ed(this.reportThread)
* new ErrorReportingThread(sendError#1) num objects <= 1
* init'ed(new ErrorReportingThread(sendError#1).queue)
* new File(getErrorFile#1) num objects <= 1
*/
132 addError(level, message, getTrace(exception), appError, isValidError(exception));
133 }
134
135 /**
136 * Adds a new error to the manager with the specified details.
137 *
138 * @param level The severity of the error
139 * @param message The error message
140 * @param details The details of the exception
141 * @param appError Whether or not this is an application error
142 * @since 0.6.3m1
143 */
144 protected void addError(final ErrorLevel level, final String message,
145 final String[] details, final boolean appError) {
/*
P/P * Method: void addError(ErrorLevel, String, String[], bool)
*
* Preconditions:
* details != null
* details.length <= 232-1
* level != null
* message != null
* this.errors != null
* init'ed(this.logReports)
* this.nextErrorID != null
* (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[...])
* (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
* (soft) init'ed(this.reportThread)
* ...
*
* Postconditions:
* com/dmdirc/logger/ProgramError.errorDir == One-of{old com/dmdirc/logger/ProgramError.errorDir, &new File(getErrorFile#1)}
* init'ed(com/dmdirc/logger/ProgramError.errorDir)
* this.reportThread == One-of{old this.reportThread, &new ErrorReportingThread(sendError#1)}
* init'ed(this.reportThread)
* new ErrorReportingThread(sendError#1) num objects <= 1
* init'ed(new ErrorReportingThread(sendError#1).queue)
* new File(getErrorFile#1) num objects <= 1
*/
146 addError(level, message, details, appError, true);
147 }
148
149 /**
150 * Adds a new error to the manager with the specified details.
151 *
152 * @param level The severity of the error
153 * @param message The error message
154 * @param details The details of the exception
155 * @param appError Whether or not this is an application error
156 * @param canReport Whether or not this error can be reported
157 * @since 0.6.3m1
158 */
159 protected void addError(final ErrorLevel level, final String message,
160 final String[] details, final boolean appError, final boolean canReport) {
/*
P/P * Method: void addError(ErrorLevel, String, String[], bool, bool)
*
* Preconditions:
* details != null
* details.length <= 232-1
* level != null
* message != null
* this.errors != null
* init'ed(this.logReports)
* this.nextErrorID != null
* (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[...])
* (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
* (soft) init'ed(this.reportThread)
* ...
*
* Presumptions:
* error.trace.length in {1..232-1}
* error.trace[0] != null
* error.trace[...] != null
*
* Postconditions:
* com/dmdirc/logger/ProgramError.errorDir == One-of{old com/dmdirc/logger/ProgramError.errorDir, &new File(getErrorFile#1)}
* init'ed(com/dmdirc/logger/ProgramError.errorDir)
* this.reportThread == One-of{old this.reportThread, &new ErrorReportingThread(sendError#1)}
* init'ed(this.reportThread)
* new ErrorReportingThread(sendError#1) num objects <= 1
* init'ed(new ErrorReportingThread(sendError#1).queue)
* new File(getErrorFile#1) num objects <= 1
*
* Test Vectors:
* appError: {0}, {1}
* canReport: {0}, {1}
* this.logReports: {0}, {1}
* this.sendReports: {0}, {1}
*/
161 final ProgramError error = getError(level, message, details, appError);
162
163 if (addError(error) && canReport) {
164 error.setReportStatus(ErrorReportStatus.NOT_APPLICABLE);
165 error.setFixedStatus(ErrorFixedStatus.KNOWN);
166 } else if (!canReport || (appError && !error.isValidSource())) {
167 error.setReportStatus(ErrorReportStatus.NOT_APPLICABLE);
168 error.setFixedStatus(ErrorFixedStatus.INVALID);
169 } else if (!appError) {
170 error.setReportStatus(ErrorReportStatus.NOT_APPLICABLE);
171 error.setFixedStatus(ErrorFixedStatus.UNREPORTED);
172 } else if (sendReports) {
173 sendError(error);
174 }
175
176 if (logReports) {
177 error.save();
178 }
179
180 if (level == ErrorLevel.FATAL) {
181 fireFatalError(error);
182 } else {
183 fireErrorAdded(error);
184 }
185 }
186
187 /**
188 * Adds the specified error to the list of known errors and determines if
189 * it was previously added.
190 *
191 * @param error The error to be added
192 * @return True if a duplicate error has already been registered, false
193 * otherwise
194 */
195 protected boolean addError(final ProgramError error) {
/*
P/P * Method: bool addError(ProgramError)
*
* Preconditions:
* this.errors != null
*
* Postconditions:
* init'ed(return_value)
*/
196 boolean res = false;
197
198 synchronized (errors) {
199 res = errors.contains(error);
200 errors.add(error);
201 }
202
203 return res;
204 }
205
206 /**
207 * Retrieves a {@link ProgramError} that represents the specified details.
208 *
209 * @param level The severity of the error
210 * @param message The error message
211 * @param details The details of the exception
212 * @param appError Whether or not this is an application error
213 * @since 0.6.3m1
214 * @return A corresponding ProgramError
215 */
216 protected ProgramError getError(final ErrorLevel level, final String message,
217 final String[] details, final boolean appError) {
/*
P/P * Method: ProgramError getError(ErrorLevel, String, String[], bool)
*
* Preconditions:
* details != null
* details.length <= 232-1
* level != null
* message != null
* this.nextErrorID != null
*
* Presumptions:
* java.util.concurrent.atomic.AtomicLong:getAndIncrement(...)@218 >= 0
*
* Postconditions:
* return_value == &new ProgramError(getError#1)
* new ProgramError(getError#1) num objects == 1
* return_value.date != null
* return_value.fixedStatus == &com.dmdirc.logger.ErrorFixedStatus__static_init.new ErrorFixedStatus(ErrorFixedStatus__static_init#7)
* return_value.id >= 0
* return_value.level == level
* return_value.level != null
* return_value.message == message
* return_value.message != null
* return_value.reportStatus == &com.dmdirc.logger.ErrorReportStatus__static_init.new ErrorReportStatus(ErrorReportStatus__static_init#6)
* ...
*/
218 return new ProgramError(nextErrorID.getAndIncrement(), level, message,
219 details, new Date());
220 }
221
222 /**
223 * Determines whether or not the specified exception is one that we are
224 * willing to report.
225 *
226 * @param exception The exception to test
227 * @since 0.6.3m1
228 * @return True if the exception may be reported, false otherwise
229 */
230 protected boolean isValidError(final Throwable exception) {
/*
P/P * Method: bool isValidError(Throwable)
*
* Preconditions:
* (soft) BANNED_EXCEPTIONS[...] != null
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* java.lang.Object:equals(...)@235: {0}, {1}
*/
231 Throwable target = exception;
232
233 while (target != null) {
234 for (Class bad : BANNED_EXCEPTIONS) {
235 if (bad.equals(target.getClass())) {
236 return false;
237 }
238 }
239
240 target = target.getCause();
241 }
242
243 return true;
244 }
245
246 /**
247 * Converts an exception into a string array.
248 *
249 * @param throwable Exception to convert
250 * @since 0.6.3m1
251 * @return Exception string array
252 */
253 protected String[] getTrace(final Throwable throwable) {
254 String[] trace;
255
/*
P/P * Method: String[] getTrace(Throwable)
*
* Presumptions:
* java.lang.Throwable:getStackTrace(...)@259 != null
* traceElements.length@259 <= 232-1
* traceElements[i]@259 != null
*
* Postconditions:
* java.lang.StackTraceElement:toString(...)._tainted == 0
* possibly_updated(java.lang.StackTraceElement:toString(...)._tainted)
* init'ed(java.lang.StringBuilder:toString(...)._tainted)
* java.lang.StringBuilder:toString(...)._tainted == 0
* possibly_updated(java.lang.StringBuilder:toString(...)._tainted)
* init'ed(java.lang.Throwable:toString(...)._tainted)
* java.lang.Throwable:toString(...)._tainted == 0
* possibly_updated(java.lang.Throwable:toString(...)._tainted)
* return_value == One-of{&new String[](getTrace#1), &new String[](getTrace#2), &new String[](getTrace#3)}
* return_value in Addr_Set{&new String[](getTrace#2),&new String[](getTrace#3),&new String[](getTrace#1)}
* ...
*
* Test Vectors:
* throwable: Inverse{null}, Addr_Set{null}
* java.lang.Throwable:getCause(...)@268: Addr_Set{null}, Inverse{null}
*/
256 if (throwable == null) {
257 trace = new String[0];
258 } else {
259 final StackTraceElement[] traceElements = throwable.getStackTrace();
260 trace = new String[traceElements.length + 1];
261
262 trace[0] = throwable.toString();
263
264 for (int i = 0; i < traceElements.length; i++) {
265 trace[i + 1] = traceElements[i].toString();
266 }
267
268 if (throwable.getCause() != null) {
269 final String[] causeTrace = getTrace(throwable.getCause());
270 final String[] newTrace = new String[trace.length + causeTrace.length];
271 trace[0] = "\nWhich caused: " + trace[0];
272
273 System.arraycopy(causeTrace, 0, newTrace, 0, causeTrace.length);
274 System.arraycopy(trace, 0, newTrace, causeTrace.length, trace.length);
275
276 trace = newTrace;
277 }
278 }
279
280 return trace;
281 }
282
283 /**
284 * Sends an error to the developers.
285 *
286 * @param error error to be sent
287 */
288 public void sendError(final ProgramError error) {
/*
P/P * Method: void sendError(ProgramError)
*
* Preconditions:
* error != null
* init'ed(error.reportStatus)
* (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[...])
* (soft) init'ed(this.reportThread)
* (soft) this.reportQueue != null
*
* Postconditions:
* error.reportStatus == One-of{old error.reportStatus, &com.dmdirc.logger.ErrorReportStatus__static_init.new ErrorReportStatus(ErrorReportStatus__static_init#5)}
* init'ed(error.reportStatus)
* this.reportThread == One-of{old this.reportThread, &new ErrorReportingThread(sendError#1)}
* init'ed(this.reportThread)
* new ErrorReportingThread(sendError#1) num objects <= 1
* new ErrorReportingThread(sendError#1).queue == this.reportQueue
* new ErrorReportingThread(sendError#1).queue != null
*
* Test Vectors:
* this.reportThread: Addr_Set{null}, Inverse{null}
* java.lang.Thread:isAlive(...)@298: {1}, {0}
*/
289 if (error.getReportStatus() != ErrorReportStatus.ERROR
290 && error.getReportStatus() != ErrorReportStatus.WAITING) {
291 return;
292 }
293
294 error.setReportStatus(ErrorReportStatus.QUEUED);
295
296 reportQueue.add(error);
297
298 if (reportThread == null || !reportThread.isAlive()) {
299 reportThread = new ErrorReportingThread(reportQueue);
300 reportThread.start();
301 }
302 }
303
304 /**
305 * Called when an error needs to be deleted from the list.
306 *
307 * @param error ProgramError that changed
308 */
309 public void deleteError(final ProgramError error) {
/*
P/P * Method: void deleteError(ProgramError)
*
* Preconditions:
* this.errorListeners != null
* this.errors != null
*/
310 synchronized (errors) {
311 errors.remove(error);
312 }
313
314 fireErrorDeleted(error);
315 }
316
317 /**
318 * Deletes all errors from the manager.
319 *
320 * @since 0.6.3m1
321 */
322 public void deleteAll() {
/*
P/P * Method: void deleteAll()
*
* Preconditions:
* this.errors != null
* (soft) this.errorListeners != null
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@324: {0}, {1}
*/
323 synchronized (errors) {
324 for (ProgramError error : errors) {
325 fireErrorDeleted(error);
326 }
327
328 errors.clear();
329 }
330 }
331
332 /**
333 * Returns the number of errors.
334 *
335 * @return Number of ProgramErrors
336 */
337 public int getErrorCount() {
/*
P/P * Method: int getErrorCount()
*
* Preconditions:
* this.errors != null
*
* Postconditions:
* init'ed(return_value)
*/
338 return errors.size();
339 }
340
341 /**
342 * Returns the list of program errors.
343 *
344 * @return Program error list
345 */
346 public List<ProgramError> getErrors() {
/*
P/P * Method: List getErrors()
*
* Postconditions:
* return_value == &new LinkedList(getErrors#1)
* new LinkedList(getErrors#1) num objects == 1
*/
347 synchronized (errors) {
348 return new LinkedList<ProgramError>(errors);
349 }
350 }
351
352 /**
353 * Adds an ErrorListener to the listener list.
354 *
355 * @param listener Listener to add
356 */
357 public void addErrorListener(final ErrorListener listener) {
/*
P/P * Method: void addErrorListener(ErrorListener)
*
* Preconditions:
* (soft) this.errorListeners != null
*
* Test Vectors:
* listener: Inverse{null}, Addr_Set{null}
*/
358 if (listener == null) {
359 return;
360 }
361
362 errorListeners.add(ErrorListener.class, listener);
363 }
364
365 /**
366 * Removes an ErrorListener from the listener list.
367 *
368 * @param listener Listener to remove
369 */
370 public void removeErrorListener(final ErrorListener listener) {
/*
P/P * Method: void removeErrorListener(ErrorListener)
*
* Preconditions:
* this.errorListeners != null
*/
371 errorListeners.remove(ErrorListener.class, listener);
372 }
373
374 /**
375 * Fired when the program encounters an error.
376 *
377 * @param error Error that occurred
378 */
379 protected void fireErrorAdded(final ProgramError error) {
/*
P/P * Method: void fireErrorAdded(ProgramError)
*
* Preconditions:
* error != null
* error.trace != null
* error.trace.length <= 232-1
* this.errorListeners != null
*
* Presumptions:
* arr$.length <= 232-1
* com.dmdirc.util.ListenerList:get(...)@382 != null
* java.lang.System.err != null
* java.util.Arrays:copyOf(...)@148 != null
* java.util.Iterator:next(...)@382 != null
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@382: {0}, {1}
*/
380 int firedListeners = 0;
381
382 for (ErrorListener listener : errorListeners.get(ErrorListener.class)) {
383 if (listener.isReady()) {
384 listener.errorAdded(error);
385 firedListeners++;
386 }
387 }
388
389 if (firedListeners == 0) {
390 System.err.println("An error has occurred: " + error.getLevel()
391 + ": " + error.getMessage());
392
393 for (String line : error.getTrace()) {
394 System.err.println("\t" + line);
395 }
396 }
397 }
398
399 /**
400 * Fired when the program encounters a fatal error.
401 *
402 * @param error Error that occurred
403 */
404 protected void fireFatalError(final ProgramError error) {
/*
P/P * Method: void fireFatalError(ProgramError)
* fireFatalError does not return
*
* Preconditions:
* error != null
* error.reportStatus != null
* (soft) error.trace != null
* (soft) error.trace.length <= 232-1
*
* Presumptions:
* arr$.length <= 232-1
* java.lang.System.err != null
* java.util.Arrays:copyOf(...)@148 != null
*
* Test Vectors:
* java.awt.GraphicsEnvironment:isHeadless(...)@405: {0}, {1}
*/
405 if (GraphicsEnvironment.isHeadless()) {
406 System.err.println("A fatal error has occurred: " + error.getMessage());
407 for (String line : error.getTrace()) {
408 System.err.println("\t" + line);
409 }
410 } else {
411 FatalErrorDialog.displayBlocking(error);
412 }
413
414 while (!error.getReportStatus().isTerminal()) {
415 try {
416 synchronized (error) {
417 error.wait();
418 }
419 } catch (InterruptedException ex) {
420 // Do nothing
421 }
422 }
423
424 System.exit(-1);
425 }
426
427 /**
428 * Fired when an error is deleted.
429 *
430 * @param error Error that has been deleted
431 */
432 protected void fireErrorDeleted(final ProgramError error) {
/*
P/P * Method: void fireErrorDeleted(ProgramError)
*
* Preconditions:
* this.errorListeners != null
*
* Presumptions:
* com.dmdirc.util.ListenerList:get(...)@433 != null
* java.util.Iterator:next(...)@433 != null
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@433: {0}, {1}
*/
433 for (ErrorListener listener : errorListeners.get(ErrorListener.class)) {
434 listener.errorDeleted(error);
435 }
436 }
437
438 /**
439 * Fired when an error's status is changed.
440 *
441 * @param error Error that has been altered
442 */
443 protected void fireErrorStatusChanged(final ProgramError error) {
/*
P/P * Method: void fireErrorStatusChanged(ProgramError)
*
* Preconditions:
* this.errorListeners != null
* (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[...])
* (soft) error.reportStatus != null
*
* Presumptions:
* com.dmdirc.util.ListenerList:get(...)@444 != null
* java.util.Iterator:next(...)@444 != null
* listener.error.message@444 != null
* listener.error@444 != null
* listener.okButton@444 != null
* ...
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@444: {0}, {1}
*/
444 for (ErrorListener listener : errorListeners.get(ErrorListener.class)) {
445 listener.errorStatusChanged(error);
446 }
447 }
448
449 /** {@inheritDoc} */
450 @Override
451 public void configChanged(final String domain, final String key) {
/*
P/P * Method: void configChanged(String, String)
*
* Postconditions:
* init'ed(this.logReports)
* init'ed(this.sendReports)
*/
452 updateSettings();
453 }
454
455 /** Updates the settings used by this error manager. */
456 protected void updateSettings() {
/*
P/P * Method: void updateSettings()
*
* Presumptions:
* com.dmdirc.config.IdentityManager:getGlobalConfig(...)@457 != null
*
* Postconditions:
* init'ed(this.logReports)
* init'ed(this.sendReports)
*/
457 final ConfigManager config = IdentityManager.getGlobalConfig();
458
459 try {
460 sendReports = config.getOptionBool("general", "submitErrors")
461 && !config.getOptionBool("temp", "noerrorreporting");
462 logReports = config.getOptionBool("general", "logerrors");
463 } catch (IllegalArgumentException ex) {
464 sendReports = false;
465 logReports = true;
466 }
467 }
468
469 }
SofCheck Inspector Build Version : 2.17854
| ErrorManager.java |
2009-Jun-25 01:54:24 |
| ErrorManager.class |
2009-Sep-02 17:04:14 |