Project

General

Profile

Download (18.1 KB) Statistics
| Branch: | Tag: | Revision:
1
package eu.etaxonomy.taxeditor.model;
2

    
3
import java.io.PrintWriter;
4
import java.io.StringWriter;
5
import java.util.ArrayList;
6
import java.util.List;
7

    
8
import org.apache.log4j.Logger;
9
import org.eclipse.core.runtime.IStatus;
10
import org.eclipse.core.runtime.MultiStatus;
11
import org.eclipse.core.runtime.Platform;
12
import org.eclipse.core.runtime.Status;
13
import org.eclipse.jface.dialogs.MessageDialog;
14
import org.eclipse.swt.widgets.Display;
15

    
16
import eu.etaxonomy.cdm.persistence.hibernate.permission.SecurityExceptionUtils;
17
import eu.etaxonomy.taxeditor.store.CdmStore;
18
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
19

    
20
/**
21
 * Utility class which handles all the messaging information generated by the
22
 * Editor.
23
 *
24
 * This includes logging as well as dialogs.
25
 *
26
 * @author cmathew
27
 *
28
 */
29
public class MessagingUtils {
30
    public final static String UNEXPECTED_ERROR_MESSAGE = "This is an unexpected error.";
31
    public final static String CONTACT_MESSAGE = System.getProperty("line.separator") +  "Please contact EDIT Support (EditSupport@bgbm.org) with the error trace below (click on the 'Details' button).";
32

    
33
    /**
34
     * Gets the Log4J logger for a given class
35
     *
36
     * @param clazz
37
     *            a {@link java.lang.Class} object.
38
     * @return a {@link org.apache.log4j.Logger} object.
39
     */
40
    public static Logger getLog4JLogger(Class clazz) {
41
        return Logger.getLogger(clazz);
42
    }
43

    
44
    /**
45
     * Logs details from a given Status object
46
     *
47
     * @param status
48
     * 				a {@link org.eclipse.core.runtime.IStatus} object.
49
     */
50
    private static void log(IStatus status) {
51
        TaxeditorStorePlugin.getDefault().getLog().log(status);
52
    }
53

    
54
    /**
55
     * Logs a status object as information.
56
     *
57
     * @param status
58
     *            a {@link org.eclipse.core.runtime.IStatus} object.
59
     */
60
    public static void info(IStatus status) {
61
        log(status);
62
    }
63

    
64
    /**
65
     * Logs a string as information.
66
     *
67
     * @param message
68
     *            a {@link java.lang.String} object.
69
     */
70
    public static void info(String message) {
71
        IStatus status = new Status(IStatus.INFO, AbstractUtility.getPluginId(), message);
72
        info(status);
73
    }
74

    
75
    /**
76
     * Logs an exception from a given source as a warning.
77
     *
78
     * @param source
79
     * @param t
80
     */
81
    public static void warn(Class source, Throwable t) {
82
        IStatus status = new Status(IStatus.WARNING, AbstractUtility.getPluginId(), t.getMessage(), t);
83
        MessagingUtils.getLog4JLogger(source).warn(t);
84
        log(status);
85
    }
86

    
87
    /**
88
     * Logs a status object from a given source as a warning.
89
     *
90
     * @param source
91
     * @param status
92
     */
93
    public static void warn(Class source, IStatus status) {
94
        MessagingUtils.getLog4JLogger(source).warn(status.getMessage(), status.getException());
95
        log(status);
96
    }
97

    
98
    /**
99
     * Logs a string from a given source as a warning.
100
     *
101
     *
102
     * @param source
103
     *            a {@link java.lang.Class} object.
104
     * @param message
105
     *            a {@link java.lang.String} object.
106
     */
107
    public static void warn(Class source, String message) {
108
        IStatus status = new Status(IStatus.WARNING, AbstractUtility.getPluginId(), message);
109
        MessagingUtils.getLog4JLogger(source).warn(message);
110
        log(status);
111
    }
112

    
113
    /**
114
     * Logs a status object from a given source as an error.
115
     *
116
     *
117
     * @param source
118
     *            a {@link java.lang.Class} object.
119
     * @param status
120
     *            a {@link org.eclipse.core.runtime.IStatus} object.
121
     */
122
    public static void error(Class source, IStatus status) {
123
        getLog4JLogger(source)
124
        .error(status.getMessage(), status.getException());
125
        log(status);
126
    }
127

    
128
    /**
129
     * Logs a string and exception from a given source as an error.
130
     *
131
     *
132
     * @param source
133
     *            a {@link java.lang.Class} object.
134
     * @param message
135
     *            a {@link java.lang.String} object.
136
     * @param t
137
     *            a {@link java.lang.Throwable} object.
138
     */
139
    public static void error(Class source, String message, Throwable t) {
140
        IStatus status = new Status(IStatus.ERROR, AbstractUtility.getPluginId(), message, t);
141
        error(source, status);
142
    }
143

    
144

    
145

    
146
    /**
147
     * Logs an exception from a given source as an error.
148
     *
149
     *
150
     * @param source
151
     *            a {@link java.lang.Class} object.
152
     * @param t
153
     *            a {@link java.lang.Throwable} object.
154
     */
155
    public static void error(Class source, Throwable t) {
156
        error(source.getClass(), t.getMessage(), t);
157
    }
158

    
159

    
160

    
161
    /**
162
     * Returns a list of strings, providing info on,
163
     *  - login
164
     *  - editor version
165
     *  - server (address + source name)
166
     *  - db schema version
167
     *
168
     * @return
169
     */
170
    public static List<String> getContextInfo() {
171
        List<String> contextInfo = new ArrayList<String>();
172
        String name = "";
173
        String schemaVersion = "";
174
        String server = "";
175
        String version = "";
176
        String login = "";
177
        try {
178
            version = Platform.getBundle("eu.etaxonomy.taxeditor.application").getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION);
179

    
180
            if(CdmStore.getActiveCdmSource() != null ) {
181
                login = CdmStore.getLoginManager().getAuthenticatedUser().getUsername();
182
                name = CdmStore.getActiveCdmSource().getName();
183
                schemaVersion = CdmStore.getActiveCdmSource().getDbSchemaVersion();
184
                server = CdmStore.getActiveCdmSource().getServer();
185
            }
186

    
187
        } catch (Exception e) {
188
            // Nothing to do
189
        }
190
        contextInfo.add("login : " + login);
191
        contextInfo.add("editor version : " + version);
192
        contextInfo.add("server : " + server + " / " + name);
193
        contextInfo.add("schema version : " + schemaVersion);
194

    
195
        return contextInfo;
196
    }
197

    
198
    public static String getStackTraceAndContextInfo(Throwable t, List<String> contextInfo)  {
199
        StringBuffer stackTraceAndContextInfo = new StringBuffer();
200

    
201
        for(String infoItem : contextInfo) {
202
            stackTraceAndContextInfo.append(infoItem + System.getProperty("line.separator"));
203
        }
204

    
205
        StringWriter sw = new StringWriter();
206
        t.printStackTrace(new PrintWriter(sw));
207

    
208
        stackTraceAndContextInfo.append(sw.toString());
209

    
210
        return stackTraceAndContextInfo.toString();
211
    }
212

    
213
    /**
214
     * Displays a {@link eu.etaxonomy.taxeditor.model.CdmErrorDialog}.
215
     *
216
     * @param title
217
     * @param source
218
     * @param t
219
     * @param contextInfo
220
     * @param message
221
     * @param status
222
     */
223
    private static void errorDialog(final String title,
224
            final Object source,
225
            final Throwable t,
226
            final List<String> contextInfo,
227
            final String message,
228
            final MultiStatus status) {
229

    
230
        Display.getDefault().asyncExec(new Runnable() {
231

    
232
            @Override
233
            public void run() {
234
                String stackTraceWithContext = getStackTraceAndContextInfo(t, contextInfo);
235
                CdmErrorDialog ced = new CdmErrorDialog(AbstractUtility.getShell(), title, message, status, stackTraceWithContext);
236
                ced.open();
237
                Class<? extends Object> clazz = source != null ? source.getClass() : this.getClass();
238

    
239

    
240
                IStatus singleStatus = new Status(IStatus.ERROR,
241
                        status.getPlugin(),
242
                        message,
243
                        new Exception(stackTraceWithContext));
244

    
245
                error(clazz, singleStatus);
246
            }
247
        });
248
    }
249

    
250
    /**
251
     * Displays a {@link eu.etaxonomy.taxeditor.model.CdmErrorDialog}.
252
     *
253
     * @param title
254
     * @param source
255
     * @param message
256
     * @param pluginId
257
     * @param t
258
     */
259
    public static void errorDialog(final String title,
260
            final Object source,
261
            final String message,
262
            final String pluginId,
263
            final Throwable t,
264
            boolean addContactMesg) {
265

    
266

    
267
        StringBuffer sbStackTrace = new StringBuffer();
268

    
269
        // We need to build a MultiStatus object since the simple
270
        // idea of writing out the stack trace as a single string
271
        // leads to a single line on windows
272
        List<Status> childStatuses = new ArrayList<Status>();
273

    
274
        // add context info
275
        List<String> contextInfo = getContextInfo();
276
        for(String infoItem : contextInfo) {
277
            childStatuses.add(new Status(IStatus.ERROR, pluginId, infoItem));
278
        }
279

    
280
        // add main execption
281
        for (StackTraceElement ste : t.getStackTrace()) {
282
            childStatuses.add(new Status(IStatus.ERROR, pluginId, "at " + ste.toString()));
283
        }
284

    
285
        // add cause
286
        if(t.getCause() != null) {
287
            childStatuses.add(new Status(IStatus.ERROR, pluginId, ""));
288
            childStatuses.add(new Status(IStatus.ERROR, pluginId, "Caused by : " + t.getCause().toString()));
289
            for (StackTraceElement ste : t.getCause().getStackTrace()) {
290
                // build & add status
291
                childStatuses.add(new Status(IStatus.ERROR, pluginId, "at " + ste.toString()));
292
            }
293
        }
294

    
295
        String finalMessage = message;
296

    
297
        if(finalMessage == null || finalMessage.isEmpty()) {
298
            finalMessage = "";
299
        }
300

    
301
        if(addContactMesg) {
302
            // add edit support contact info to message
303
            finalMessage += MessagingUtils.CONTACT_MESSAGE;
304
        }
305

    
306
        MultiStatus ms = new MultiStatus(pluginId,
307
                IStatus.ERROR,
308
                childStatuses.toArray(new Status[] {}),
309
                t.toString(),
310
                t);
311

    
312
        errorDialog(title, source, t, contextInfo, finalMessage, ms);
313
    }
314

    
315
    /**
316
     * Displays a {@link eu.etaxonomy.taxeditor.model.CdmErrorDialog}.
317
     *
318
     * @param title
319
     *            a {@link java.lang.String} object.
320
     * @param source
321
     *            a {@link java.lang.Object} object.
322
     * @param status
323
     *            a {@link org.eclipse.core.runtime.IStatus} object.
324
     */
325
    private static void errorDialog(final String title,
326
            final Object source,
327
            final String message,
328
            final IStatus status) {
329

    
330
        Display.getDefault().asyncExec(new Runnable() {
331

    
332
            @Override
333
            public void run() {
334
                CdmErrorDialog ced = new CdmErrorDialog(AbstractUtility.getShell(), title, message, status);
335
                ced.open();
336
                Class<? extends Object> clazz = source != null ? source.getClass() : this.getClass();
337
                error(clazz, status);
338
            }
339
        });
340
    }
341

    
342
    /**
343
     * Displays a dialog for an exception occurring in an operation.
344
     *
345
     * This will be either a {@link eu.etaxonomy.taxeditor.model.CdmErrorDialog} in case of a
346
     * security runtime exception or a warning {@link org.eclipse.jface.dialogs.MessageDialog} in
347
     * case of any other exception.
348
     *
349
     * @param title
350
     *            a {@link java.lang.String} object.
351
     * @param source
352
     *            a {@link java.lang.Object} object.
353
     * @param status
354
     *            a {@link org.eclipse.core.runtime.IStatus} object.
355
     */
356
    public static void operationDialog(final Object source,
357
            final Exception ex,
358
            final String pluginId,
359
            final String operationlabel,
360
            final String hint) {
361

    
362
        Display.getDefault().asyncExec(new Runnable() {
363

    
364
            @Override
365
            public void run() {
366
                MultiStatus info = null;
367
                String title = null;
368

    
369
                // FIXME cannot access TaxonomicEditorPlugin.PLUGIN_ID from here
370
                // String PID = TaxonomicEditorPlugin.PLUGIN_ID;
371
                String PID = "eu.etaxonomy.taxeditor.application";
372

    
373
                // checking security exceptions for every operation
374
                RuntimeException securityRuntimeException = SecurityExceptionUtils.findSecurityRuntimeException(ex);
375

    
376
                // in case of a security exception it is a warning, else it is an error
377
                if(securityRuntimeException != null){
378
                    title = "Your changes could not be saved!";
379
                    warningDialog(title, source, String.format("You are missing sufficient permissions for the operation \"%s\". %s", operationlabel, hint));
380
                } else {
381
                    title = "Error executing operation";
382
                    errorDialog(title, source, String.format("An error occured while executing %s. %s", operationlabel, hint), pluginId, ex, true);
383

    
384
                }
385

    
386

    
387
            }
388
        });
389
    }
390

    
391

    
392

    
393

    
394
    /**
395
     * Displays a question {@link org.eclipse.jface.dialogs.MessageDialog}.
396
     *
397
     * @param title
398
     *            a {@link java.lang.String} object.
399
     * @param message
400
     *            a {@link java.lang.String} object.
401
     * @return a boolean.
402
     */
403
    public static boolean confirmDialog(String title, String message) {
404
        return MessageDialog.openQuestion(AbstractUtility.getShell(), title, message);
405
    }
406

    
407
    /**
408
     * Displays a message {@link org.eclipse.jface.dialogs.MessageDialog}.
409
     *
410
     * @param title
411
     * @param source
412
     * @param message
413
     */
414
    public static void messageDialog(final String title, final Object source, final String message) {
415
        MessagingUtils.messageDialog(title, source, message, null, true);
416
    }
417

    
418

    
419

    
420
    /**
421
     * Displays an error {@link org.eclipse.jface.dialogs.MessageDialog}.
422
     *
423
     * @param title
424
     *            The dialogs title
425
     * @param source
426
     *            The object where the warning was generated (used by log4j)
427
     * @param message
428
     *            An informative String to be presented to the user
429
     * @param title
430
     *            The dialogs title
431
     * @param t
432
     *            a Throwable if one exists or null
433
     */
434
    public static void messageDialog(final String title,
435
            final Object source,
436
            final String message,
437
            final Throwable t) {
438
        MessagingUtils.messageDialog(title, source, message, t, true);
439
    }
440

    
441
    /**
442
     * Displays an error {@link org.eclipse.jface.dialogs.MessageDialog}.
443
     *
444
     * @param title
445
     *            The dialogs title
446
     * @param source
447
     *            The object where the warning was generated (used by log4j)
448
     * @param message
449
     *            An informative String to be presented to the user
450
     * @param title
451
     *            The dialogs title
452
     * @param t
453
     *            a Throwable if one exists or null
454
     */
455
    public static void messageDialog(final String title,
456
            final Object source,
457
            final String message,
458
            final Throwable t,
459
            boolean async) {
460
        if(async) {
461
            Display.getDefault().asyncExec(new Runnable() {
462

    
463
                @Override
464
                public void run() {
465
                    MessageDialog.openError(AbstractUtility.getShell(), title, message + getCauseRecursively(t));
466
                    Class<? extends Object> clazz = source != null ? source
467
                            .getClass() : this.getClass();
468
                            error(clazz, message, t);
469
                }
470

    
471

    
472
            });
473
        } else {
474
            MessageDialog.openError(AbstractUtility.getShell(), title, message + getCauseRecursively(t));
475
            Class<? extends Object> clazz = source != null ? source.getClass() : TaxeditorStorePlugin.class;
476
            error(clazz, message, t);
477
        }
478
    }
479

    
480
    public static String getCauseRecursively(Throwable t) {
481
        if(t == null){
482
            return "";
483
        }
484

    
485
        if(t.getCause() != null){
486
            return getCauseRecursively(t.getCause());
487
        }else{
488
            return String.format("\n\nException: %s\nMessage: %s", t.getClass().getSimpleName(), t.getMessage());
489
        }
490

    
491
    }
492
    /**
493
     * Displays a warning {@link org.eclipse.jface.dialogs.MessageDialog}.
494
     *
495
     * @param title
496
     * @param termBase
497
     * @param status
498
     */
499
    public static void warningDialog(String title, Object source,
500
            IStatus status) {
501
        MessagingUtils.warningDialog(title, source, status.getMessage());
502
    }
503

    
504
    /**
505
     * Displays a warning {@link org.eclipse.jface.dialogs.MessageDialog}.
506
     *
507
     * @param title
508
     *            The dialogs title
509
     * @param source
510
     *            The object where the warning was generated (used by log4j)
511
     * @param message
512
     *            An informative String to be presented to the user
513
     */
514
    public static void warningDialog(final String title, final Object source, final String message) {
515
        Display.getDefault().asyncExec(new Runnable() {
516

    
517
            @Override
518
            public void run() {
519
                MessageDialog.openWarning(AbstractUtility.getShell(), title, message);
520
                Class<? extends Object> clazz = source != null ? source
521
                        .getClass() : AbstractUtility.class;
522
                        warn(clazz, message);
523
            }
524
        });
525
    }
526

    
527
    /**
528
     * Displays an information {@link org.eclipse.jface.dialogs.MessageDialog}.
529
     *
530
     * @param title
531
     * @param status
532
     */
533
    public static void informationDialog(final String title, final IStatus status) {
534
        MessagingUtils.informationDialog(title, status.getMessage());
535
    }
536

    
537
    /**
538
     * Displays an information {@link org.eclipse.jface.dialogs.MessageDialog}.
539
     *
540
     * @param title
541
     *            a {@link java.lang.String} object.
542
     * @param message
543
     *            a {@link java.lang.String} object.
544
     */
545
    public static void informationDialog(final String title,
546
            final String message) {
547
        Display.getDefault().asyncExec(new Runnable() {
548

    
549
            @Override
550
            public void run() {
551
                MessageDialog.openInformation(AbstractUtility.getShell(), title, message);
552
            }
553
        });
554
    }
555

    
556
    /**
557
     * Open a message box that informs the user about unimplemented
558
     * functionality. This method is for developer convenience.
559
     *
560
     * @param source
561
     *            a {@link java.lang.Object} object.
562
     */
563
    public static void notImplementedMessage(Object source) {
564
        warningDialog("Not yet implemented", source,
565
                "This functionality is not yet implemented.");
566
    }
567

    
568
}
(26-26/35)