OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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