OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 25 | Rev 73 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
17 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 /*
15
 * ExceptionHandler created on 7 mai 2004
16
 */
17
package org.openconcerto.utils;
18
 
19
import java.awt.Component;
20
import java.awt.Desktop;
21
import java.awt.Desktop.Action;
22
import java.awt.Dialog;
23
import java.awt.Dimension;
24
import java.awt.Font;
25
import java.awt.Frame;
26
import java.awt.GraphicsEnvironment;
27
import java.awt.GridBagConstraints;
28
import java.awt.GridBagLayout;
29
import java.awt.Insets;
30
import java.awt.Toolkit;
31
import java.awt.Window;
32
import java.awt.datatransfer.Clipboard;
33
import java.awt.datatransfer.StringSelection;
34
import java.awt.event.ActionEvent;
35
import java.awt.event.ActionListener;
36
import java.awt.event.WindowAdapter;
37
import java.awt.event.WindowEvent;
38
import java.net.URI;
65 ilm 39
import java.util.concurrent.Future;
40
import java.util.concurrent.FutureTask;
41
import java.util.logging.Level;
17 ilm 42
import java.util.logging.Logger;
43
 
44
import javax.swing.AbstractAction;
45
import javax.swing.ImageIcon;
46
import javax.swing.JButton;
47
import javax.swing.JDialog;
48
import javax.swing.JLabel;
49
import javax.swing.JPanel;
50
import javax.swing.JScrollPane;
51
import javax.swing.JSeparator;
52
import javax.swing.JTextArea;
53
import javax.swing.ScrollPaneConstants;
54
import javax.swing.SwingUtilities;
55
import javax.swing.UIManager;
56
 
57
/**
58
 * Allow to display an exception both on the GUI and on the console.
59
 *
60
 * @author ILM Informatique 7 mai 2004
61
 */
62
public class ExceptionHandler extends RuntimeException {
63
 
64
    private static final String ILM_CONTACT = "http://www.ilm-informatique.fr/contact";
65
    private static String ForumURL = null;
66
 
67
    public static void setForumURL(String url) {
68
        ForumURL = url;
69
    }
70
 
71
    static private void copyToClipboard(final String s) {
72
        final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
73
        final StringSelection data = new StringSelection(s);
74
        clipboard.setContents(data, data);
75
    }
76
 
25 ilm 77
    /**
78
     * Display the passed message. Note: this method doesn't block.
79
     *
80
     * @param comp the modal parent of the error window.
81
     * @param msg the message to display.
82
     * @param originalExn the cause, can be <code>null</code>.
83
     * @return an exception.
84
     */
65 ilm 85
    static public ExceptionHandler handle(Component comp, String msg, Throwable originalExn) {
17 ilm 86
        return new ExceptionHandler(comp, msg, originalExn, false);
87
    }
88
 
89
    static public RuntimeException handle(String msg, Throwable originalExn) {
90
        return handle(null, msg, originalExn);
91
    }
92
 
93
    static public RuntimeException handle(String msg) {
94
        return handle(msg, null);
95
    }
96
 
25 ilm 97
    /**
98
     * Display the passed message and quit. Note: this method blocks until the user closes the
99
     * window (then exits).
100
     *
101
     * @param msg the message to display.
102
     * @param originalExn the cause, can be <code>null</code>.
103
     * @return an exception.
104
     */
17 ilm 105
    static public RuntimeException die(String msg, Throwable originalExn) {
106
        return new ExceptionHandler(null, msg, originalExn);
107
    }
108
 
109
    static public RuntimeException die(String msg) {
110
        return die(msg, null);
111
    }
112
 
113
    private static Logger getLogger() {
114
        return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
115
    }
116
 
117
    // the comp on which to display the popup, may be null
118
    private final Component comp;
65 ilm 119
    private final Future<?> future;
17 ilm 120
    private static boolean forceUI;
121
 
122
    public static void setForceUI(boolean forceUI) {
123
        ExceptionHandler.forceUI = forceUI;
124
    }
125
 
65 ilm 126
    private Future<?> display(final boolean error) {
17 ilm 127
        final String msg = this.getMessage();
128
        if (error) {
65 ilm 129
            getLogger().log(Level.SEVERE, null, this);
17 ilm 130
        } else {
131
            if (this.getCause() != null) {
65 ilm 132
                getLogger().log(Level.INFO, null, this);
17 ilm 133
            }
134
        }
135
        if (!GraphicsEnvironment.isHeadless() || forceUI) {
136
            if (SwingUtilities.isEventDispatchThread()) {
137
                showMsg(msg, error);
25 ilm 138
            } else {
65 ilm 139
                final FutureTask<?> run = new FutureTask<Object>(new Runnable() {
17 ilm 140
                    public void run() {
141
                        showMsg(msg, error);
142
                    }
65 ilm 143
                }, null);
25 ilm 144
                if (error) {
145
                    try {
146
                        SwingUtilities.invokeAndWait(run);
147
                    } catch (Exception e) {
148
                        e.printStackTrace();
149
                        System.exit(1);
150
                    }
151
                } else {
152
                    SwingUtilities.invokeLater(run);
153
                }
65 ilm 154
                return run;
25 ilm 155
            }
17 ilm 156
        }
65 ilm 157
        return null;
17 ilm 158
    }
159
 
65 ilm 160
    public final Future<?> getDialogFuture() {
161
        return this.future;
162
    }
163
 
17 ilm 164
    protected final void showMsg(final String msg, final boolean quit) {
165
        final JPanel p = new JPanel();
166
        p.setLayout(new GridBagLayout());
167
        final GridBagConstraints c = new GridBagConstraints();
168
        c.insets = new Insets(10, 10, 10, 10);
169
        c.gridx = 0;
170
        c.gridy = 0;
171
        c.fill = GridBagConstraints.BOTH;
172
        final JImage im = new JImage(new ImageIcon(this.getClass().getResource("error.png")));
173
        final JLabel l = new JLabel("Une erreur est survenue");
174
        l.setFont(l.getFont().deriveFont(Font.BOLD));
175
        final JLabel lError = new JLabel(msg);
176
 
177
        final JTextArea textArea = new JTextArea();
178
        textArea.setFont(textArea.getFont().deriveFont(11f));
179
 
180
        c.gridheight = 3;
181
        p.add(im, c);
182
        c.insets = new Insets(2, 4, 2, 4);
183
        c.gridheight = 1;
184
        c.gridx++;
185
        c.weightx = 1;
186
        c.gridwidth = 2;
187
        p.add(l, c);
188
        c.gridy++;
189
        p.add(lError, c);
190
 
191
        c.gridy++;
192
        p.add(new JLabel("Il s'agit probablement d'une mauvaise configuration ou installation du logiciel."), c);
193
 
194
        c.gridx = 0;
195
        c.gridwidth = 3;
196
        c.gridy++;
197
        c.weighty = 0;
198
        c.gridwidth = 1;
199
        c.gridx = 1;
200
        c.gridy++;
201
 
202
        c.fill = GridBagConstraints.NONE;
203
        c.anchor = GridBagConstraints.EAST;
204
        final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
205
        final boolean browseSupported = desktop != null && desktop.isSupported(Action.BROWSE);
206
        if (ForumURL != null) {
207
            final javax.swing.Action communityAction;
208
            if (browseSupported) {
209
                communityAction = new AbstractAction("Consulter le forum") {
210
                    @Override
211
                    public void actionPerformed(ActionEvent e) {
212
                        try {
213
                            desktop.browse(new URI(ForumURL));
214
                        } catch (Exception e1) {
215
                            e1.printStackTrace();
216
                        }
217
                    }
218
                };
219
            } else {
220
                communityAction = new AbstractAction("Copier l'adresse du forum") {
221
                    @Override
222
                    public void actionPerformed(ActionEvent e) {
223
                        copyToClipboard(ForumURL);
224
                    }
225
                };
226
            }
227
            p.add(new JButton(communityAction), c);
228
        }
229
        c.weightx = 0;
230
        c.gridx++;
231
 
232
        final javax.swing.Action supportAction;
233
        if (browseSupported)
234
            supportAction = new AbstractAction("Contacter l'assistance") {
235
                @Override
236
                public void actionPerformed(ActionEvent e) {
237
                    try {
238
                        desktop.browse(URI.create(ILM_CONTACT));
239
                    } catch (Exception e1) {
240
                        e1.printStackTrace();
241
                    }
242
 
243
                }
244
            };
245
        else
246
            supportAction = new AbstractAction("Copier l'adresse de l'assistance") {
247
                @Override
248
                public void actionPerformed(ActionEvent e) {
249
                    copyToClipboard(ILM_CONTACT);
250
                }
251
            };
252
 
253
        p.add(new JButton(supportAction), c);
254
        c.gridy++;
255
        c.gridx = 0;
256
        c.gridwidth = 3;
257
        c.fill = GridBagConstraints.BOTH;
258
        c.insets = new Insets(0, 0, 0, 0);
259
        p.add(new JSeparator(), c);
260
 
261
        c.gridx = 0;
262
        c.gridwidth = 3;
263
        c.gridy++;
264
        c.insets = new Insets(2, 4, 2, 4);
265
        p.add(new JLabel("Détails de l'erreur:"), c);
266
        c.insets = new Insets(0, 0, 0, 0);
267
        c.gridy++;
268
        String message = this.getCause() == null ? null : this.getCause().getMessage();
269
        if (message == null) {
270
            message = msg;
271
        } else {
272
            message = msg + "\n\n" + message;
273
        }
274
        message += "\n";
275
        message += getTrace();
276
        textArea.setText(message);
277
        textArea.setEditable(false);
278
        // Scroll
279
        JScrollPane scroll = new JScrollPane(textArea);
280
        scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
281
        scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
282
        scroll.getViewport().setMinimumSize(new Dimension(200, 300));
283
        c.weighty = 1;
284
        c.gridwidth = 3;
285
        c.gridx = 0;
286
        c.gridy++;
287
        p.add(scroll, c);
288
 
289
        c.gridy++;
290
        c.fill = GridBagConstraints.NONE;
291
        c.weighty = 0;
292
        c.insets = new Insets(2, 4, 2, 4);
293
        final JButton buttonClose = new JButton("Fermer");
294
        p.add(buttonClose, c);
295
 
296
        final Window window = this.comp == null ? null : SwingUtilities.getWindowAncestor(this.comp);
297
        final JDialog f;
298
        if (window instanceof Frame) {
299
            f = new JDialog((Frame) window, "Erreur", true);
300
        } else {
301
            f = new JDialog((Dialog) window, "Erreur", true);
302
        }
303
        f.setContentPane(p);
304
        f.pack();
305
        f.setSize(580, 680);
306
        f.setMinimumSize(new Dimension(380, 380));
307
        f.setLocationRelativeTo(this.comp);
308
        final ActionListener al = new ActionListener() {
309
 
310
            @Override
311
            public void actionPerformed(ActionEvent e) {
312
                if (quit) {
313
                    System.exit(1);
314
                } else {
315
                    f.dispose();
316
                }
317
 
318
            }
319
        };
320
        buttonClose.addActionListener(al);
321
        // cannot set EXIT_ON_CLOSE on JDialog
322
        f.addWindowListener(new WindowAdapter() {
323
            @Override
324
            public void windowClosing(WindowEvent e) {
325
                al.actionPerformed(null);
326
            }
327
        });
328
        f.setVisible(true);
329
    }
330
 
331
    private String getTrace() {
332
        return ExceptionUtils.getStackTrace(this);
333
    }
334
 
335
    /**
336
     * Affiche l'erreur et quitte.
337
     *
338
     * @param comp the component upon which to display the popup.
339
     * @param msg le message d'erreur à afficher.
340
     * @param cause la cause de l'exception (peut être <code>null</code>).
341
     */
342
    private ExceptionHandler(Component comp, String msg, Throwable cause) {
343
        this(comp, msg, cause, true);
344
    }
345
 
346
    /**
347
     * Affiche l'erreur et quitte suivant l'option passée.
348
     *
349
     * @param comp the component upon which to display the popup.
350
     * @param msg the error message to display.
351
     * @param cause the cause of the exception (maybe <code>null</code>).
352
     * @param quit if the VM must exit.
353
     */
354
    private ExceptionHandler(Component comp, String msg, Throwable cause, boolean quit) {
355
        super(msg, cause);
356
        this.comp = comp;
65 ilm 357
        this.future = this.display(quit);
17 ilm 358
    }
359
 
360
    public static void main(String[] args) throws Exception {
361
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
362
        ExceptionHandler.handle("Fichier de configuration corrompu", new IllegalStateException("Id manquant"));
363
    }
364
}