This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 35067
Collapse All | Expand All

(-)apisupport/jackpotrules/nbproject/project.properties (+24 lines)
Line 0 Link Here
1
#                 Sun Public License Notice
2
# 
3
# The contents of this file are subject to the Sun Public License
4
# Version 1.0 (the "License"). You may not use this file except in
5
# compliance with the License. A copy of the License is available at
6
# http://www.sun.com/
7
# 
8
# The Original Code is NetBeans. The Initial Developer of the Original
9
# Code is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
10
# Microsystems, Inc. All Rights Reserved.
11
12
13
test.unit.cp.extra=\
14
    ${openide/fs.dir}/core/org-openide-filesystems.jar:\
15
    ${openide/masterfs.dir}/modules/org-netbeans-modules-masterfs.jar:\
16
    ${openide/util.dir}/lib/org-openide-util.jar:\
17
    ${openide/modules.dir}/lib/org-openide-modules.jar:\
18
    ${jackpot/engine.dir}/modules/org-netbeans-jackpot.jar:\
19
    ${jackpot.dir}/modules/org-netbeans-modules-jackpot.jar:\
20
    ${jackpot.dir}/modules/ext/javac-api.jar:\
21
    ${jackpot.dir}/modules/ext/javac-impl.jar:\
22
23
24
(-)apisupport/jackpotrules/nbproject/project.xml (+6 lines)
Lines 12-17 Link Here
12
                        <specification-version>1.4.5</specification-version>
12
                        <specification-version>1.4.5</specification-version>
13
                    </run-dependency>
13
                    </run-dependency>
14
                </dependency>
14
                </dependency>
15
                <dependency>
16
                    <code-name-base>org.netbeans.modules.jackpot.rules</code-name-base>
17
                    <run-dependency>
18
                        <specification-version>1.2.3</specification-version>
19
                    </run-dependency>
20
                </dependency>
15
            </module-dependencies>
21
            </module-dependencies>
16
            <public-packages/>
22
            <public-packages/>
17
        </data>
23
        </data>
(-)apisupport/jackpotrules/src/org/netbeans/modules/apisupport/jackpotrules/annotate-to-initcause.rules (+90 lines)
Lines 1-3 Link Here
1
//
2
// attachMessage:
3
//
4
5
$ErrMgr.annotate($nue, org.openide.ErrorManager.UNKNOWN, $msg, null, null, null) => Exceptions.attachMessage($nue, $msg)
6
:: $nue instanceof java.lang.Throwable, $msg instanceof java.lang.String, $ErrMgr instanceof org.openide.ErrorManager;
7
8
$ErrMgr.annotate($nue, org.openide.ErrorManager.INFORMATIONAL, $msg, null, null, null) => Exceptions.attachMessage($nue, $msg)
9
:: $nue instanceof java.lang.Throwable, $msg instanceof java.lang.String, $ErrMgr instanceof org.openide.ErrorManager;
10
11
$ErrMgr.annotate($nue, org.openide.ErrorManager.EXCEPTION, $msg, null, null, null) => Exceptions.attachMessage($nue, $msg)
12
:: $nue instanceof java.lang.Throwable, $msg instanceof java.lang.String, $ErrMgr instanceof org.openide.ErrorManager;
13
14
15
//
16
// attachLocalizedMessage:
17
//
18
19
$ErrMgr.annotate($nue, $msg) => Exceptions.attachLocalizedMessage($nue, $msg)
20
:: $nue instanceof java.lang.Throwable, $msg instanceof java.lang.String, $ErrMgr instanceof org.openide.ErrorManager;
21
22
$ErrMgr.annotate($nue, org.openide.ErrorManager.EXCEPTION, null, $msg, null, null) => Exceptions.attachLocalizedMessage($nue, $msg)
23
:: $nue instanceof java.lang.Throwable, $msg instanceof java.lang.String, $ErrMgr instanceof org.openide.ErrorManager;
24
25
$ErrMgr.annotate($nue, org.openide.ErrorManager.UNKNOWN, null, $msg, null, null) => Exceptions.attachLocalizedMessage($nue, $msg)
26
:: $nue instanceof java.lang.Throwable, $msg instanceof java.lang.String, $ErrMgr instanceof org.openide.ErrorManager;
27
28
//
29
// friend contract for annotate(USER)
30
//
31
32
$ErrMgr.annotate($nue, org.openide.ErrorManager.USER, $msg, $locmsg, $cause, $date)
33
=> UIException.annotateUser($nue, $msg, $locmsg, $cause, $date)
34
::  $nue instanceof java.lang.Throwable,
35
    $cause instanceof java.lang.Throwable,
36
    $msg instanceof java.lang.String,
37
    $locmsg instanceof java.lang.String,
38
    $date instanceof java.util.Date,
39
    $ErrMgr instanceof org.openide.ErrorManager;
40
41
$ErrMgr.annotate($nue, org.openide.ErrorManager.USER, null, $locmsg, null, null)
42
=> UIException.annotateUser($nue, null, $locmsg, null, null)
43
::  $nue instanceof java.lang.Throwable,
44
    $locmsg instanceof java.lang.String,
45
    $ErrMgr instanceof org.openide.ErrorManager;
46
47
//
48
// ErrorManager.notify(Throwable t):
49
//
50
51
$ErrMgr.notify($nue) => Exceptions.printStackTrace($nue)
52
:: $nue instanceof java.lang.Throwable, $ErrMgr instanceof org.openide.ErrorManager;
53
54
55
$ErrMgr.notify(org.openide.ErrorManager.USER, $nue) => DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Exception($nue))
56
:: $nue instanceof java.lang.Throwable, $ErrMgr instanceof org.openide.ErrorManager;
57
58
$ErrMgr.notify(org.openide.ErrorManager.INFORMATIONAL, $nue) => Logger.global.log(Level.WARNING, null, $nue);
59
:: $nue instanceof java.lang.Throwable, $ErrMgr instanceof org.openide.ErrorManager;
60
61
$ErrMgr.notify(org.openide.ErrorManager.WARNING, $nue) => Logger.global.log(Level.WARNING, null, $nue);
62
:: $nue instanceof java.lang.Throwable, $ErrMgr instanceof org.openide.ErrorManager;
63
64
//
65
// remove unused variables
66
//
67
68
//$EM $err = $EM.getDefault(); => ; :: !referenced($err), $EM instanceof org.openide.ErrorManager;
69
70
//
71
// initCause rules:
72
//
73
1
{ $before$;
74
{ $before$;
2
$E $nue = new $E($orig.getMessage());
75
$E $nue = new $E($orig.getMessage());
3
$ErrMgr.annotate($nue, $orig);
76
$ErrMgr.annotate($nue, $orig);
Lines 10-15 Link Here
10
::
83
::
11
$E instanceof java.lang.Throwable, $orig instanceof java.lang.Throwable,
84
$E instanceof java.lang.Throwable, $orig instanceof java.lang.Throwable,
12
    $ErrMgr instanceof org.openide.ErrorManager;
85
    $ErrMgr instanceof org.openide.ErrorManager;
86
87
{ $before$;
88
$E $nue = new $E($orig.getMessage());
89
$ErrMgr.copyAnnotation($nue, $orig);
90
throw $nue;
91
}
92
=>
93
{ $before$;
94
throw ($E) new $E($orig.toString()).initCause($orig);
95
}
96
::
97
$E instanceof java.lang.Throwable, $orig instanceof java.lang.Throwable,
98
    $ErrMgr instanceof org.openide.ErrorManager;
99
100
$ErrMgr.copyAnnotation($nue, $orig) => $nue.initCause($orig)
101
:: $ErrMgr instanceof org.openide.ErrorManager, $nue instanceof java.lang.Throwable, $orig instanceof java.lang.Throwable;
102
13
103
14
{ $before$;
104
{ $before$;
15
$E $nue = new $E($orig.getLocalizedMessage());
105
$E $nue = new $E($orig.getLocalizedMessage());
(-)apisupport/jackpotrules/test/unit/src/org/netbeans/modules/apisupport/jackpotrules/ErrorManagerTest.java (+323 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.modules.apisupport.jackpotrules;
15
16
import java.io.File;
17
import java.io.IOException;
18
import java.net.URL;
19
import java.util.logging.Level;
20
21
import org.netbeans.junit.NbTestCase;
22
23
/**
24
 *
25
 * @author Jaroslav Tulach
26
 */
27
public final class ErrorManagerTest extends NbTestCase {
28
29
    private URL script;
30
31
32
    public ErrorManagerTest(String s) {
33
        super(s);
34
    }
35
36
    protected Level logLevel() {
37
        return Level.INFO;
38
    }
39
40
    protected void setUp() throws Exception {
41
        clearWorkDir();
42
        script = ErrorManagerTest.class.getResource("/org/netbeans/modules/apisupport/jackpotrules/annotate-to-initcause.rules");
43
        assertNotNull(script);
44
    }
45
46
    public void testRenameNotifyToPst() throws Exception {
47
        File f = JackpotUtils.extractString(new File(getWorkDir(), "A.java"),
48
            "package test;\n" +
49
            "class A {\n" +
50
            " public static void main(String[] args) {\n" +
51
            "   Exception e = new Exception();\n" +
52
            "   org.openide.ErrorManager.getDefault().notify(e);\n" +
53
            " }\n" +
54
            "}\n"
55
        );
56
57
        JackpotUtils.apply(getWorkDir(), script);
58
59
        String txt = JackpotUtils.readFile(f, false);
60
61
        if (txt.indexOf("ErrorManager") >= 0) {
62
            fail("No ErrorManager shall be there:\n" + txt);
63
        }
64
    }
65
66
    public void testErrMgrAnnoMsg() throws Exception {
67
        File f = JackpotUtils.extractString(new File(getWorkDir(), "A.java"),
68
            "package test;\n" +
69
            "import javax.swing.JButton;" +
70
            "class A {\n" +
71
            " public static void main(String[] args) {\n" +
72
            "       NullPointerException npe = new NullPointerException();\n" +
73
            "       org.openide.ErrorManager.getDefault().annotate(" +
74
            "       npe, \"localizedText\");" +
75
            " }\n" +
76
            "}\n"
77
        );
78
79
        JackpotUtils.apply(getWorkDir(), script);
80
81
        String txt = JackpotUtils.readFile(f, false);
82
83
        if (txt.indexOf("ErrorManager") >= 0) {
84
            fail("No ErrorManager shall be there:\n" + txt);
85
        }
86
87
        if (txt.indexOf("attachLocalizedMessage") < 0) {
88
            fail("There should be a localized message usage:\n" + txt);
89
        }
90
    }
91
    public void testErrMgrUnknown() throws Exception {
92
        File f = JackpotUtils.extractString(new File(getWorkDir(), "A.java"),
93
            "package test;\n" +
94
            "import javax.swing.JButton;" +
95
            "class A {\n" +
96
            " public static void main(String[] args) {\n" +
97
            "       NullPointerException npe = new NullPointerException();\n" +
98
            "       org.openide.ErrorManager.getDefault().annotate(" +
99
            "           npe, org.openide.ErrorManager.UNKNOWN," +
100
            "           \"msg\", null, null, null);" +
101
            " }\n" +
102
            "}\n"
103
        );
104
105
        JackpotUtils.apply(getWorkDir(), script);
106
107
        String txt = JackpotUtils.readFile(f, false);
108
109
        if (txt.indexOf("ErrorManager") >= 0) {
110
            fail("No ErrorManager shall be there:\n" + txt);
111
        }
112
    }
113
114
    public void testErrMgrException() throws Exception {
115
        File f = JackpotUtils.extractString(new File(getWorkDir(), "A.java"),
116
            "package test;\n" +
117
            "import javax.swing.JButton;" +
118
            "class A {\n" +
119
            " public static void main(String[] args) {\n" +
120
            "       JButton r = new JButton();\n" +
121
            "       String icon = null;\n" +
122
            "       NullPointerException npe = new NullPointerException();\n" +
123
            "       org.openide.ErrorManager.getDefault().annotate(" +
124
            "       npe, org.openide.ErrorManager.EXCEPTION," +
125
            "       \"Probably an ImageIcon with a null source image: \" + icon + \" - \" + //NOI18N\n" +
126
            "       r.getText(), null, null, null\n" +
127
            "); //NOI18N\n" +
128
            " }\n" +
129
            "}\n"
130
        );
131
132
        JackpotUtils.apply(getWorkDir(), script);
133
134
        String txt = JackpotUtils.readFile(f, false);
135
136
        if (txt.indexOf("ErrorManager") >= 0) {
137
            fail("No ErrorManager shall be there:\n" + txt);
138
        }
139
    }
140
141
    public void testConvertToLogging() throws Exception {
142
        File f = JackpotUtils.extractString(new File(getWorkDir(), "A.java"),
143
            "package test;\n" +
144
            "class A {\n" +
145
            " public static void main(String[] args) {\n" +
146
            "       NullPointerException e = new NullPointerException();\n" +
147
            "       org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, e);" +
148
            " }\n" +
149
            "}\n"
150
        );
151
152
        JackpotUtils.apply(getWorkDir(), script);
153
154
        String txt = JackpotUtils.readFile(f, false);
155
156
        if (txt.indexOf("ErrorManager") >= 0) {
157
            fail("No ErrorManager shall be there:\n" + txt);
158
        }
159
        if (!txt.replace('\n', ' ').matches(".*Logger.global.log *\\(Level.WARNING, *null, *e *\\).*")) {
160
            fail("Logger.global shall be there:\n" + txt);
161
        }
162
    }
163
164
    public void testGetRidOfCopyAnnotation() throws Exception {
165
        File f = JackpotUtils.extractString(new File(getWorkDir(), "A.java"),
166
            "package test;\n" +
167
            "class A {\n" +
168
            " public static void main(String[] args) {\n" +
169
            "       NullPointerException npe = new NullPointerException();\n" +
170
            "       java.io.IOException io = null;\n" +
171
            "       org.openide.ErrorManager.getDefault().copyAnnotation(npe, io);" +
172
            " }\n" +
173
            "}\n"
174
        );
175
176
        JackpotUtils.apply(getWorkDir(), script);
177
178
        String txt = JackpotUtils.readFile(f, false);
179
180
        if (txt.indexOf("ErrorManager") >= 0) {
181
            fail("No ErrorManager shall be there:\n" + txt);
182
        }
183
184
        if (!txt.replace("\n", " ").matches(".*npe.initCause *\\( *io *\\).*")) {
185
            fail("initCause shall be used:\n" + txt);
186
        }
187
    }
188
189
    public void testNonLocalizedAnnotation() throws Exception {
190
        File f = JackpotUtils.extractString(new File(getWorkDir(), "A.java"),
191
            "package test;\n" +
192
            "class A {\n" +
193
            " public static void main(String[] args) {\n" +
194
            "       NullPointerException npe = new NullPointerException();\n" +
195
            "       String msg = \"nonlocmsg\";\n" +
196
            "       org.openide.ErrorManager.getDefault().annotate(npe, org.openide.ErrorManager.UNKNOWN, null, msg, null, null);" +
197
            " }\n" +
198
            "}\n"
199
        );
200
201
        JackpotUtils.apply(getWorkDir(), script);
202
203
        String txt = JackpotUtils.readFile(f, false);
204
205
        if (txt.indexOf("ErrorManager") >= 0) {
206
            fail("No ErrorManager shall be there:\n" + txt);
207
        }
208
209
        if (!txt.replace("\n", " ").matches(".*Exceptions.attachLocalizedMessage.*")) {
210
            fail("initCause shall be used:\n" + txt);
211
        }
212
    }
213
214
215
    public void testFriendContractWithOwnLevel() throws Exception {
216
        File f = JackpotUtils.extractString(new File(getWorkDir(), "A.java"),
217
            "package test;\n" +
218
            "class A {\n" +
219
            " public static void main(String[] args) {\n" +
220
            "       NullPointerException npe = new NullPointerException();\n" +
221
            "       String msg = \"nonlocmsg\";\n" +
222
            "       org.openide.ErrorManager.getDefault().annotate(npe, " +
223
            "           org.openide.ErrorManager.USER, msg == null ? \"\" : npe.getMessage()," +
224
            "           msg, npe, new java.util.Date()); //NOI18N\n" +
225
            " }\n" +
226
            "}\n"
227
        );
228
229
        JackpotUtils.apply(getWorkDir(), script);
230
231
        String txt = JackpotUtils.readFile(f, false);
232
233
        if (txt.indexOf("ErrorManager") >= 0) {
234
            fail("No ErrorManager shall be there:\n" + txt);
235
        }
236
237
        if (!txt.replace("\n", " ").matches(".*UIException.annotateUser *\\( *npe.*")) {
238
            fail("UIException shall be used:\n" + txt);
239
        }
240
    }
241
242
    public void testWarningGoesToLogging() throws Exception {
243
        File f = JackpotUtils.extractString(new File(getWorkDir(), "A.java"),
244
            "package test;\n" +
245
            "class A {\n" +
246
            " public static void main(String[] args) {\n" +
247
            "       NullPointerException npe = new NullPointerException();\n" +
248
            "       org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.WARNING, npe);" +
249
            " }\n" +
250
            "}\n"
251
        );
252
253
        JackpotUtils.apply(getWorkDir(), script);
254
255
        String txt = JackpotUtils.readFile(f, false);
256
257
        if (txt.indexOf("ErrorManager") >= 0) {
258
            fail("No ErrorManager shall be there:\n" + txt);
259
        }
260
261
        if (!txt.replace('\n', ' ').matches(".*Logger.global.log *\\(Level.WARNING, *null, *npe *\\).*")) {
262
            fail("Logger.global shall be there:\n" + txt);
263
        }
264
    }
265
266
    public void testAnnotateWithInfo() throws Exception {
267
        File f = JackpotUtils.extractString(new File(getWorkDir(), "A.java"),
268
            "package test;\n" +
269
            "class A {\n" +
270
            " public static void main(String[] args) {\n" +
271
            "       NullPointerException cnfe = new NullPointerException();\n" +
272
            "       String msg = \"ahoj\";\n" +
273
            "       org.openide.ErrorManager.getDefault().annotate(cnfe, org.openide.ErrorManager.INFORMATIONAL, msg, null, null, null);" +
274
            " }\n" +
275
            "}\n"
276
        );
277
278
        JackpotUtils.apply(getWorkDir(), script);
279
280
        String txt = JackpotUtils.readFile(f, false);
281
282
        if (txt.indexOf("ErrorManager") >= 0) {
283
            fail("No ErrorManager shall be there:\n" + txt);
284
        }
285
286
        if (!txt.replace('\n', ' ').matches(".*Exceptions.attachMessage *\\(*cnfe, *msg\\).*")) {
287
            fail("Exceptions.attachMessage shall be there:\n" + txt);
288
        }
289
290
    }
291
292
    public void testRenamesEditor() throws Exception {
293
        File f = JackpotUtils.extractString(new File(getWorkDir(), "A.java"),
294
            "package test;\n" +
295
            "class A {\n" +
296
            " public static void main(String[] args) {\n" +
297
            "       try {" +
298
            "          System.exit(0);\n" +
299
            "        } catch( IllegalArgumentException iaE ) {" + 
300
            "           org.openide.ErrorManager.getDefault().annotate(iaE, org.openide.ErrorManager.USER, null, iaE.getLocalizedMessage(), null, null);\n" +
301
            "           throw iaE;\n" + 
302
            "        }" +
303
            " }\n" +
304
            "}\n"
305
        );
306
307
        JackpotUtils.apply(getWorkDir(), script);
308
309
        String txt = JackpotUtils.readFile(f, false);
310
311
        if (txt.indexOf("ErrorManager") >= 0) {
312
            fail("No ErrorManager shall be there:\n" + txt);
313
        }
314
315
        if (!txt.replace('\n', ' ').matches(".*UIException.*")) {
316
            fail("UIException shall be there:\n" + txt);
317
        }
318
        if (txt.replace('\n', ' ').indexOf("$") >= 0) {
319
            fail("NO $ shall be there:\n" + txt);
320
        }
321
    }
322
    
323
}
(-)apisupport/jackpotrules/test/unit/src/org/netbeans/modules/apisupport/jackpotrules/JackpotUtils.java (+123 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.modules.apisupport.jackpotrules;
15
16
import java.io.ByteArrayInputStream;
17
import java.io.File;
18
import java.io.FileInputStream;
19
import java.io.FileOutputStream;
20
import java.io.InputStream;
21
import java.io.OutputStream;
22
import java.io.OutputStreamWriter;
23
import java.io.Writer;
24
import java.net.URL;
25
import java.util.zip.GZIPInputStream;
26
27
import junit.framework.Assert;
28
29
import org.netbeans.jackpot.engine.*;
30
import org.netbeans.jackpot.transform.Transformer;
31
32
import org.openide.filesystems.FileObject;
33
import org.openide.filesystems.FileUtil;
34
import org.openide.filesystems.Repository;
35
36
/**
37
 *
38
 * @author Jaroslav Tulach
39
 */
40
public final class JackpotUtils {
41
    
42
    /** Creates a new instance of JackpotUtils */
43
    private JackpotUtils() {
44
    }
45
46
    public static void apply(File dir, URL rules) throws Exception {
47
        DefaultApplicationContext context = new DefaultApplicationContext();
48
        JackpotEngine eng = EngineFactory.createEngine(context);
49
50
        File rulesFile = extractResource(rules);
51
52
        int errors = eng.initialize(dir.getPath(), System.getProperty("java.class.path"), "1.4");
53
        Assert.assertEquals("No errors during compilation", 0, errors);
54
        eng.runScript("q", "t", rulesFile.getPath());
55
56
        Assert.assertTrue("There is something to commit", eng.needsCommit());
57
        Assert.assertTrue("commit ok", eng.commit());
58
    }
59
60
    final static String readFile (java.io.File f, boolean gzip) throws java.io.IOException {
61
        if (!gzip) {
62
            int s = (int)f.length ();
63
            byte[] data = new byte[s];
64
            Assert.assertEquals ("Read all data", s, new FileInputStream (f).read (data));
65
66
            return new String (data);
67
        } else {
68
            GZIPInputStream is = new GZIPInputStream(new FileInputStream(f));
69
            byte[] arr = new byte[256 * 256];
70
            int first = 0;
71
            for(;;) {
72
                int len = is.read(arr, first, arr.length - first);
73
                if (first + len < arr.length) {
74
                    return new String(arr, 0, first + len);
75
                }
76
            }
77
        }
78
    }
79
    
80
    final static File extractString(String res) throws Exception {
81
        File f = File.createTempFile("res", ".xml");
82
        f.deleteOnExit ();
83
        return extractString(f, res);
84
    }
85
86
    final static File extractString (File f, String res) throws Exception {
87
        FileOutputStream os = new FileOutputStream(f);
88
        InputStream is = new ByteArrayInputStream(res.getBytes("UTF-8"));
89
        for (;;) {
90
            int ch = is.read ();
91
            if (ch == -1) break;
92
            os.write (ch);
93
        }
94
        os.close ();
95
            
96
        return f;
97
    }
98
    
99
    final static File extractResource(String res) throws Exception {
100
        URL u = JackpotUtils.class.getResource(res);
101
        Assert.assertNotNull ("Resource should be found " + res, u);
102
        return extractResource(u);
103
    }
104
105
    final static File extractResource(URL u) throws Exception {
106
        Assert.assertNotNull ("Resource should be found " + u, u);
107
        
108
        File f = File.createTempFile("res", ".xml");
109
        f.deleteOnExit ();
110
        
111
        FileOutputStream os = new FileOutputStream(f);
112
        InputStream is = u.openStream();
113
        for (;;) {
114
            int ch = is.read ();
115
            if (ch == -1) break;
116
            os.write (ch);
117
        }
118
        os.close ();
119
            
120
        return f;
121
    }
122
123
}
(-)core/src/META-INF/services/java.util.logging.Handler (+1 lines)
Added Link Here
1
org.netbeans.core.NbErrorManager
(-)core/src/META-INF/services/org.openide.ErrorManager (-1 lines)
Removed Link Here
1
org.netbeans.core.NbErrorManager
(-)core/src/org/netbeans/core/Bundle.properties (-12 lines)
Lines 260-277 Link Here
260
# NOI18N
260
# NOI18N
261
MSG_ExceptionHeader={0}*********** Exception occurred ************ at {1,time,short} on {1,date,medium}
261
MSG_ExceptionHeader={0}*********** Exception occurred ************ at {1,time,short} on {1,date,medium}
262
262
263
# {0} - class name from MRE
264
EXC_MissingResourceException_class_name=Missing resource from class: {0}
265
# {0} - key from MRE
266
EXC_MissingResourceException_key=Key which was not found: {0}
267
# {0} - public ID
268
# {1] - system ID
269
EXC_sax_parse=Parse error in file {1} (PUBLIC {0})
270
# {0} - public ID
271
# {1] - system ID
272
# {2} - column #
273
# {3} - line #
274
EXC_sax_parse_col_line=Parse error in file {1} line {3} column {2} (PUBLIC {0})
275
263
276
UI/Services=Options
264
UI/Services=Options
277
# UI/Service_Hint=Contains global IDE preferences.
265
# UI/Service_Hint=Contains global IDE preferences.
(-)core/src/org/netbeans/core/NbErrorManager.java (-504 / +187 lines)
Lines 1-11 Link Here
1
/*
1
/*
2
 *                 Sun Public License Notice
2
 *                 Sun Public License Notice
3
 * 
3
 *
4
 * The contents of this file are subject to the Sun Public License
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
7
 * http://www.sun.com/
8
 * 
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun
11
 * Microsystems, Inc. All Rights Reserved.
11
 * Microsystems, Inc. All Rights Reserved.
Lines 31-373 Link Here
31
import java.util.Locale;
31
import java.util.Locale;
32
import java.util.Map;
32
import java.util.Map;
33
import java.util.MissingResourceException;
33
import java.util.MissingResourceException;
34
import java.util.ResourceBundle;
34
import java.util.Set;
35
import java.util.Set;
35
import java.util.StringTokenizer;
36
import java.util.StringTokenizer;
36
import java.util.WeakHashMap;
37
import java.util.WeakHashMap;
38
import java.util.concurrent.Callable;
39
import java.util.logging.Handler;
37
import java.util.logging.Level;
40
import java.util.logging.Level;
38
import java.util.logging.LogRecord;
41
import java.util.logging.LogRecord;
39
import java.util.logging.Logger;
42
import java.util.logging.Logger;
40
import org.openide.ErrorManager;
43
import org.openide.ErrorManager;
44
import org.openide.util.Lookup;
41
import org.openide.util.NbBundle;
45
import org.openide.util.NbBundle;
42
import org.xml.sax.SAXParseException;
46
import org.xml.sax.SAXParseException;
43
47
44
/** Wraps errormanager with logger.
48
/** Wraps errormanager with logger.
45
*
49
 *
46
* @author Jaroslav Tulach, Jesse Glick
50
 * @author Jaroslav Tulach, Jesse Glick
47
*/
51
 */
48
public final class NbErrorManager extends ErrorManager {
52
public final class NbErrorManager extends Handler {
49
    static {
53
    /** our root logger */
50
        System.setProperty("sun.awt.exception.handler", "org.netbeans.core.NbErrorManager$AWTHandler"); // NOI18N
54
    static NbErrorManager ROOT = new NbErrorManager();
51
    }
55
    
52
56
    Exc createExc(Throwable t, Level severity, LogRecord add) {
53
    /** logger to delegate to */
57
        LogRecord[] ann = findAnnotations(t, add);
54
    private Logger logger;
58
        return new Exc(t, severity, ann, findAnnotations0(t, add, true, new HashSet()));
55
    /** mapping of Throwables to errors */
56
    private static Map<Throwable,List<Annotation>> map = new HashMap<Throwable,List<Annotation>>();
57
58
    public NbErrorManager() {
59
        this("");
60
    }
59
    }
61
60
62
    private NbErrorManager(String pfx) {
61
    public void publish(LogRecord record) {
63
        this(Logger.getLogger(pfx));
62
        if (record.getThrown() != null) {
63
            Level level = record.getLevel();
64
            if (level.intValue() == Level.WARNING.intValue() + 1) {
65
                // unknown level
66
                level = null;
67
            }
68
            Exc ex = createExc(record.getThrown(), level, record.getLevel().intValue() == 1973 ? record : null);
69
            NotifyException.notify(ex);
70
        }
64
    }
71
    }
65
    
72
    
66
    /**
73
    public void flush() {
67
     * Construct for testing.
74
        //logWriter.flush();
68
     * @see "#18141"
69
     */
70
    NbErrorManager(Logger l) {
71
        this.logger = l;
72
    }
75
    }
73
    
76
    
74
    private static Level mapSeverity (int severity, boolean forException) {
77
    public void close() throws SecurityException {
75
        Level sev = Level.SEVERE;
78
        // nothing needed
76
77
        if (severity >= ERROR) {
78
            sev = Level.SEVERE;
79
        } else if (severity >= EXCEPTION) {
80
            sev = Level.SEVERE;
81
        } else if (severity >= USER) {
82
            sev = Level.INFO;
83
        } else if (severity >= WARNING) {
84
            sev = Level.WARNING;
85
        } else if (severity >= INFORMATIONAL) {
86
            sev = forException ? Level.INFO: Level.FINE;
87
        }
88
        return sev;
89
    }
90
91
92
    public synchronized Throwable annotate (
93
        Throwable t,
94
        int severity, String message, String localizedMessage,
95
        Throwable stackTrace, Date date
96
    ) {
97
        List<Annotation> o = map.get (t);
98
99
        List<Annotation> ll;
100
        if (o == null) {
101
            ll = new ArrayList<Annotation> ();
102
            map.put (t, ll);
103
        } else {
104
            ll = o;
105
        }
106
107
        ll.add(0,
108
            new Ann (severity, message, localizedMessage, stackTrace, date)
109
        );
110
111
        return t;
112
    }
79
    }
113
80
    
114
81
    /** Extracts localized message from a LogRecord */
115
    /** Associates annotations with this thread.
82
    static final String getLocalizedMessage(LogRecord rec) {
116
    *
83
        ResourceBundle rb = rec.getResourceBundle();
117
    * @param arr array of annotations (or null)
84
        if (rb == null) {
118
    */
85
            return null;
119
    public synchronized Throwable attachAnnotations (Throwable t, Annotation[] arr) {
120
        List<Annotation> o = map.get (t);
121
        List<Annotation> l;
122
        if (o == null) {
123
            l = new ArrayList<Annotation>(arr.length + 5);
124
            map.put (t, l);
125
        } else {
126
            l = o;
127
        }
86
        }
128
        l.addAll(0, Arrays.asList(arr));
129
        
87
        
130
        return t;
88
        String msg = rec.getMessage();
131
    }
89
        if (msg == null) {
132
90
            return null;
133
    /** Honor configured min-severity levels, more or less.
134
     * Actually bump up the effective severity of an exception by one.
135
     * Thus by default INFORMATIONAL stack traces are displayed, but not
136
     * messages. By playing with min log severity levels, you can get
137
     * both, or neither.
138
     * @see "#24056"
139
     */
140
    public boolean isNotifiable(int severity) {
141
        return logger.isLoggable(mapSeverity(severity, true));
142
    }
143
144
    /** Notifies all the exceptions associated with
145
    * this thread.
146
    */
147
    public synchronized void notify (int severity, Throwable t) {
148
        // synchronized to ensure that only one exception is
149
        // written to the thread
150
        
151
        Exc ex = createExc(t, severity);
152
        
153
        if (!isNotifiable(ex.getSeverity())) {
154
            return;
155
        }
156
        
157
        //issue 36878 - printing the stack trace on a user error is
158
        //disconcerting because it makes it look like something went wrong
159
        //with the software.
160
        
161
        //Note the algorithm below is different than that of Exc.getSeverity() -
162
        //there are cases (e.g. a property editor over a filesystem) where
163
        //an exception may be annotated as severe, but in the context
164
        //it is not - thus we check if *any* annotation is USER, rather than
165
        //that the highest level severity in the annotation is USER
166
        boolean wantStackTrace = severity != USER;
167
        if (wantStackTrace) {
168
            Annotation[] ann = findAnnotations(t);
169
            if (ann != null) {
170
                for (int i=0; i < ann.length; i++) {
171
                    if (ann[i] instanceof Ann) {
172
                        if (((Ann) ann[i]).getSeverity() == USER) {
173
                            wantStackTrace = false;
174
                            break;
175
                        }
176
                    }
177
                }
178
            }
179
        }
91
        }
180
        if (wantStackTrace) {
92
        
181
            String s = ex.getSeverity() == ErrorManager.INFORMATIONAL ? "INFORMATIONAL" : ""; // NOI18N
93
        String format = rb.getString(msg);
182
            Level level = mapSeverity(ex.getSeverity(), true);
183
            LogRecord rec = new LogRecord(level, "MSG_ExceptionHeader"); // NOI18N
184
            rec.setResourceBundle(NbBundle.getBundle(NbErrorManager.class));
185
            rec.setMillis(ex.getDate().getTime());
186
            rec.setParameters(new Object[] { s, ex.getDate() });
187
            try {
188
                if (!enterLog()) {
189
                    logger.log(rec);
190
                }
191
            } finally {
192
                exitLog();
193
            }
194
195
            StringWriter annotate = new StringWriter();
196
            PrintWriter pw = new PrintWriter(annotate);
197
            ex.printStackTrace(pw);
198
            pw.close();
199
94
200
            try {
95
        Object[] arr = rec.getParameters();
201
                if (!enterLog()) {
96
        if (arr == null) {
202
                    logger.log(level, annotate.toString());
97
            return format;
203
                }
204
            } finally {
205
                exitLog();
206
            }
207
        }
98
        }
208
99
209
        if (ex.getSeverity () > INFORMATIONAL) {
100
        return MessageFormat.format(format, arr);
210
            NotifyException.notify (ex);
211
        }
212
    }
213
    
214
    /**
215
     * Just create the exception information for a throwable being notified.
216
     * Useful for the unit test.
217
     */
218
    Exc createExc(Throwable t, int severity) {
219
        Annotation[] ann = findAnnotations (t);
220
        return new Exc (t, severity, ann, findAnnotations0(t, true, new HashSet<Throwable>()));
221
    }
101
    }
222
102
223
    public void log(int severity, String s) {
103
    /** Finds annotations associated with given exception.
224
        try {
104
     * @param t the exception
225
            if (!enterLog()) {
105
     * @return array of annotations or null
226
                logger.log(mapSeverity(severity, false), s);
227
            }
228
        } finally {
229
            exitLog();
230
        }
231
    }
232
    
233
    /** Allows to test whether messages with given severity will be logged
234
     * or not prior to constraction of complicated and time expensive
235
     * logging messages.
236
     *
237
     * @param severity the severity to check
238
     * @return false if the next call to log method with the same severity will
239
     *    discard the message
240
     */
106
     */
241
    public boolean isLoggable (int severity) {
107
    public synchronized LogRecord[] findAnnotations(Throwable t, LogRecord add) {
242
        return logger.isLoggable(mapSeverity(severity, false));
108
        return findAnnotations0(t, add, false, new HashSet());
243
    }
109
    }
244
    
110
    
245
    
246
    /** Returns an instance with given name. The name
247
     * can be dot separated list of names creating
248
     * a hierarchy.
249
     */
250
    public final ErrorManager getInstance(String name) {
251
        String pfx = logger.getName();
252
        if (pfx.length() > 0 && !pfx.endsWith(".")) {
253
            pfx += ".";
254
        }
255
        pfx += name;
256
        return new NbErrorManager(pfx);
257
    }    
258
    
259
    /** Method (or field) names in various exception classes which give
260
     * a nested exception. Fields should be public, methods public no-arg.
261
     * Field names should be prefixed with a dot.
262
     */
263
    private static Map<String,String> NESTS = null;
264
    private static Throwable extractNestedThrowable(Throwable t) {
265
        synchronized (NbErrorManager.class) {
266
            if (NESTS == null) {
267
                NESTS = new HashMap<String,String>();
268
                NESTS.put("javax.xml.parsers.FactoryConfigurationError", "getException"); // NOI18N
269
                NESTS.put("javax.xml.transform.TransformerFactoryConfigurationError", "getException"); // NOI18N
270
                NESTS.put("org.xml.sax.SAXException", "getException"); // NOI18N
271
            }
272
        }
273
        for (Class c = t.getClass(); c != Object.class; c = c.getSuperclass()) {
274
            String getter = (String)NESTS.get(c.getName());
275
            if (getter != null) {
276
                try {
277
                    if (getter.charAt(0) == '.') { // NOI18N
278
                        Field f = c.getField(getter.substring(1));
279
                        return (Throwable)f.get(t);
280
                    } else {
281
                        Method m = c.getMethod(getter);
282
                        return (Throwable)m.invoke(t);
283
                    }
284
                } catch (Exception e) {
285
                    // Should not happen.
286
                    System.err.println("From throwable class: " + c.getName()); // NOI18N
287
                    e.printStackTrace();
288
                }
289
            }
290
        }
291
        return null;
292
    }
293
294
    /** Finds annotations associated with given exception.
295
    * @param t the exception
296
    * @return array of annotations or null
297
    */
298
    public synchronized Annotation[] findAnnotations (Throwable t) {
299
        return findAnnotations0(t, false, new HashSet<Throwable>());
300
    }
301
302
    /** If recursively is true it is not adviced to print all annotations
111
    /** If recursively is true it is not adviced to print all annotations
303
     * because a lot of warnings will be printed. But while searching for
112
     * because a lot of warnings will be printed. But while searching for
304
     * localized message we should scan all the annotations (even recursively).
113
     * localized message we should scan all the annotations (even recursively).
305
     */
114
     */
306
    private synchronized Annotation[] findAnnotations0(Throwable t, boolean recursively, Set<Throwable> alreadyVisited) {
115
    private synchronized LogRecord[] findAnnotations0(Throwable t, LogRecord add, boolean recursively, Set alreadyVisited) {
307
        List<ErrorManager.Annotation> l = map.get (t);
116
        List l = new ArrayList();
308
        // MissingResourceException should be printed nicely... --jglick
117
        Throwable collect = t;
309
        if (t instanceof MissingResourceException) {
118
        while (collect != null) {
310
            if (l == null) {
119
            if (collect instanceof Callable) {
311
                l = new ArrayList<ErrorManager.Annotation>(1);
120
                Object res = null;
312
            } else {
121
                try {
313
                // make a copy, do not modify it
122
                    res = ((Callable) collect).call();
314
                l = new ArrayList<ErrorManager.Annotation>(l);
123
                } catch (Exception ex) {
315
            }
124
                    ex.printStackTrace();
316
            MissingResourceException mre = (MissingResourceException) t;
317
            String cn = mre.getClassName ();
318
            if (cn != null) {
319
                l.add (new Ann (EXCEPTION, NbBundle.getMessage (NbErrorManager.class, "EXC_MissingResourceException_class_name", cn), null, null, null));
320
            }
321
            String k = mre.getKey ();
322
            if (k != null) {
323
                l.add (new Ann (EXCEPTION, NbBundle.getMessage (NbErrorManager.class, "EXC_MissingResourceException_key", k), null, null, null));
324
            }
325
            if (l.size () == 0) l = null; // not clear if null means something other than new Annotation[0]
326
        } else {
327
            // #15611: find all kinds of nested exceptions and deal with them too.
328
            // Use of Throwable.initCause is preferred.
329
            Throwable t2 = extractNestedThrowable(t);
330
            if (t2 != null) {
331
                if (l == null) {
332
                    l = new ArrayList<ErrorManager.Annotation>(1);
333
                } else {
334
                    l = new ArrayList<ErrorManager.Annotation>(l);
335
                }
336
                l.add(new Ann(UNKNOWN, null, null, t2, null));
337
            }
338
        }
339
        if (t instanceof SAXParseException) {
340
            // For some reason these fail to come with useful data, like location.
341
            SAXParseException spe = (SAXParseException)t;
342
            String pubid = spe.getPublicId();
343
            String sysid = spe.getSystemId();
344
            if (pubid != null || sysid != null) {
345
                int col = spe.getColumnNumber();
346
                int line = spe.getLineNumber();
347
                String msg;
348
                if (col != -1 || line != -1) {
349
                    msg = NbBundle.getMessage(NbErrorManager.class, "EXC_sax_parse_col_line", new Object[] {String.valueOf(pubid), String.valueOf(sysid), new Integer(col), new Integer(line)});
350
                } else {
351
                    msg = NbBundle.getMessage(NbErrorManager.class, "EXC_sax_parse", String.valueOf(pubid), String.valueOf(sysid));
352
                }
125
                }
353
                if (l == null) {
126
                if (res instanceof LogRecord[]) {
354
                    l = new ArrayList<ErrorManager.Annotation>(1);
127
                    LogRecord[] arr = (LogRecord[])res;
355
                } else {
128
                    l.addAll(Arrays.asList(arr));
356
                    l = new ArrayList<ErrorManager.Annotation>(l);
357
                }
129
                }
358
                l.add(new Ann(UNKNOWN, msg, null, null, null));
359
            }
130
            }
131
            collect = collect.getCause();
360
        }
132
        }
133
134
        if (add != null) {
135
            l.add(add);
136
        }
137
361
        
138
        
362
        if (recursively) {
139
        if (recursively) {
363
            if (l != null) {
140
            if (l != null) {
364
                ArrayList<Annotation> al = new ArrayList<Annotation>();
141
                ArrayList al = new ArrayList();
365
                for (Iterator<Annotation> i = l.iterator(); i.hasNext(); ) {
142
                for (Iterator i = l.iterator(); i.hasNext(); ) {
366
                    Annotation ano = i.next();
143
                    LogRecord ano = (LogRecord)i.next();
367
                    Throwable t1 = ano.getStackTrace();
144
                    Throwable t1 = ano.getThrown();
368
                    if ((t1 != null) && (! alreadyVisited.contains(t1))) {
145
                    if ((t1 != null) && (! alreadyVisited.contains(t1))) {
369
                        alreadyVisited.add(t1);
146
                        alreadyVisited.add(t1);
370
                        Annotation[] tmpAnnoArray = findAnnotations0(t1, true, alreadyVisited);
147
                        LogRecord[] tmpAnnoArray = findAnnotations0(t1, null, true, alreadyVisited);
371
                        if ((tmpAnnoArray != null) && (tmpAnnoArray.length > 0)) {
148
                        if ((tmpAnnoArray != null) && (tmpAnnoArray.length > 0)) {
372
                            al.addAll(Arrays.asList(tmpAnnoArray));
149
                            al.addAll(Arrays.asList(tmpAnnoArray));
373
                        }
150
                        }
Lines 376-520 Link Here
376
                l.addAll(al);
153
                l.addAll(al);
377
            }
154
            }
378
        }
155
        }
156
379
        Throwable cause = t.getCause();
157
        Throwable cause = t.getCause();
380
        if (cause != null) {
158
        if (cause != null) {
381
            Annotation[] extras = findAnnotations0(cause, true, alreadyVisited);
159
            LogRecord[] extras = findAnnotations0(cause, null, true, alreadyVisited);
382
            if (extras != null && extras.length > 0) {
160
            if (extras != null && extras.length > 0) {
383
                if (l == null) {
161
                if (l == null) {
384
                    l = new ArrayList<Annotation>();
162
                    l = new ArrayList<LogRecord>();
385
                }
163
                }
386
                l.addAll(Arrays.asList(extras));
164
                l.addAll(Arrays.asList(extras));
387
            }
165
            }
388
        }
166
        }
389
        
167
        
390
        Annotation[] arr;
168
        LogRecord[] arr;
391
        if (l == null) {
169
        if (l == null) {
392
            arr = null;
170
            arr = null;
393
        } else {
171
        } else {
394
            arr = new Annotation[l.size ()];
172
            arr = new LogRecord[l.size()];
395
            l.toArray (arr);
173
            l.toArray(arr);
396
        }
174
        }
397
175
        
398
        return arr;
176
        return arr;
399
    }
177
    }
400
    
178
    
401
    public String toString() {
402
        return super.toString() + "<" + logger + ">"; // NOI18N
403
    }
404
405
    private static volatile Thread lastThread;
406
    private static boolean enterLog() {
407
        if (lastThread == Thread.currentThread()) {
408
            new Exception("using error manager from inside a logger").printStackTrace(); // NOI18N
409
            return true;
410
        }
411
        lastThread = Thread.currentThread();
412
        return false;
413
    }
414
415
    private static void exitLog() {
416
        lastThread = null;
417
    }
418
    
419
    /** Implementation of annotation interface.
420
    */
421
    private static final class Ann extends Object
422
        implements ErrorManager.Annotation {
423
        private int severity;
424
        private String message;
425
        private String localizedMessage;
426
        private Throwable stackTrace;
427
        private Date date;
428
429
        /** Constructor.
430
        */
431
        public Ann (
432
            int severity,
433
            String message,
434
            String localizedMessage,
435
            Throwable stackTrace,
436
            Date date
437
        ) {
438
            this.severity = severity;
439
            this.message = message;
440
            this.localizedMessage = localizedMessage;
441
            this.stackTrace = stackTrace;
442
            this.date = date;
443
        }
444
445
        /** Non-localized message.
446
         * @return associated message or null
447
         */
448
        public String getMessage() {
449
            return message;
450
        }
451
        /** Localized message.
452
         * @return message to be presented to the user or null
453
         */
454
        public String getLocalizedMessage() {
455
            return localizedMessage;
456
        }
457
        /** Stack trace. The stack trace should locate the method
458
         * and possition in the method where error occured.
459
         *
460
         * @return exception representing the location of error or null
461
         */
462
        public Throwable getStackTrace() {
463
            return stackTrace;
464
        }
465
        /** Date when the exception occured.
466
         * @return the date or null
467
         */
468
        public java.util.Date getDate() {
469
            return date;
470
        }
471
        /** Severity of the exception.
472
         * @return number representing the severity
473
         */
474
        public int getSeverity() {
475
            return severity;
476
        }
477
        
478
        public String toString() {
479
            return "NbEM.Ann[severity=" + severity + ",message=" + message + ",localizedMessage=" + localizedMessage + ",stackTrace=" + stackTrace + ",date=" + date + "]"; // NOI18N
480
        }
481
        
482
    } // end of Ann
483
484
    /**
179
    /**
485
     * Another final class that is used to communicate with
180
     * Another final class that is used to communicate with
486
     * NotifyException and provides enough information to the dialog.
181
     * NotifyException and provides enough information to the dialog.
487
     */
182
     */
488
    final class Exc
183
    final class Exc {
489
    {
490
        /** the original throwable */
184
        /** the original throwable */
491
        private Throwable t;
185
        private Throwable t;
492
        private Date d;
186
        private Date d;
493
        private Annotation[] arr;
187
        private LogRecord[] arr;
494
        private Annotation[] arrAll; // all - recursively
188
        private LogRecord[] arrAll; // all - recursively
495
        private int severity;
189
        private Level severity;
496
190
        
497
        /** @param severity if -1 then we will compute the
191
        /** @param severity if -1 then we will compute the
498
         * severity from annotations
192
         * severity from annotations
499
         */
193
         */
500
        Exc (Throwable t, int severity, Annotation[] arr, Annotation[] arrAll) {
194
        Exc(Throwable t, Level severity, LogRecord[] arr, LogRecord[] arrAll) {
501
            this.t = t;
195
            this.t = t;
502
            this.severity = severity;
196
            this.severity = severity;
503
            this.arr = arr == null ? new Annotation[0] : arr;
197
            this.arr = arr == null ? new LogRecord[0] : arr;
504
            this.arrAll = arrAll == null ? new Annotation[0] : arrAll;
198
            this.arrAll = arrAll == null ? new LogRecord[0] : arrAll;
505
        }
199
        }
506
200
        
507
        /** @return message */
201
        /** @return message */
508
        String getMessage () {
202
        String getMessage() {
509
            String m = t.getMessage();
203
            String m = t.getMessage();
510
            if (m != null) {
204
            if (m != null) {
511
                return m;
205
                return m;
512
            }
206
            }
513
            return (String)find (1);
207
            return (String)find(1);
514
        }
208
        }
515
209
        
516
        /** @return localized message */
210
        /** @return localized message */
517
        String getLocalizedMessage () {
211
        String getLocalizedMessage() {
518
            String m = t.getLocalizedMessage();
212
            String m = t.getLocalizedMessage();
519
            if (m != null && !m.equals(t.getMessage())) {
213
            if (m != null && !m.equals(t.getMessage())) {
520
                return m;
214
                return m;
Lines 524-537 Link Here
524
                return (String)find(2);
218
                return (String)find(2);
525
            }
219
            }
526
            for (int i = 0; i < arrAll.length; i++) {
220
            for (int i = 0; i < arrAll.length; i++) {
527
                String s = arrAll[i].getLocalizedMessage ();
221
                String s = NbErrorManager.getLocalizedMessage(arrAll[i]);
528
                if (s != null) {
222
                if (s != null) {
529
                    return s;
223
                    return s;
530
                }
224
                }
531
            }
225
            }
532
            return m;
226
            return m;
533
        }
227
        }
534
	
228
        
535
        boolean isLocalized() {
229
        boolean isLocalized() {
536
            String m = t.getLocalizedMessage();
230
            String m = t.getLocalizedMessage();
537
            if (m != null && !m.equals(t.getMessage())) {
231
            if (m != null && !m.equals(t.getMessage())) {
Lines 542-597 Link Here
542
                return (String)find(2) != null;
236
                return (String)find(2) != null;
543
            }
237
            }
544
            for (int i = 0; i < arrAll.length; i++) {
238
            for (int i = 0; i < arrAll.length; i++) {
545
                String s = arrAll[i].getLocalizedMessage ();
239
                String s = NbErrorManager.getLocalizedMessage(arrAll[i]);
546
                if (s != null) {
240
                if (s != null) {
547
                    return true;
241
                    return true;
548
                }
242
                }
549
            }
243
            }
550
            return false;
244
            return false;
551
	}
245
        }
552
246
        
553
        /** @return class name of the exception */
247
        /** @return class name of the exception */
554
        String getClassName () {
248
        String getClassName() {
555
            return (String)find (3);
249
            return (String)find(3);
556
        }
250
        }
557
251
        
558
        /** @return the severity of the exception */
252
        /** @return the severity of the exception */
559
        int getSeverity () {
253
        Level getSeverity() {
560
            if (severity != UNKNOWN) {
254
            if (severity != null) {
561
                return severity;
255
                return severity;
562
            }
256
            }
563
257
            
564
            Annotation[] anns = (arrAll != null) ? arrAll : arr;
258
            LogRecord[] anns = (arrAll != null) ? arrAll : arr;
565
            for (int i = 0; i < anns.length; i++) {
259
            for (int i = 0; i < anns.length; i++) {
566
                int s = anns[i].getSeverity ();
260
                Level s = anns[i].getLevel();
567
                if (s > severity) {
261
                if (severity == null || s.intValue() > severity.intValue()) {
568
                    severity = s;
262
                    severity = s;
569
                }
263
                }
570
            }
264
            }
571
265
            
572
            if (severity == UNKNOWN) {
266
            if (severity == null || severity == Level.ALL) {
573
                // no severity specified, assume this is an error
267
                // no severity specified, assume this is an error
574
                severity = t instanceof Error ? ERROR : EXCEPTION;
268
                severity = t instanceof Error ? Level.SEVERE : Level.WARNING;
575
            }
269
            }
576
270
            
577
            return severity;
271
            return severity;
578
        }
272
        }
579
273
        
580
        /** @return date assigned to the exception */
274
        /** @return date assigned to the exception */
581
        Date getDate () {
275
        Date getDate() {
582
            if (d == null) {
276
            if (d == null) {
583
                d = (Date)find (4);
277
                d = (Date)find(4);
584
            }
278
            }
585
            return d;
279
            return d;
586
        }
280
        }
587
281
        
588
        void printStackTrace (PrintStream ps) {
282
        void printStackTrace(PrintStream ps) {
589
            printStackTrace(new PrintWriter(new OutputStreamWriter(ps)));
283
            printStackTrace(new PrintWriter(new OutputStreamWriter(ps)));
590
        }
284
        }
591
        /** Prints stack trace of all annotations and if
285
        /** Prints stack trace of all annotations and if
592
         * there is no annotation trace then of the exception
286
         * there is no annotation trace then of the exception
593
         */
287
         */
594
        void printStackTrace (PrintWriter pw) {
288
        void printStackTrace(PrintWriter pw) {
595
            // #19487: don't go into an endless loop here
289
            // #19487: don't go into an endless loop here
596
            printStackTrace(pw, new HashSet<Throwable>(10));
290
            printStackTrace(pw, new HashSet<Throwable>(10));
597
        }
291
        }
Lines 599-620 Link Here
599
        private void printStackTrace(PrintWriter pw, Set<Throwable> nestingCheck) {
293
        private void printStackTrace(PrintWriter pw, Set<Throwable> nestingCheck) {
600
            if (t != null && !nestingCheck.add(t)) {
294
            if (t != null && !nestingCheck.add(t)) {
601
                // Unlocalized log message - this is for developers of NB, not users
295
                // Unlocalized log message - this is for developers of NB, not users
602
                log(ErrorManager.WARNING, "WARNING - ErrorManager detected cyclic exception nesting:"); // NOI18N
296
                Logger l = Logger.getAnonymousLogger();
297
                l.warning("WARNING - ErrorManager detected cyclic exception nesting:"); // NOI18N
603
                Iterator it = nestingCheck.iterator();
298
                Iterator it = nestingCheck.iterator();
604
                while (it.hasNext()) {
299
                while (it.hasNext()) {
605
                    Throwable t = (Throwable)it.next();
300
                    Throwable t = (Throwable)it.next();
606
                    log(ErrorManager.WARNING, "\t" + t); // NOI18N
301
                    l.warning("\t" + t); // NOI18N
607
                    Annotation[] anns = findAnnotations(t);
302
                    LogRecord[] anns = findAnnotations(t, null);
608
                    if (anns != null) {
303
                    if (anns != null) {
609
                        for (int i = 0; i < anns.length; i++) {
304
                        for (int i = 0; i < anns.length; i++) {
610
                            Throwable t2 = anns[i].getStackTrace();
305
                            Throwable t2 = anns[i].getThrown();
611
                            if (t2 != null) {
306
                            if (t2 != null) {
612
                                log(ErrorManager.WARNING, "\t=> " + t2); // NOI18N
307
                                l.warning("\t=> " + t2); // NOI18N
613
                            }
308
                            }
614
                        }
309
                        }
615
                    }
310
                    }
616
                }
311
                }
617
                log(ErrorManager.WARNING, "Be sure not to annotate an exception with itself, directly or indirectly."); // NOI18N
312
                l.warning("Be sure not to annotate an exception with itself, directly or indirectly."); // NOI18N
618
                return;
313
                return;
619
            }
314
            }
620
            /*Heaeder
315
            /*Heaeder
Lines 629-641 Link Here
629
                pw.print("<no message>"); // NOI18N
324
                pw.print("<no message>"); // NOI18N
630
            }
325
            }
631
            pw.println ();
326
            pw.println ();
632
            */
327
             */
633
            /*Annotations */
328
            /*Annotations */
634
          for (int i = 0; i < arr.length; i++) {
329
            for (int i = 0; i < arr.length; i++) {
635
                if (arr[i] == null) continue;
330
                if (arr[i] == null) continue;
636
                
331
                
637
                Throwable thr = arr[i].getStackTrace();                
332
                Throwable thr = arr[i].getThrown();
638
                String annotation = arr[i].getLocalizedMessage();
333
                String annotation = NbErrorManager.getLocalizedMessage(arr[i]);
639
                
334
                
640
                if (annotation == null) annotation = arr[i].getMessage();
335
                if (annotation == null) annotation = arr[i].getMessage();
641
                /*
336
                /*
Lines 645-655 Link Here
645
                
340
                
646
                if (annotation != null) {
341
                if (annotation != null) {
647
                    if (thr == null) {
342
                    if (thr == null) {
648
                        pw.println ("Annotation: "+annotation);// NOI18N
343
                        pw.println("Annotation: "+annotation);// NOI18N
649
                    }
344
                    }
650
                    //else pw.println ("Nested annotation: "+annotation);// NOI18N
345
                    //else pw.println ("Nested annotation: "+annotation);// NOI18N
651
                }                
346
                }
652
            }            
347
            }
653
            
348
            
654
            // ok, print trace of the original exception too
349
            // ok, print trace of the original exception too
655
            // Attempt to show an annotation indicating where the exception
350
            // Attempt to show an annotation indicating where the exception
Lines 670-715 Link Here
670
                        break;
365
                        break;
671
                    }
366
                    }
672
                }
367
                }
673
            String[] tLines = decompose (t);
368
                String[] tLines = decompose(t);
674
            for (int i = 0; i < tLines.length; i++) {
369
                for (int i = 0; i < tLines.length; i++) {
675
                if (i == idx) {
370
                    if (i == idx) {
676
                    pw.print ("[catch]"); // NOI18N
371
                        pw.print("[catch]"); // NOI18N
677
                    // Also translate following tab -> space since formatting is bad in
372
                        // Also translate following tab -> space since formatting is bad in
678
                    // Output Window (#8104) and some mail agents screw it up etc.
373
                        // Output Window (#8104) and some mail agents screw it up etc.
679
                    if (tLines[i].charAt (0) == '\t') {
374
                        if (tLines[i].charAt(0) == '\t') {
680
                        pw.print (' ');
375
                            pw.print(' ');
681
                        tLines[i] = tLines[i].substring (1);
376
                            tLines[i] = tLines[i].substring(1);
377
                        }
682
                    }
378
                    }
379
                    pw.println(tLines[i]);
683
                }
380
                }
684
                pw.println (tLines[i]);
685
            }
381
            }
686
            }
382
            /*Nested annotations */
687
            /*Nested annotations */            
688
            for (int i = 0; i < arr.length; i++) {
383
            for (int i = 0; i < arr.length; i++) {
689
                if (arr[i] == null) continue;
384
                if (arr[i] == null) continue;
690
                
385
                
691
                Throwable thr = arr[i].getStackTrace();
386
                Throwable thr = arr[i].getThrown();
692
                if (thr != null) {
387
                if (thr != null) {
693
                    Annotation[] ans = findAnnotations (thr);
388
                    LogRecord[] ans = findAnnotations(thr, null);
694
                    Exc ex = new Exc (thr, 0, ans, null);
389
                    Exc ex = new Exc(thr, null, ans, null);
695
                    pw.println("==>"); // NOI18N
390
                    pw.println("==>"); // NOI18N
696
                    ex.printStackTrace(pw, nestingCheck);
391
                    ex.printStackTrace(pw, nestingCheck);
697
                }
392
                }
698
            }
393
            }
699
        }
394
        }
700
395
        
701
        /** Get a throwable's stack trace, decomposed into individual lines. */
396
        /** Get a throwable's stack trace, decomposed into individual lines. */
702
        private  String[] decompose (Throwable t) {
397
        private  String[] decompose(Throwable t) {
703
            StringWriter sw = new StringWriter ();
398
            StringWriter sw = new StringWriter();
704
            t.printStackTrace (new PrintWriter (sw));
399
            t.printStackTrace(new PrintWriter(sw));
705
            StringTokenizer tok = new StringTokenizer (sw.toString (), "\n\r"); // NOI18N
400
            StringTokenizer tok = new StringTokenizer(sw.toString(), "\n\r"); // NOI18N
706
            int c = tok.countTokens ();
401
            int c = tok.countTokens();
707
            String[] lines = new String[c];
402
            String[] lines = new String[c];
708
            for (int i = 0; i < c; i++)
403
            for (int i = 0; i < c; i++)
709
                lines[i] = tok.nextToken ();
404
                lines[i] = tok.nextToken();
710
            return lines;
405
            return lines;
711
        }
406
        }
712
407
        
713
        /**
408
        /**
714
         * Method that iterates over annotations to find out
409
         * Method that iterates over annotations to find out
715
         * the first annotation that brings the requested value.
410
         * the first annotation that brings the requested value.
Lines 717-726 Link Here
717
         * @param kind what to look for (1, 2, 3, 4, ...);
412
         * @param kind what to look for (1, 2, 3, 4, ...);
718
         * @return the found object
413
         * @return the found object
719
         */
414
         */
720
        private Object find (int kind) {
415
        private Object find(int kind) {
721
	    return find(kind, true);
416
            return find(kind, true);
722
	}
417
        }
723
418
        
724
        /**
419
        /**
725
         * Method that iterates over annotations to find out
420
         * Method that iterates over annotations to find out
726
         * the first annotation that brings the requested value.
421
         * the first annotation that brings the requested value.
Lines 728-787 Link Here
728
         * @param kind what to look for (1, 2, 3, 4, ...);
423
         * @param kind what to look for (1, 2, 3, 4, ...);
729
         * @return the found object
424
         * @return the found object
730
         */
425
         */
731
        private Object find (int kind, boolean def) {
426
        private Object find(int kind, boolean def) {
732
            for (int i = 0; i < arr.length; i++) {
427
            for (int i = 0; i < arr.length; i++) {
733
                Annotation a = arr[i];
428
                LogRecord a = arr[i];
734
429
                
735
                Object o = null;
430
                Object o = null;
736
                switch (kind) {
431
                switch (kind) {
737
                case 1: // message
432
                    case 1: // message
738
                    o = a.getMessage (); break;
433
                        o = a.getMessage(); break;
739
                case 2: // localized
434
                    case 2: // localized
740
                    o = a.getLocalizedMessage (); break;
435
                        o = NbErrorManager.getLocalizedMessage(a); break;
741
                case 3: // class name
436
                    case 3: // class name
742
                    {
437
                    {
743
                        Throwable t = a.getStackTrace ();
438
                        Throwable t = a.getThrown();
744
                        o = t == null ? null : t.getClass().getName();
439
                        o = t == null ? null : t.getClass().getName();
745
                        break;
440
                        break;
746
                    }
441
                    }
747
                case 4: // date
442
                    case 4: // date
748
                    o = a.getDate (); break;
443
                        o = new Date(a.getMillis()); break;
749
                }
444
                }
750
445
                
751
                if (o != null) {
446
                if (o != null) {
752
                    return o;
447
                    return o;
753
                }
448
                }
754
            }
449
            }
755
	    
450
            
756
	    if (!def)
451
            if (!def)
757
		return null;
452
                return null;
758
            switch (kind) {
453
            switch (kind) {
759
            case 1: // message
454
                case 1: // message
760
                return t.getMessage ();
455
                    return t.getMessage();
761
            case 2: // loc.msg.
456
                case 2: // loc.msg.
762
                return t.getLocalizedMessage();
457
                    return t.getLocalizedMessage();
763
            case 3: // class name
458
                case 3: // class name
764
                return t.getClass ().getName ();
459
                    return t.getClass().getName();
765
            case 4: // date
460
                case 4: // date
766
                return new Date ();
461
                    return new Date();
767
            default:
462
                default:
768
                throw new IllegalArgumentException (
463
                    throw new IllegalArgumentException(
769
                    "Unknown " + new Integer (kind) // NOI18N
464
                        "Unknown " + new Integer(kind) // NOI18N
770
                );
465
                        );
771
            }
772
        }
773
    }
774
775
    /** Instances are created in awt.EventDispatchThread */
776
    public static final class AWTHandler
777
    {
778
        /** The name MUST be handle and MUST be public */
779
        public static void handle(Throwable t) {
780
            // Either org.netbeans or org.netbeans.core.execution pkgs:
781
            if (t.getClass().getName().endsWith(".ExitSecurityException")) { // NOI18N
782
                return;
783
            }
466
            }
784
            ErrorManager.getDefault().notify((ERROR << 1), t);
785
        }
467
        }
786
    }
468
    }
469
    
787
}
470
}
(-)core/src/org/netbeans/core/NotifyException.java (-50 / +80 lines)
Lines 26-31 Link Here
26
import java.io.StringWriter;
26
import java.io.StringWriter;
27
import java.util.ArrayList;
27
import java.util.ArrayList;
28
import java.util.ResourceBundle;
28
import java.util.ResourceBundle;
29
import java.util.logging.Level;
29
import javax.swing.Icon;
30
import javax.swing.Icon;
30
import javax.swing.ImageIcon;
31
import javax.swing.ImageIcon;
31
import javax.swing.JButton;
32
import javax.swing.JButton;
Lines 38-44 Link Here
38
import org.netbeans.core.startup.CLIOptions;
39
import org.netbeans.core.startup.CLIOptions;
39
import org.openide.DialogDescriptor;
40
import org.openide.DialogDescriptor;
40
import org.openide.DialogDisplayer;
41
import org.openide.DialogDisplayer;
41
import org.openide.ErrorManager;
42
import org.openide.NotifyDescriptor;
42
import org.openide.NotifyDescriptor;
43
import org.openide.util.NbBundle;
43
import org.openide.util.NbBundle;
44
import org.openide.util.Utilities;
44
import org.openide.util.Utilities;
Lines 171-242 Link Here
171
        
171
        
172
        return false;
172
        return false;
173
    }
173
    }
174
175
    private static boolean isAssertionsEnabled() {
176
        boolean assertsionAreOn = false;
177
        assert assertsionAreOn = true;
178
        return assertsionAreOn;
179
    }
180
    
174
    
181
    /**
175
    /**
182
     * For unit-testing only
176
     * For unit-testing only
183
     */
177
     */
184
    static NotifyException newInstance() {
178
    static void cleanInstance() {
185
        return new NotifyException();
179
        INSTANCE = null;
186
    }
180
    }
187
    
181
182
188
    /** Adds new exception into the queue.
183
    /** Adds new exception into the queue.
189
     */
184
     */
190
    public static void notify (
185
    public static void notify (
191
        final NbErrorManager.Exc t
186
        final NbErrorManager.Exc t
192
    ) {
187
    ) {
188
        if (!shallNotify(t.getSeverity(), false)) {
189
            return;
190
        }
191
        
193
        // #50018 Don't try to show any notify dialog when reporting headless exception
192
        // #50018 Don't try to show any notify dialog when reporting headless exception
194
        if ("java.awt.HeadlessException".equals(t.getClassName()) && GraphicsEnvironment.isHeadless()) {
193
        if ("java.awt.HeadlessException".equals(t.getClassName()) && GraphicsEnvironment.isHeadless()) {
195
            t.printStackTrace(System.err);
194
            t.printStackTrace(System.err);
196
            return;
195
            return;
197
        }
196
        }
198
        
197
199
        SwingUtilities.invokeLater (new Runnable () {
198
        SwingUtilities.invokeLater (new Runnable () {
200
            public void run() {
199
            public void run() {
201
                String glm = t.getLocalizedMessage();
200
                String glm = t.getLocalizedMessage();
202
                int gs = t.getSeverity();
201
                Level gs = t.getSeverity();
203
                boolean loc = t.isLocalized();
202
                boolean loc = t.isLocalized();
203
204
                if (loc) {
205
                    if (gs == Level.WARNING) {
206
                        DialogDisplayer.getDefault().notify(
207
                            new NotifyDescriptor.Message(glm, NotifyDescriptor.WARNING_MESSAGE)
208
                        );
209
                        return;
210
                    }
211
212
                    if (gs.intValue() == 1973) {
213
                        DialogDisplayer.getDefault().notify(
214
                            new NotifyDescriptor.Message(glm, NotifyDescriptor.INFORMATION_MESSAGE)
215
                        );
216
                        return;
217
                    }
218
219
                    if (gs == Level.SEVERE) {
220
                        DialogDisplayer.getDefault().notify(
221
                            new NotifyDescriptor.Message(glm, NotifyDescriptor.ERROR_MESSAGE)
222
                        );
223
                        return;
224
                    }
225
                }
226
204
                
227
                
205
                if (gs == ErrorManager.WARNING && loc) {
228
                if( null == exceptions )
206
                    DialogDisplayer.getDefault().notify(
229
                    exceptions = new ArrayListPos();
207
                        new NotifyDescriptor.Message(glm, NotifyDescriptor.WARNING_MESSAGE));
230
                exceptions.add(t);
208
                } else if (gs == ErrorManager.USER && loc) {
231
                exceptions.position = exceptions.size()-1;
209
                    DialogDisplayer.getDefault().notify(
232
210
                        new NotifyDescriptor.Message(glm, NotifyDescriptor.INFORMATION_MESSAGE));
233
                if(shallNotify(t.getSeverity(), true)) {
211
                } else if (gs == ErrorManager.ERROR && loc) {
234
                    // Assertions are on, so show the exception window.
212
                    DialogDisplayer.getDefault().notify(
235
                    if( INSTANCE == null ) {
213
                        new NotifyDescriptor.Message(glm, NotifyDescriptor.ERROR_MESSAGE));
236
                        INSTANCE = new NotifyException();
237
                    }
238
                    INSTANCE.updateState(t);
214
                } else {
239
                } else {
215
                    if( null == exceptions )
240
                    // No assertions, use the flashing icon.
216
                        exceptions = new ArrayListPos();
241
                    if( null != flasher && null == INSTANCE ) {
217
                    exceptions.add(t);
242
                        //exception window is not visible, start flashing the icon
218
                    exceptions.position = exceptions.size()-1;
243
                        flasher.setToolTipText( getExceptionSummary( t ) );
219
                    
244
                        flasher.startFlashing();
220
                    if( isAssertionsEnabled() ) {
245
                    } else {
221
                        // Assertions are on, so show the exception window.
246
                        //exception window is already visible (or the flashing icon is not available)
247
                        //so we'll only update the exception window
222
                        if( INSTANCE == null ) {
248
                        if( INSTANCE == null ) {
223
                            INSTANCE = new NotifyException();
249
                            INSTANCE = new NotifyException();
224
                        }
250
                        }
225
                        INSTANCE.updateState(t);
251
                        INSTANCE.updateState(t);
226
                    } else {
227
                        // No assertions, use the flashing icon.
228
                        if( null != flasher && null == INSTANCE ) {
229
                            //exception window is not visible, start flashing the icon
230
                            flasher.setToolTipText( getExceptionSummary( t ) );
231
                            flasher.startFlashing();
232
                        } else {
233
                            //exception window is already visible (or the flashing icon is not available)
234
                            //so we'll only update the exception window
235
                            if( INSTANCE == null ) {
236
                                INSTANCE = new NotifyException();
237
                            }
238
                            INSTANCE.updateState(t);
239
                        }
240
                    }
252
                    }
241
                }
253
                }
242
            }
254
            }
Lines 291-301 Link Here
291
            //another dialog, which will trigger another exception, endlessly.
303
            //another dialog, which will trigger another exception, endlessly.
292
            //Catch any exceptions and append them to the list instead.
304
            //Catch any exceptions and append them to the list instead.
293
            ensurePreferredSize();
305
            ensurePreferredSize();
294
            dialog.setVisible (true);
306
            dialog.setVisible(true);
295
            //throw new RuntimeException ("I am not so exceptional"); //uncomment to test
307
            //throw new RuntimeException ("I am not so exceptional"); //uncomment to test
296
        } catch (Exception e) {
308
        } catch (Exception e) {
297
            exceptions.add(new NbErrorManager().createExc(
309
            exceptions.add(new NbErrorManager().createExc(
298
                e, ErrorManager.EXCEPTION));
310
                e, Level.SEVERE, null));
299
            next.setVisible(true);
311
            next.setVisible(true);
300
        }
312
        }
301
    }
313
    }
Lines 360-366 Link Here
360
                }
372
                }
361
            } else {
373
            } else {
362
                ResourceBundle curBundle = NbBundle.getBundle (NotifyException.class);
374
                ResourceBundle curBundle = NbBundle.getBundle (NotifyException.class);
363
                if (current.getSeverity() == ErrorManager.WARNING) {
375
                if (current.getSeverity() == Level.WARNING) {
364
                    // less scary message for warning level
376
                    // less scary message for warning level
365
                    descriptor.setMessage (
377
                    descriptor.setMessage (
366
                        java.text.MessageFormat.format(
378
                        java.text.MessageFormat.format(
Lines 417-423 Link Here
417
                //Do not allow an exception thrown here to trigger an endless
429
                //Do not allow an exception thrown here to trigger an endless
418
                //loop
430
                //loop
419
                exceptions.add(new NbErrorManager().createExc(e, //ugly but works
431
                exceptions.add(new NbErrorManager().createExc(e, //ugly but works
420
                    ErrorManager.EXCEPTION));
432
                    Level.SEVERE, null));
421
                next.setVisible(true);
433
                next.setVisible(true);
422
            }
434
            }
423
            return;
435
            return;
Lines 450-461 Link Here
450
            }
462
            }
451
        }
463
        }
452
    }
464
    }
465
466
467
    /** Method that checks whether the level is high enough to be notified
468
     * at all.
469
     * @param dialog shall we check for dialog or just a blinking icon (false)
470
     */
471
    private static boolean shallNotify(Level level, boolean dialog) {
472
        int minAlert = Integer.getInteger("netbeans.exception.alert.min.level", 900); // NOI18N
473
        boolean assertionsOn = false;
474
        assert assertionsOn = true;
475
        int defReport = assertionsOn ? 900 : 1001;
476
        int minReport = Integer.getInteger("netbeans.exception.report.min.level", defReport); // NOI18N
477
478
        if (dialog) {
479
            return level.intValue() >= minReport;
480
        } else {
481
            return level.intValue() >= minAlert || level.intValue() >= minReport;
482
        }
483
    }
453
    
484
    
485
454
    /**
486
    /**
455
     * The icon shown in the main status bar that is flashing when an exception
487
     * The icon shown in the main status bar that is flashing when an exception
456
     * is encountered.
488
     * is encountered.
457
     */
489
     */
458
    private static ExceptionFlasher flasher = null;
490
    static FlashingIcon flasher = null;
459
    
491
    
460
    /**
492
    /**
461
     * Return an icon that is flashing when a new internal exception occurs. 
493
     * Return an icon that is flashing when a new internal exception occurs. 
Lines 467-481 Link Here
467
     */
499
     */
468
    public static Component getNotificationVisualizer() {
500
    public static Component getNotificationVisualizer() {
469
        //do not create flashing icon if not allowed in system properties
501
        //do not create flashing icon if not allowed in system properties
470
        if( isAssertionsEnabled() ) 
471
            return null;
472
        if( null == flasher ) {
502
        if( null == flasher ) {
473
            ImageIcon img1 = new ImageIcon( Utilities.loadImage("org/netbeans/core/resources/exception.gif", true) );
503
            ImageIcon img1 = new ImageIcon( Utilities.loadImage("org/netbeans/core/resources/exception.gif", true) );
474
            flasher = new ExceptionFlasher( img1 );
504
            flasher = new ExceptionFlasher( img1 );
475
        }
505
        }
476
        return flasher;
506
        return flasher;
477
    }
507
    }
478
    
508
479
    private static class ExceptionFlasher extends FlashingIcon {
509
    private static class ExceptionFlasher extends FlashingIcon {
480
        public ExceptionFlasher( Icon img1 ) {
510
        public ExceptionFlasher( Icon img1 ) {
481
            super( img1 );
511
            super( img1 );
(-)core/startup/src/org/netbeans/core/startup/Bundle.properties (+19 lines)
Lines 185-187 Link Here
185
    This property cannot be changed while the IDE is running, so this attempt had no effect.
185
    This property cannot be changed while the IDE is running, so this attempt had no effect.
186
# {0} - JAR file name
186
# {0} - JAR file name
187
TEXT_patch=Module patch or custom extension: {0}
187
TEXT_patch=Module patch or custom extension: {0}
188
189
190
#
191
# TopLogging
192
#
193
194
# {0} - class name from MRE
195
EXC_MissingResourceException_class_name=Missing resource from class: {0}
196
# {0} - key from MRE
197
EXC_MissingResourceException_key=Key which was not found: {0}
198
# {0} - public ID
199
# {1] - system ID
200
EXC_sax_parse=Parse error in file {1} (PUBLIC {0})
201
# {0} - public ID
202
# {1] - system ID
203
# {2} - column #
204
# {3} - line #
205
EXC_sax_parse_col_line=Parse error in file {1} line {3} column {2} (PUBLIC {0})
206
(-)core/startup/src/org/netbeans/core/startup/TopLogging.java (-12 / +174 lines)
Lines 24-33 Link Here
24
import java.io.UnsupportedEncodingException;
24
import java.io.UnsupportedEncodingException;
25
import java.text.DateFormat;
25
import java.text.DateFormat;
26
import java.util.Date;
26
import java.util.Date;
27
import java.util.HashSet;
27
import java.util.Iterator;
28
import java.util.Iterator;
28
import java.util.Locale;
29
import java.util.Locale;
29
import java.util.Map;
30
import java.util.Map;
31
import java.util.MissingResourceException;
32
import java.util.Set;
30
import java.util.StringTokenizer;
33
import java.util.StringTokenizer;
34
import java.util.concurrent.Callable;
31
import java.util.logging.Formatter;
35
import java.util.logging.Formatter;
32
import java.util.logging.Handler;
36
import java.util.logging.Handler;
33
import java.util.logging.Level;
37
import java.util.logging.Level;
Lines 36-43 Link Here
36
import java.util.logging.Logger;
40
import java.util.logging.Logger;
37
import java.util.logging.StreamHandler;
41
import java.util.logging.StreamHandler;
38
import org.openide.filesystems.FileUtil;
42
import org.openide.filesystems.FileUtil;
43
import org.openide.util.Lookup;
39
import org.openide.util.NbBundle;
44
import org.openide.util.NbBundle;
40
import org.openide.util.RequestProcessor;
45
import org.openide.util.RequestProcessor;
46
import org.xml.sax.SAXParseException;
41
47
42
/**
48
/**
43
 * Class that sets the java.util.logging.LogManager configuration to log into
49
 * Class that sets the java.util.logging.LogManager configuration to log into
Lines 49-54 Link Here
49
    private static boolean disabledConsole = ! Boolean.getBoolean("netbeans.logger.console"); // NOI18N
55
    private static boolean disabledConsole = ! Boolean.getBoolean("netbeans.logger.console"); // NOI18N
50
    /** reference to the old error stream */
56
    /** reference to the old error stream */
51
    private static final PrintStream OLD_ERR = System.err;
57
    private static final PrintStream OLD_ERR = System.err;
58
    static {
59
        System.setProperty("sun.awt.exception.handler", "org.netbeans.core.startup.TopLogging$AWTHandler"); // NOI18N
60
    }
52
61
53
    /** Initializes the logging configuration. Invoked by <code>LogManager.readConfiguration</code> method.
62
    /** Initializes the logging configuration. Invoked by <code>LogManager.readConfiguration</code> method.
54
     */
63
     */
Lines 93-98 Link Here
93
        if (!disabledConsole) { // NOI18N
102
        if (!disabledConsole) { // NOI18N
94
            logger.addHandler (streamHandler ());
103
            logger.addHandler (streamHandler ());
95
        }
104
        }
105
        logger.addHandler(new LookupDel());
106
107
        /* TBD:
108
        for (Handler h : Lookup.getDefault().lookupAll(Handler.class)) {
109
            logger.addHandler(h);
110
        }
111
         */
96
    }
112
    }
97
113
98
    private static String previousUser;
114
    private static String previousUser;
Lines 361-373 Link Here
361
377
362
        
378
        
363
        public String format(java.util.logging.LogRecord record) {
379
        public String format(java.util.logging.LogRecord record) {
380
            StringBuilder sb = new StringBuilder();
381
            print(sb, record, new HashSet<Throwable>());
382
            return sb.toString();
383
        }
384
385
386
        private void print(StringBuilder sb, LogRecord record, Set<Throwable> beenThere) {
364
            String message = formatMessage(record);
387
            String message = formatMessage(record);
365
            if (message != null && message.indexOf('\n') != -1 && record.getThrown() == null) {
388
            if (message != null && message.indexOf('\n') != -1 && record.getThrown() == null) {
366
                // multi line messages print witout any wrappings
389
                // multi line messages print witout any wrappings
367
                return message;
390
                sb.append(message);
391
                return;
368
            }
392
            }
369
393
370
            StringBuffer sb = new StringBuffer();
371
            sb.append(record.getLevel().getLocalizedName());
394
            sb.append(record.getLevel().getLocalizedName());
372
            addLoggerName (sb, record);
395
            addLoggerName (sb, record);
373
            if (message != null) {
396
            if (message != null) {
Lines 375-406 Link Here
375
                sb.append(message);
398
                sb.append(message);
376
            }
399
            }
377
            sb.append(lineSeparator);
400
            sb.append(lineSeparator);
378
            if (record.getThrown() != null) {
401
            if (record.getThrown() != null && record.getLevel().intValue() != 1973) { // 1973 signals ErrorManager.USER
379
                try {
402
                try {
380
                    StringWriter sw = new StringWriter();
403
                    StringWriter sw = new StringWriter();
381
                    PrintWriter pw = new PrintWriter(sw);
404
                    PrintWriter pw = new PrintWriter(sw);
382
                    record.getThrown().printStackTrace(pw);
405
                    // All other kinds of throwables we check for a stack trace.
406
                    // First try to find where the throwable was caught.
407
                    StackTraceElement[] tStack = record.getThrown().getStackTrace();
408
                    StackTraceElement[] hereStack = new Throwable().getStackTrace();
409
                    int idx = -1;
410
                    for (int i = 1; i <= Math.min(tStack.length, hereStack.length); i++) {
411
                        if (!tStack[tStack.length - i].equals(hereStack[hereStack.length - i])) {
412
                            idx = tStack.length - i + 1;
413
                            break;
414
                        }
415
                    }
416
                    String[] tLines = decompose(record.getThrown());
417
                    for (int i = 0; i < tLines.length; i++) {
418
                        if (i == idx) {
419
                            pw.print("[catch]"); // NOI18N
420
                            // Also translate following tab -> space since formatting is bad in
421
                            // Output Window (#8104) and some mail agents screw it up etc.
422
                            if (tLines[i].charAt(0) == '\t') {
423
                                pw.print(' ');
424
                                tLines[i] = tLines[i].substring(1);
425
                            }
426
                        }
427
                        pw.println(tLines[i]);
428
                    }
383
                    pw.close();
429
                    pw.close();
384
                    sb.append(sw.toString());
430
                    sb.append(sw.toString());
385
                } catch (Exception ex) {
431
                } catch (Exception ex) {
386
                }
432
                }
433
434
                LogRecord[] arr = extractDelegates(sb, record.getThrown(), beenThere);
435
                if (arr != null) {
436
                    for (LogRecord r : arr) {
437
                        print(sb, r, beenThere);
438
                    }
439
                }
440
441
                specialProcessing(sb, record.getThrown(), beenThere);
387
            }
442
            }
388
            return sb.toString();
389
        }
443
        }
390
        
444
        
391
        private static void addLoggerName (StringBuffer sb, java.util.logging.LogRecord record) {
445
        private static void addLoggerName (StringBuilder sb, java.util.logging.LogRecord record) {
392
            String name = record.getLoggerName ();
446
            String name = record.getLoggerName ();
393
            if (!"".equals (name)) {
447
            if (!"".equals (name)) {
394
                sb.append(" [");
448
                sb.append(" [");
395
                sb.append(name);
449
                sb.append(name);
396
                sb.append(']');
450
                sb.append(']');
397
//                if (record.getSourceClassName() != null) {	
398
//                    sb.append(record.getSourceClassName());
399
//                } else {
400
//                    sb.append(record.getLoggerName());
401
//                }
402
            }
451
            }
403
        }
452
        }
453
454
        private static LogRecord[] extractDelegates(StringBuilder sb, Throwable t, Set<Throwable> beenThere) {
455
            if (!beenThere.add(t)) {
456
                sb.append("warning: cyclic dependency between annotated throwables"); // NOI18N
457
                return null;
458
            }
459
460
            if (t instanceof Callable) {
461
                Object rec = null;
462
                try {
463
                    rec = ((Callable) t).call();
464
                } catch (Exception ex) {
465
                    ex.printStackTrace();
466
                }
467
                if (rec instanceof LogRecord[]) {
468
                    return (LogRecord[])rec;
469
                }
470
            }
471
            if (t == null) {
472
                return null;
473
            }
474
            return extractDelegates(sb, t.getCause(), beenThere);
475
        }
476
477
478
        private void specialProcessing(StringBuilder sb, Throwable t, Set<Throwable> beenThere) {
479
            // MissingResourceException should be printed nicely... --jglick
480
            if (t instanceof MissingResourceException) {
481
                MissingResourceException mre = (MissingResourceException) t;
482
                String cn = mre.getClassName();
483
                if (cn != null) {
484
                    LogRecord rec = new LogRecord(Level.CONFIG, null);
485
                    rec.setResourceBundle(NbBundle.getBundle(TopLogging.class));
486
                    rec.setMessage("EXC_MissingResourceException_class_name");
487
                    rec.setParameters(new Object[] { cn });
488
                    print(sb, rec, beenThere);
489
                }
490
                String k = mre.getKey();
491
                if (k != null) {
492
                    LogRecord rec = new LogRecord(Level.CONFIG, null);
493
                    rec.setResourceBundle(NbBundle.getBundle(TopLogging.class));
494
                    rec.setMessage("EXC_MissingResourceException_key");
495
                    rec.setParameters(new Object[] { k });
496
                    print(sb, rec, beenThere);
497
                }
498
            }
499
            if (t instanceof SAXParseException) {
500
                // For some reason these fail to come with useful data, like location.
501
                SAXParseException spe = (SAXParseException)t;
502
                String pubid = spe.getPublicId();
503
                String sysid = spe.getSystemId();
504
                if (pubid != null || sysid != null) {
505
                    int col = spe.getColumnNumber();
506
                    int line = spe.getLineNumber();
507
                    String msg;
508
                    Object[] param;
509
                    if (col != -1 || line != -1) {
510
                        msg = "EXC_sax_parse_col_line"; // NOI18N
511
                        param = new Object[] {String.valueOf(pubid), String.valueOf(sysid), new Integer(col), new Integer(line)};
512
                    } else {
513
                        msg = "EXC_sax_parse"; // NOI18N
514
                        param = new Object[] { String.valueOf(pubid), String.valueOf(sysid) };
515
                    }
516
                    LogRecord rec = new LogRecord(Level.CONFIG, null);
517
                    rec.setResourceBundle(NbBundle.getBundle(TopLogging.class));
518
                    rec.setMessage(msg);
519
                    rec.setParameters(param);
520
                    print(sb, rec, beenThere);
521
                }
522
            }
523
        }
524
        /** Get a throwable's stack trace, decomposed into individual lines. */
525
        private static String[] decompose(Throwable t) {
526
            StringWriter sw = new StringWriter();
527
            t.printStackTrace(new PrintWriter(sw));
528
            StringTokenizer tok = new StringTokenizer(sw.toString(), "\n\r"); // NOI18N
529
            int c = tok.countTokens();
530
            String[] lines = new String[c];
531
            for (int i = 0; i < c; i++)
532
                lines[i] = tok.nextToken();
533
            return lines;
534
        }
404
    } // end of NbFormater
535
    } // end of NbFormater
405
536
406
    /** a stream to delegate to logging.
537
    /** a stream to delegate to logging.
Lines 442-448 Link Here
442
                sb.delete(0, first);
573
                sb.delete(0, first);
443
            }
574
            }
444
        }
575
        }
576
    } // end of LgStream
577
578
    private static final class LookupDel extends Handler {
579
        public void publish(LogRecord record) {
580
            for (Handler h : Lookup.getDefault().lookupAll(Handler.class)) {
581
                h.publish(record);
582
            }
583
        }
445
584
585
        public void flush() {
586
            for (Handler h : Lookup.getDefault().lookupAll(Handler.class)) {
587
                h.flush();
588
            }
589
        }
590
591
        public void close() throws SecurityException {
592
            for (Handler h : Lookup.getDefault().lookupAll(Handler.class)) {
593
                h.close();
594
            }
595
        }
596
    } // end of LookupDel
597
598
    /** Instances are created in awt.EventDispatchThread */
599
    public static final class AWTHandler {
600
        /** The name MUST be handle and MUST be public */
601
        public static void handle(Throwable t) {
602
            // Either org.netbeans or org.netbeans.core.execution pkgs:
603
            if (t.getClass().getName().endsWith(".ExitSecurityException")) { // NOI18N
604
                return;
605
            }
606
            Logger.global.throwing(null, null, t);
607
        }
608
    } // end of AWTHandler
446
609
447
    }
448
}
610
}
(-)core/startup/test/unit/src/org/netbeans/core/startup/TopLoggingLookupTest.java (+108 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 * 
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 * 
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
package org.netbeans.core.startup;
14
15
import java.io.ByteArrayOutputStream;
16
import java.io.File;
17
import java.io.FileInputStream;
18
import java.io.FileNotFoundException;
19
import java.io.IOException;
20
import java.io.OutputStream;
21
import java.io.PrintStream;
22
import java.util.ArrayList;
23
import java.util.Collections;
24
import java.util.List;
25
import java.util.logging.Handler;
26
import java.util.logging.Level;
27
import java.util.logging.LogManager;
28
import java.util.logging.LogRecord;
29
import java.util.logging.Logger;
30
import java.util.logging.StreamHandler;
31
import java.util.logging.XMLFormatter;
32
import java.util.regex.Matcher;
33
import java.util.regex.Pattern;
34
import org.netbeans.junit.NbTestCase;
35
import org.openide.util.Lookup;
36
import org.openide.util.lookup.AbstractLookup;
37
import org.openide.util.lookup.InstanceContent;
38
39
40
/**
41
 * Checks the top logging delegates to handlers in lookup.
42
 */
43
public class TopLoggingLookupTest extends NbTestCase {
44
    static {
45
        System.setProperty("org.openide.util.Lookup", Lkp.class.getName());
46
    }
47
48
    private MyHandler handler;
49
    
50
    public TopLoggingLookupTest(String testName) {
51
        super(testName);
52
    }
53
54
    protected void setUp() throws Exception {
55
        clearWorkDir();
56
        System.setProperty("netbeans.user", getWorkDirPath());
57
58
        assertEquals(Lkp.class, Lookup.getDefault().getClass());
59
        Lkp.IC.set(Collections.emptyList(), null);
60
61
        // initialize logging
62
        TopLogging.initialize();
63
64
        handler = new MyHandler();
65
66
        Lkp.IC.add(handler);
67
    }
68
69
70
    protected void tearDown() throws Exception {
71
    }
72
73
    public void testLogOneLine() throws Exception {
74
        Logger.getLogger(TopLoggingTest.class.getName()).log(Level.INFO, "First visible message");
75
76
        assertEquals("[First visible message]", handler.logs.toString());
77
78
    }
79
80
    public static final class Lkp extends AbstractLookup {
81
        public static InstanceContent IC;
82
83
        public Lkp() {
84
            this(new InstanceContent());
85
        }
86
        private Lkp(InstanceContent ic) {
87
            super(ic);
88
            IC = ic;
89
        }
90
    }
91
92
    private static final class MyHandler extends Handler {
93
        public List<String> logs = new ArrayList<String>();
94
95
        public void publish(LogRecord record) {
96
            logs.add(record.getMessage());
97
        }
98
99
        public void flush() {
100
            logs.add("flush");
101
        }
102
103
        public void close() throws SecurityException {
104
            logs.add("close");
105
        }
106
107
    }
108
}
(-)core/test/unit/src/org/netbeans/core/NbErrorManagerTest.java (-37 / +34 lines)
Lines 13-43 Link Here
13
13
14
package org.netbeans.core;
14
package org.netbeans.core;
15
15
16
import java.io.*;
16
import java.io.File;
17
import java.io.FileInputStream;
18
import java.io.IOException;
17
import java.lang.reflect.InvocationTargetException;
19
import java.lang.reflect.InvocationTargetException;
18
import java.util.Iterator;
20
import java.util.Iterator;
19
import java.util.MissingResourceException;
21
import java.util.MissingResourceException;
22
import java.util.logging.Level;
20
import java.util.logging.LogManager;
23
import java.util.logging.LogManager;
21
import javax.swing.SwingUtilities;
24
import javax.swing.SwingUtilities;
25
import junit.framework.Test;
22
import org.netbeans.core.startup.CLIOptions;
26
import org.netbeans.core.startup.CLIOptions;
23
import org.netbeans.junit.*;
27
import org.netbeans.junit.NbTestCase;
24
import junit.textui.TestRunner;
28
import org.netbeans.junit.NbTestSuite;
25
import org.openide.ErrorManager;
29
import org.openide.ErrorManager;
26
import org.openide.util.Lookup;
30
import org.openide.util.Lookup;
27
import org.xml.sax.SAXParseException;
31
import org.xml.sax.SAXParseException;
28
32
33
29
/**
34
/**
30
 * Test the core error manager impl.
35
 * Test the core error manager impl.
31
 * @author Jesse Glick
36
 * @author Jesse Glick
32
 * @see "#18141"
37
 * @see "#18141"
33
 */
38
 */
34
public class NbErrorManagerTest extends NbTestCase {
39
public final class NbErrorManagerTest extends NbTestCase {
35
    
40
    public NbErrorManagerTest(String s) {
36
    public NbErrorManagerTest(String name) {
41
        super(s);
37
        super(name);
42
    }
43
44
    public static Test suite() {
45
        //return new NbErrorManagerTest("testAddedInfo");
46
        return new NbTestSuite(NbErrorManagerTest.class);
38
    }
47
    }
39
    
48
    
40
    private NbErrorManager err;
49
    private ErrorManager err;
41
    protected void setUp() throws Exception {
50
    protected void setUp() throws Exception {
42
        clearWorkDir();
51
        clearWorkDir();
43
        
52
        
Lines 46-67 Link Here
46
        CLIOptions.initialize();
55
        CLIOptions.initialize();
47
56
48
57
49
        Iterator it = Lookup.getDefault().lookup(new Lookup.Template(ErrorManager.class)).allInstances().iterator();
58
        err = ErrorManager.getDefault();
50
        while (it.hasNext()) {
51
            Object o = it.next();
52
            if (o instanceof NbErrorManager) {
53
                assertNull("No err yet", err);
54
                err = (NbErrorManager)o;
55
            }
56
        }
57
58
        assertNotNull("One Error manager found", err);
59
        assertNotNull("One Error manager found", err);
59
    }
60
    }
60
    
61
    
61
    public void testEMFound() throws Exception {
62
        assertEquals(NbErrorManager.class, Lookup.getDefault().lookup(ErrorManager.class).getClass());
63
    }
64
65
    public void testIsLoggable() {
62
    public void testIsLoggable() {
66
        assertFalse(ErrorManager.getDefault ().isLoggable(ErrorManager.INFORMATIONAL));
63
        assertFalse(ErrorManager.getDefault ().isLoggable(ErrorManager.INFORMATIONAL));
67
        assertFalse(ErrorManager.getDefault ().isLoggable(ErrorManager.INFORMATIONAL + 1));
64
        assertFalse(ErrorManager.getDefault ().isLoggable(ErrorManager.INFORMATIONAL + 1));
Lines 205-212 Link Here
205
    public void testNotifyException() throws Exception {
202
    public void testNotifyException() throws Exception {
206
        IOException ioe = new IOException("unloc msg");
203
        IOException ioe = new IOException("unloc msg");
207
        err.annotate(ioe, "loc msg");
204
        err.annotate(ioe, "loc msg");
208
        NbErrorManager.Exc x = err.createExc(ioe, ErrorManager.USER);
205
        NbErrorManager.Exc x = NbErrorManager.ROOT.createExc(ioe, Level.INFO, null);
209
        assertEquals(ErrorManager.USER, x.getSeverity());
206
        assertEquals(Level.INFO, x.getSeverity());
210
        assertEquals("loc msg", x.getLocalizedMessage());
207
        assertEquals("loc msg", x.getLocalizedMessage());
211
        assertTrue(x.isLocalized());
208
        assertTrue(x.isLocalized());
212
        // could do more here...
209
        // could do more here...
Lines 220-227 Link Here
220
        
217
        
221
        // Simple exception is EXCEPTION.
218
        // Simple exception is EXCEPTION.
222
        Throwable t = new IOException("unloc msg");
219
        Throwable t = new IOException("unloc msg");
223
        NbErrorManager.Exc x = err.createExc(t, ErrorManager.UNKNOWN);
220
        NbErrorManager.Exc x = NbErrorManager.ROOT.createExc(t, null, null);
224
        assertEquals(ErrorManager.EXCEPTION, x.getSeverity());
221
        assertEquals(Level.WARNING, x.getSeverity());
225
        assertEquals("unloc msg", x.getMessage());
222
        assertEquals("unloc msg", x.getMessage());
226
        assertEquals("unloc msg", x.getLocalizedMessage());
223
        assertEquals("unloc msg", x.getLocalizedMessage());
227
        assertFalse(x.isLocalized());
224
        assertFalse(x.isLocalized());
Lines 229-236 Link Here
229
        // Same when there is unloc debug info attached.
226
        // Same when there is unloc debug info attached.
230
        t = new IOException("unloc msg");
227
        t = new IOException("unloc msg");
231
        err.annotate(t, ErrorManager.UNKNOWN, "some debug info", null, null, null);
228
        err.annotate(t, ErrorManager.UNKNOWN, "some debug info", null, null, null);
232
        x = err.createExc(t, ErrorManager.UNKNOWN);
229
        x = NbErrorManager.ROOT.createExc(t, null, null);
233
        assertEquals(ErrorManager.EXCEPTION, x.getSeverity());
230
        assertEquals(Level.WARNING, x.getSeverity());
234
        assertEquals("unloc msg", x.getMessage());
231
        assertEquals("unloc msg", x.getMessage());
235
        assertEquals("unloc msg", x.getLocalizedMessage());
232
        assertEquals("unloc msg", x.getLocalizedMessage());
236
        assertFalse(x.isLocalized());
233
        assertFalse(x.isLocalized());
Lines 239-246 Link Here
239
        t = new IOException("unloc msg");
236
        t = new IOException("unloc msg");
240
        Throwable t2 = new IOException("unloc msg #2");
237
        Throwable t2 = new IOException("unloc msg #2");
241
        err.annotate(t, ErrorManager.UNKNOWN, null, null, t2, null);
238
        err.annotate(t, ErrorManager.UNKNOWN, null, null, t2, null);
242
        x = err.createExc(t, ErrorManager.UNKNOWN);
239
        x = NbErrorManager.ROOT.createExc(t, null, null);
243
        assertEquals(ErrorManager.EXCEPTION, x.getSeverity());
240
        assertEquals(Level.WARNING, x.getSeverity());
244
        assertEquals("unloc msg", x.getMessage());
241
        assertEquals("unloc msg", x.getMessage());
245
        assertEquals("unloc msg", x.getLocalizedMessage());
242
        assertEquals("unloc msg", x.getLocalizedMessage());
246
        assertFalse(x.isLocalized());
243
        assertFalse(x.isLocalized());
Lines 249-256 Link Here
249
        // set the severity for the exception.
246
        // set the severity for the exception.
250
        t = new IOException("unloc msg");
247
        t = new IOException("unloc msg");
251
        err.annotate(t, ErrorManager.USER, null, "loc msg", null, null);
248
        err.annotate(t, ErrorManager.USER, null, "loc msg", null, null);
252
        x = err.createExc(t, ErrorManager.UNKNOWN);
249
        x = NbErrorManager.ROOT.createExc(t, null, null);
253
        assertEquals(ErrorManager.USER, x.getSeverity());
250
        assertEquals(1973, x.getSeverity().intValue());
254
        assertEquals("unloc msg", x.getMessage());
251
        assertEquals("unloc msg", x.getMessage());
255
        assertEquals("loc msg", x.getLocalizedMessage());
252
        assertEquals("loc msg", x.getLocalizedMessage());
256
        assertTrue(x.isLocalized());
253
        assertTrue(x.isLocalized());
Lines 260-267 Link Here
260
        t2 = new IOException("unloc msg #2");
257
        t2 = new IOException("unloc msg #2");
261
        err.annotate(t2, ErrorManager.USER, null, "loc msg", null, null);
258
        err.annotate(t2, ErrorManager.USER, null, "loc msg", null, null);
262
        err.annotate(t, ErrorManager.UNKNOWN, null, null, t2, null);
259
        err.annotate(t, ErrorManager.UNKNOWN, null, null, t2, null);
263
        x = err.createExc(t, ErrorManager.UNKNOWN);
260
        x = NbErrorManager.ROOT.createExc(t, null, null);
264
        assertEquals(ErrorManager.USER, x.getSeverity());
261
        assertEquals(1973, x.getSeverity().intValue());
265
        assertEquals("unloc msg", x.getMessage());
262
        assertEquals("unloc msg", x.getMessage());
266
        assertEquals("loc msg", x.getLocalizedMessage());
263
        assertEquals("loc msg", x.getLocalizedMessage());
267
        assertTrue(x.isLocalized());
264
        assertTrue(x.isLocalized());
Lines 271-278 Link Here
271
        err.annotate(t2, ErrorManager.USER, null, "loc msg", null, null);
268
        err.annotate(t2, ErrorManager.USER, null, "loc msg", null, null);
272
        t = new IOException("loc msg");
269
        t = new IOException("loc msg");
273
        err.annotate(t, ErrorManager.USER, null, null, t2, null);
270
        err.annotate(t, ErrorManager.USER, null, null, t2, null);
274
        x = err.createExc(t, ErrorManager.UNKNOWN);
271
        x = NbErrorManager.ROOT.createExc(t, null, null);
275
        assertEquals(ErrorManager.USER, x.getSeverity());
272
        assertEquals(1973, x.getSeverity().intValue());
276
        assertEquals("loc msg", x.getMessage());
273
        assertEquals("loc msg", x.getMessage());
277
        assertEquals("loc msg", x.getLocalizedMessage());
274
        assertEquals("loc msg", x.getLocalizedMessage());
278
        // Note that it is stil considered localized even though the messages
275
        // Note that it is stil considered localized even though the messages
Lines 297-305 Link Here
297
        // wait for a dialog to be shown
294
        // wait for a dialog to be shown
298
        waitEQ();
295
        waitEQ();
299
        
296
        
300
        int report = output.indexOf("Exception occurred");
297
        int report = output.indexOf("My: Ahoj");
301
        assertTrue("There is one exception reported: " + output, report > 0);
298
        assertTrue("There is one exception reported: " + output, report > 0);
302
        int next = output.indexOf("Exception occurred", report + 1);
299
        int next = output.indexOf("My: Ahoj", report + 1);
303
        assertEquals("No next exceptions there (after " + report + "):\n" + output, -1, next);
300
        assertEquals("No next exceptions there (after " + report + "):\n" + output, -1, next);
304
    }
301
    }
305
    
302
    
(-)core/test/unit/src/org/netbeans/core/NotifyExceptionBundle.properties (+13 lines)
Added Link Here
1
#                 Sun Public License Notice
2
# 
3
# The contents of this file are subject to the Sun Public License
4
# Version 1.0 (the "License"). You may not use this file except in
5
# compliance with the License. A copy of the License is available at
6
# http://www.sun.com/
7
# 
8
# The Original Code is NetBeans. The Initial Developer of the Original
9
# Code is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
10
# Microsystems, Inc. All Rights Reserved.
11
12
13
MSG_KEY=Some Message
(-)core/test/unit/src/org/netbeans/core/NotifyExceptionTest.java (-18 / +174 lines)
Lines 13-23 Link Here
13
13
14
package org.netbeans.core;
14
package org.netbeans.core;
15
15
16
import java.awt.Dialog;
16
import java.awt.Frame;
17
import java.awt.Frame;
18
import java.util.ResourceBundle;
19
import java.util.logging.Level;
20
import java.util.logging.LogRecord;
21
import java.util.logging.Logger;
22
import javax.swing.ImageIcon;
17
import javax.swing.JDialog;
23
import javax.swing.JDialog;
18
import javax.swing.SwingUtilities;
24
import javax.swing.SwingUtilities;
25
import org.netbeans.core.startup.TopLogging;
19
import org.netbeans.junit.*;
26
import org.netbeans.junit.*;
20
import junit.textui.TestRunner;
27
import org.openide.DialogDescriptor;
28
import org.openide.DialogDisplayer;
29
import org.openide.ErrorManager;
30
import org.openide.NotifyDescriptor;
31
import org.openide.util.NbBundle;
32
import org.openide.util.lookup.AbstractLookup;
33
import org.openide.util.lookup.InstanceContent;
21
34
22
import org.openide.windows.WindowManager;
35
import org.openide.windows.WindowManager;
23
36
Lines 26-65 Link Here
26
 * @author Stanislav Aubrecht
39
 * @author Stanislav Aubrecht
27
 */
40
 */
28
public class NotifyExceptionTest extends NbTestCase {
41
public class NotifyExceptionTest extends NbTestCase {
42
    static {
43
        System.setProperty("org.openide.util.Lookup", Lkp.class.getName());
44
    }
29
    
45
    
30
    public NotifyExceptionTest(String name) {
46
    public NotifyExceptionTest(String name) {
31
        super(name);
47
        super(name);
32
    }
48
    }
33
49
34
    protected boolean runInEQ() {
50
    private static void waitEQ() throws Exception {
35
        return true;
51
        SwingUtilities.invokeAndWait(new Runnable() {
36
    }
52
            public void run() {
37
    
53
            }
38
    public static void main(String[] args) {
54
        });
39
        TestRunner.run(new NbTestSuite(NotifyExceptionTest.class));
40
    }
55
    }
41
    
56
    
42
    protected void setUp() throws Exception {
57
    protected void setUp() throws Exception {
58
        clearWorkDir();
59
        System.setProperty("netbeans.user", getWorkDirPath());
60
        // initialize the logging
61
        new TopLogging();
62
63
        DD.lastDescriptor = null;
64
        DD.toReturn = null;
65
66
        System.getProperties().remove("netbeans.exception.alert.min.level");
67
        System.getProperties().remove("netbeans.exception.report.min.level");
68
69
        NotifyException.cleanInstance();
43
    }
70
    }
44
    
71
    
45
    static boolean errorDialogIsModal;
46
    /**
72
    /**
47
     * A simple test to ensure that error dialog window is not created modal
73
     * A simple test to ensure that error dialog window is not created modal
48
     * until the MainWindow is visible.
74
     * until the MainWindow is visible.
49
     */
75
     */
50
    public void testNoModalErrorDialog() throws Exception {
76
    public void testNoModalErrorDialog() throws Exception {
51
        Frame mainWindow = WindowManager.getDefault().getMainWindow();
77
        Frame mainWindow = WindowManager.getDefault().getMainWindow();
52
        final JDialog modalDialog = new JDialog( mainWindow, true );
78
        final JDialog modalDialog = new HiddenDialog( mainWindow, true );
53
        SwingUtilities.invokeLater( new Runnable() {
79
        DD.toReturn = modalDialog;
54
            public void run() {
80
55
                NotifyException ne = NotifyException.newInstance();
81
        Logger.global.log(Level.WARNING, "Something is wrong", new NullPointerException("npe"));
56
                errorDialogIsModal = ne.dialog.isModal();
82
        waitEQ();
57
                modalDialog.dispose();
83
        assertNotNull("Really returned", DD.lastDescriptor);
84
        assertEquals("It is DialogDescriptor", DialogDescriptor.class, DD.lastDescriptor.getClass());
85
        DialogDescriptor dd = (DialogDescriptor)DD.lastDescriptor;
86
        assertFalse( "The request is for non-modal dialog", dd.isModal());
87
        assertFalse("Main window is not visible", mainWindow.isVisible());
88
    }
89
90
    public void testExceptionWillGetTheLevelFromAnnoatation() throws Exception {
91
        NullPointerException npe = new NullPointerException("npe");
92
        ErrorManager.getDefault().annotate(npe, ErrorManager.WARNING, null, null, null, null);
93
94
        DD.toReturn = new HiddenDialog();
95
        ErrorManager.getDefault().notify(npe);
96
97
        waitEQ();
98
        assertNotNull("We are going to display a warning", DD.lastDescriptor);
99
100
    }
101
102
    public void testDirectlyLoggingAnExceptionWithALocalizedMessageAndTheRightLevelShowsItInADialog() throws Exception {
103
        NullPointerException npe = new NullPointerException("npe");
104
105
        LogRecord rec = new LogRecord(OwnLevel.UI, "MSG_KEY");
106
        rec.setThrown(npe);
107
        ResourceBundle b = ResourceBundle.getBundle("org/netbeans/core/NotifyExceptionBundle");
108
        rec.setResourceBundle(b);
109
        DD.toReturn = new HiddenDialog();
110
        Logger.global.log(rec);
111
        waitEQ();
112
        assertNotNull("We are going to display a warning", DD.lastDescriptor);
113
        assertTrue("We want message: " + DD.lastDescriptor, DD.lastDescriptor instanceof NotifyDescriptor.Message);
114
        NotifyDescriptor.Message msg = (NotifyDescriptor.Message)DD.lastDescriptor;
115
        assertEquals("Info msg", NotifyDescriptor.INFORMATION_MESSAGE, msg.getMessageType());
116
        assertEquals("Msg is localized", b.getString("MSG_KEY"), msg.getMessage());
117
    }
118
119
    public void testYesDialogShown() throws Exception {
120
        Frame mainWindow = WindowManager.getDefault().getMainWindow();
121
        final JDialog modalDialog = new HiddenDialog( mainWindow, true );
122
        DD.toReturn = modalDialog;
123
124
        Logger l = Logger.getLogger(getName());
125
        l.setLevel(Level.ALL);
126
        System.setProperty("netbeans.exception.report.min.level", "200");
127
        l.log(Level.CONFIG, "Something is wrong", new NullPointerException("npe"));
128
        waitEQ();
129
        assertNotNull("Really returned", DD.lastDescriptor);
130
        assertEquals("It is DialogDescriptor", DialogDescriptor.class, DD.lastDescriptor.getClass());
131
        DialogDescriptor dd = (DialogDescriptor)DD.lastDescriptor;
132
        assertFalse( "The request is for non-modal dialog", dd.isModal());
133
        assertFalse("Main window is not visible", mainWindow.isVisible());
134
    }
135
    public void testNoDialogShownJustFlashing() throws Exception {
136
        class MockFlashingIcon extends FlashingIcon {
137
            public int cnt;
138
139
            public MockFlashingIcon() {
140
                super(new ImageIcon());
141
            }
142
            protected void onMouseClick() {
143
            }
144
145
            protected void timeout() {
146
            }
147
148
            public void startFlashing() {
149
                cnt++;
58
            }
150
            }
59
        } );
151
        }
152
        MockFlashingIcon mock = new MockFlashingIcon();
153
154
        NotifyException.flasher = mock;
155
156
        Logger l = Logger.getLogger(getName());
157
        l.setLevel(Level.ALL);
158
        System.setProperty("netbeans.exception.alert.min.level", "200");
159
        l.log(Level.CONFIG, "Something is wrong", new NullPointerException("npe"));
160
        waitEQ();
161
        assertNull("Really returned", DD.lastDescriptor);
162
163
        assertEquals("Flasher flashing", 1, mock.cnt);
164
    }
165
166
    private static final class OwnLevel extends Level {
167
        public static final Level UI = new OwnLevel("UI", 1973);
168
169
        private OwnLevel(String n, int i) {
170
            super(n, i);
171
        }
172
    }
173
174
    private static final class DD extends DialogDisplayer {
175
        public static NotifyDescriptor lastDescriptor;
176
        public static Object toReturn;
177
178
        public Object notify(NotifyDescriptor descriptor) {
179
            Object t = toReturn;
180
            toReturn = null;
181
            assertNotNull("There is something to return", t);
182
            lastDescriptor = descriptor;
183
            return t;
184
        }
185
186
        public Dialog createDialog(DialogDescriptor descriptor) {
187
            return (Dialog)notify(descriptor);
188
        }
189
    } // end of DD
190
191
    public static final class Lkp extends AbstractLookup {
192
        public static InstanceContent IC;
193
194
        public Lkp() {
195
            this(new InstanceContent());
196
        }
197
        private Lkp(InstanceContent ic) {
198
            super(ic);
199
            ic.add(new DD());
200
            ic.add(new NbErrorManager());
201
        }
202
    }
203
204
    private static final class HiddenDialog extends JDialog {
205
        private boolean v;
206
207
        public HiddenDialog() {
208
        }
209
210
        public HiddenDialog(Frame p, boolean b) {
211
            super(p, b);
212
        }
60
213
61
        modalDialog.show();
214
        public void setVisible(boolean b) {
62
        
215
            v = b;
63
        assertFalse( "Error dialog is not modal", errorDialogIsModal );
216
        }
217
        public boolean isVisible() {
218
            return v;
219
        }
64
    }
220
    }
65
}
221
}
(-)openide/dialogs/apichanges.xml (+18 lines)
Lines 17-22 Link Here
17
<apidef name="dialogs">Dialogs API</apidef>
17
<apidef name="dialogs">Dialogs API</apidef>
18
</apidefs>
18
</apidefs>
19
<changes>
19
<changes>
20
    <change id="notifyLater">
21
           <api name="dialogs"/>
22
           <summary>New method to asynchronously show messages</summary>
23
           <version major="7" minor="0"/>
24
           <date day="20" month="6" year="2006"/>
25
           <author login="jtulach"/>
26
           <compatibility addition="yes" binary="compatible" semantic="compatible" source="compatible" deprecation="no" deletion="no" modification="no"/>
27
           <description>
28
             Now it is simple to display a message box described by
29
             <a href="@TOP@/org/openide/NotifyDescriptor.html">NotifyDescriptor</a>
30
             asynchronously using
31
             <a href="@TOP@/org/openide/DialogDisplayer.html#notifyLater(org.openide.NotifyDescriptor)">
32
                 DialogDisplayer.notifyLater
33
             </a>.
34
           </description>
35
           <class package="org.openide" name="DialogDisplayer"/>
36
           <issue number="35067"/>
37
    </change>
20
    <change id="WizardDescriptor.AsynchronousInstantiatingIterator">
38
    <change id="WizardDescriptor.AsynchronousInstantiatingIterator">
21
           <api name="dialogs"/>
39
           <api name="dialogs"/>
22
           <summary>Interface <code>AsynchronousInstantiatingIterator</code> added</summary>
40
           <summary>Interface <code>AsynchronousInstantiatingIterator</code> added</summary>
(-)openide/dialogs/manifest.mf (-1 / +1 lines)
Lines 1-5 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.openide.dialogs
2
OpenIDE-Module: org.openide.dialogs
3
OpenIDE-Module-Specification-Version: 6.6
3
OpenIDE-Module-Specification-Version: 7.0
4
OpenIDE-Module-Localizing-Bundle: org/openide/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/openide/Bundle.properties
5
5
(-)openide/dialogs/src/org/openide/DialogDisplayer.java (+17 lines)
Lines 66-71 Link Here
66
     */
66
     */
67
    public abstract Object notify(NotifyDescriptor descriptor);
67
    public abstract Object notify(NotifyDescriptor descriptor);
68
68
69
    /** Notify the user of something in a message box, possibly with feedback,
70
     * this method method may be called
71
     * from any thread. The thread will return immediately and
72
     * the dialog will be shown <q>later</q>, usually when AWT thread
73
     * is empty and can handle the request.
74
     *
75
     * @param descriptor description of the notification
76
     * @since 7.0
77
     */
78
    public void notifyLater(final NotifyDescriptor descriptor) {
79
        SwingUtilities.invokeLater(new Runnable() {
80
            public void run() {
81
                DialogDisplayer.this.notify(descriptor);
82
            }
83
        });
84
    }
85
69
    /** Get a new standard dialog.
86
    /** Get a new standard dialog.
70
     * The dialog is designed and created as specified in the parameter.
87
     * The dialog is designed and created as specified in the parameter.
71
     * Anyone who wants a dialog with standard buttons and
88
     * Anyone who wants a dialog with standard buttons and
(-)openide/dialogs/src/org/openide/NotifyDescriptor.java (-2 / +3 lines)
Lines 766-773 Link Here
766
766
767
    /**
767
    /**
768
    * Provides a description of an exception that occurred during
768
    * Provides a description of an exception that occurred during
769
    * execution of the IDE.
769
    * execution of the IDE. The best is to use this class together with
770
    * @deprecated Better to use {@link org.openide.ErrorManager#notify}
770
    * {@link DialogDisplayer#notifyLater} as that allows an exception
771
    * to be notified from any thread.
771
    */
772
    */
772
    public static final class Exception extends Confirmation {
773
    public static final class Exception extends Confirmation {
773
        static final long serialVersionUID = -3387516993124229948L;
774
        static final long serialVersionUID = -3387516993124229948L;
(-)openide/util/src/org/openide/ErrorManager.java (-19 / +103 lines)
Lines 13-24 Link Here
13
13
14
package org.openide;
14
package org.openide;
15
15
16
import java.io.IOException;
17
import java.io.PrintStream;
18
import java.io.PrintWriter;
19
import java.io.StringWriter;
20
import java.util.ArrayList;
16
import java.util.Collection;
21
import java.util.Collection;
17
import java.util.Enumeration;
22
import java.util.Enumeration;
18
import java.util.HashSet;
23
import java.util.HashSet;
19
import java.util.Iterator;
24
import java.util.Iterator;
25
import java.util.List;
20
import java.util.ResourceBundle;
26
import java.util.ResourceBundle;
21
import java.util.Set;
27
import java.util.Set;
28
import java.util.concurrent.Callable;
29
import java.util.logging.Formatter;
22
import java.util.logging.Level;
30
import java.util.logging.Level;
23
import java.util.logging.LogRecord;
31
import java.util.logging.LogRecord;
24
import java.util.logging.Logger;
32
import java.util.logging.Logger;
Lines 214-219 Link Here
214
 * </dl>
222
 * </dl>
215
 * </div>
223
 * </div>
216
 * @author Jaroslav Tulach, Jesse Glick
224
 * @author Jaroslav Tulach, Jesse Glick
225
 * @deprecated
217
 */
226
 */
218
public abstract class ErrorManager extends Object {
227
public abstract class ErrorManager extends Object {
219
    // XXX note that these levels accidentally used hex rather than binary,
228
    // XXX note that these levels accidentally used hex rather than binary,
Lines 611-625 Link Here
611
                        }
620
                        }
612
                    };
621
                    };
613
                    rec.setResourceBundle(rb);
622
                    rec.setResourceBundle(rb);
614
                    rec.setResourceBundleName("msg"); // NOI18N
623
                    rec.setMessage("msg"); // NOI18N
615
                }
624
                }
616
                
625
                
617
                Throwable last = t;
626
                AnnException ann = AnnException.findOrCreate(t, true);
618
                while (last.getCause() != null) {
627
                ann.addRecord(rec);
619
                    last = last.getCause();
620
                }
621
                
622
                last.initCause(new LogException(rec));
623
                
628
                
624
                return t;
629
                return t;
625
            }
630
            }
Lines 635-643 Link Here
635
        /** Calls all delegates. */
640
        /** Calls all delegates. */
636
        public void notify(int severity, Throwable t) {
641
        public void notify(int severity, Throwable t) {
637
            if (delegates.isEmpty()) {
642
            if (delegates.isEmpty()) {
643
                if (enterLogger()) return;
638
                try {
644
                try {
639
                    if (enterLogger()) return;
645
                    logger().log(convertSeverity(severity, true, OwnLevel.UNKNOWN), t.getMessage(), t);
640
                    logger().log(convertSeverity(severity, true, Level.SEVERE), t.getMessage(), t);
641
                } finally {
646
                } finally {
642
                    exitLogger();
647
                    exitLogger();
643
                }
648
                }
Lines 668-675 Link Here
668
673
669
            if (delegates.isEmpty()) {
674
            if (delegates.isEmpty()) {
670
                Level sev = convertSeverity(severity, false, Level.FINE);
675
                Level sev = convertSeverity(severity, false, Level.FINE);
676
                if (enterLogger()) return;
671
                try {
677
                try {
672
                    if (enterLogger()) return;
673
                    logger().log(sev, s);
678
                    logger().log(sev, s);
674
                } finally {
679
                } finally {
675
                    exitLogger();
680
                    exitLogger();
Lines 691-697 Link Here
691
            } else if (severity >= EXCEPTION) {
696
            } else if (severity >= EXCEPTION) {
692
                sev = Level.SEVERE;
697
                sev = Level.SEVERE;
693
            } else if (severity >= USER) {
698
            } else if (severity >= USER) {
694
                sev = Level.INFO;
699
                sev = OwnLevel.USER;
695
            } else if (severity >= WARNING) {
700
            } else if (severity >= WARNING) {
696
                sev = Level.WARNING;
701
                sev = Level.WARNING;
697
            } else if (severity >= INFORMATIONAL) {
702
            } else if (severity >= INFORMATIONAL) {
Lines 811-825 Link Here
811
    /** An exception that has a log record associated with itself, so
816
    /** An exception that has a log record associated with itself, so
812
     * the NbErrorManager can extract info about the annotation.
817
     * the NbErrorManager can extract info about the annotation.
813
     */
818
     */
814
    private static final class LogException extends Exception implements Lookup.Provider {
819
    private static final class AnnException extends Exception implements Callable<LogRecord[]> {
815
        private Lookup lookup;
820
        private List<LogRecord> records;
816
        
821
817
        public LogException(LogRecord rec) {
822
        public String getMessage() {
818
            this.lookup = Lookups.singleton(rec);
823
            StringBuilder sb = new StringBuilder();
824
            String sep = "";
825
            for (LogRecord r : records) {
826
                if (r.getMessage() != null) {
827
                    sb.append(sep);
828
                    sb.append(r.getMessage());
829
                    sep = "\n";
830
                }
831
            }
832
            return sb.toString();
819
        }
833
        }
820
834
821
        public Lookup getLookup() {
835
        static AnnException findOrCreate(Throwable t, boolean create) {
822
            return this.lookup;
836
            if (t instanceof AnnException) {
837
                return (AnnException)t;
838
            }
839
            if (t.getCause() == null) {
840
                if (create) {
841
                    t.initCause(new AnnException());
842
                }
843
                return (AnnException)t.getCause();
844
            }
845
            return findOrCreate(t.getCause(), create);
846
        }
847
848
        private AnnException() {
849
        }
850
851
        public synchronized void addRecord(LogRecord rec) {
852
            if (records == null) {
853
                records = new ArrayList<LogRecord>();
854
            }
855
            records.add(rec);
856
        }
857
858
        public LogRecord[] call() {
859
            List<LogRecord> r = records;
860
            LogRecord[] empty = new LogRecord[0];
861
            return r == null ? empty : r.toArray(empty);
862
        }
863
864
        public void printStackTrace(PrintStream s) {
865
            super.printStackTrace(s);
866
            logRecords(s);
867
        }
868
869
        public void printStackTrace(PrintWriter s) {
870
            super.printStackTrace(s);
871
            logRecords(s);
872
        }
873
874
        public void printStackTrace() {
875
            printStackTrace(System.err);
876
        }
877
878
        private void logRecords(Appendable a) {
879
            List<LogRecord> r = records;
880
            if (r == null) {
881
                return;
882
            }
883
            try {
884
885
                for (LogRecord log : r) {
886
                    if (log.getMessage() != null) {
887
                        a.append(log.getMessage()).append("\n");;
888
                    }
889
                    if (log.getThrown() != null) {
890
                        StringWriter w = new StringWriter();
891
                        log.getThrown().printStackTrace(new PrintWriter(w));
892
                        a.append(w.toString()).append("\n");
893
                    }
894
                }
895
            } catch (IOException ex) {
896
                ex.printStackTrace();
897
            }
898
        }
899
    } // end AnnException
900
901
    private static final class OwnLevel extends Level {
902
        public static final Level USER = new OwnLevel("USER", 1973); // NOI18N
903
        public static final Level UNKNOWN = new OwnLevel("SEVERE", Level.SEVERE.intValue() + 1); // NOI18N
904
905
        private OwnLevel(String s, int i) {
906
            super(s, i);
823
        }
907
        }
824
    } // end LogException
908
    } // end of UserLevel
825
}
909
}
(-)openide/util/src/org/openide/util/Exceptions.java (+197 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
package org.openide.util;
14
15
import java.io.IOException;
16
import java.io.PrintStream;
17
import java.io.PrintWriter;
18
import java.io.StringWriter;
19
import java.text.MessageFormat;
20
import java.util.ArrayList;
21
import java.util.Enumeration;
22
import java.util.List;
23
import java.util.ResourceBundle;
24
import java.util.concurrent.Callable;
25
import java.util.logging.Level;
26
import java.util.logging.LogRecord;
27
import java.util.logging.Logger;
28
29
30
/** Useful utility and methods to work with exceptions.
31
 *
32
 * @since JST-PENDING
33
 */
34
public final class Exceptions extends Object {
35
    private Exceptions() {
36
    }
37
38
39
    public static <E extends Throwable> E attachMessage(E e, String msg) {
40
        AnnException ae = AnnException.findOrCreate(e, true);
41
        LogRecord rec = new LogRecord(Level.ALL, msg);
42
        ae.addRecord(rec);
43
        return e;
44
    }
45
46
    public static <E extends Throwable> E attachLocalizedMessage(E e, final String localizedMessage) {
47
        AnnException ae = AnnException.findOrCreate(e, true);
48
        LogRecord rec = new LogRecord(Level.ALL, "msg"); // NOI18N
49
        ResourceBundle rb = new ResourceBundle() {
50
            public Object handleGetObject(String key) {
51
                if ("msg".equals(key)) { // NOI18N
52
                    return localizedMessage;
53
                } else {
54
                    return null;
55
                }
56
            }
57
58
            public Enumeration<String> getKeys() {
59
                return Enumerations.singleton("msg"); // NOI18N
60
            }
61
        };
62
        rec.setResourceBundle(rb);
63
        ae.addRecord(rec);
64
        return e;
65
    }
66
67
    /** Extracts previously attached localized message for a given throwable.
68
     * Complements the {@link Exceptions.attachLocalizedMessage} method.
69
     *
70
     * @param t the exception to search for a message in
71
     * @return localized message attached to provided exception or <code>null</code>
72
     *   if no such message has been attached
73
     */
74
    public static String findLocalizedMessage(Throwable t) {
75
        while (t != null) {
76
            if (t instanceof Callable) {
77
                Object res = null;
78
                try {
79
                    res = ((Callable) t).call();
80
                } catch (Exception ex) {
81
                    Logger.global.log(Level.WARNING, null, t);
82
                }
83
                if (res instanceof LogRecord[]) {
84
                    for (LogRecord r : (LogRecord[])res) {
85
                        ResourceBundle b = r.getResourceBundle();
86
                        if (b != null) {
87
                            String msg = b.getString(r.getMessage());
88
                            return msg;
89
                        }
90
                    }
91
                }
92
            }
93
            t = t.getCause();
94
        }
95
        return null;
96
    }
97
    
98
    /** Notifies an exception with a severe level.
99
     * JST-PENDING: improve the doc and maybe change the name
100
     */
101
    public static void printStackTrace(Throwable t) {
102
        Logger.global.log(OwnLevel.UNKNOWN, null, t);
103
    }
104
105
106
    /** An exception that has a log record associated with itself, so
107
     * the NbErrorManager can extract info about the annotation.
108
     */
109
    private static final class AnnException extends Exception implements Callable<LogRecord[]> {
110
        private List<LogRecord> records;
111
112
        public String getMessage() {
113
            StringBuilder sb = new StringBuilder();
114
            String sep = "";
115
            for (LogRecord r : records) {
116
                if (r.getMessage() != null) {
117
                    sb.append(sep);
118
                    sb.append(r.getMessage());
119
                    sep = "\n";
120
                }
121
            }
122
            return sb.toString();
123
        }
124
125
        static AnnException findOrCreate(Throwable t, boolean create) {
126
            if (t instanceof AnnException) {
127
                return (AnnException)t;
128
            }
129
            if (t.getCause() == null) {
130
                if (create) {
131
                    t.initCause(new AnnException());
132
                }
133
                return (AnnException)t.getCause();
134
            }
135
            return findOrCreate(t.getCause(), create);
136
        }
137
138
        private AnnException() {
139
        }
140
141
        public synchronized void addRecord(LogRecord rec) {
142
            if (records == null) {
143
                records = new ArrayList<LogRecord>();
144
            }
145
            records.add(rec);
146
        }
147
148
        public LogRecord[] call() {
149
            List<LogRecord> r = records;
150
            LogRecord[] empty = new LogRecord[0];
151
            return r == null ? empty : r.toArray(empty);
152
        }
153
154
        public void printStackTrace(PrintStream s) {
155
            super.printStackTrace(s);
156
            logRecords(s);
157
        }
158
159
        public void printStackTrace(PrintWriter s) {
160
            super.printStackTrace(s);
161
            logRecords(s);
162
        }
163
164
        public void printStackTrace() {
165
            printStackTrace(System.err);
166
        }
167
168
        private void logRecords(Appendable a) {
169
            List<LogRecord> r = records;
170
            if (r == null) {
171
                return;
172
            }
173
            try {
174
175
                for (LogRecord log : r) {
176
                    if (log.getMessage() != null) {
177
                        a.append(log.getMessage()).append("\n");;
178
                    }
179
                    if (log.getThrown() != null) {
180
                        StringWriter w = new StringWriter();
181
                        log.getThrown().printStackTrace(new PrintWriter(w));
182
                        a.append(w.toString()).append("\n");
183
                    }
184
                }
185
            } catch (IOException ex) {
186
                ex.printStackTrace();
187
            }
188
        }
189
    } // end AnnException
190
    private static final class OwnLevel extends Level {
191
        public static final Level UNKNOWN = new OwnLevel("SEVERE", Level.SEVERE.intValue() + 1); // NOI18N
192
193
        private OwnLevel(String s, int i) {
194
            super(s, i);
195
        }
196
    } // end of OwnLevel
197
}
(-)openide/util/test/unit/src/org/openide/ErrorManagerDelegatesToLoggingTest.java (-10 / +42 lines)
Lines 14-20 Link Here
14
package org.openide;
14
package org.openide;
15
15
16
import java.io.IOException;
16
import java.io.IOException;
17
import java.io.PrintWriter;
17
import java.io.StringBufferInputStream;
18
import java.io.StringBufferInputStream;
19
import java.io.StringWriter;
18
import java.util.logging.Handler;
20
import java.util.logging.Handler;
19
import java.util.logging.Level;
21
import java.util.logging.Level;
20
import java.util.logging.LogManager;
22
import java.util.logging.LogManager;
Lines 86-91 Link Here
86
        assertEquals ("attachAnnotations must return the same exception", t, value);
88
        assertEquals ("attachAnnotations must return the same exception", t, value);
87
        
89
        
88
    }
90
    }
91
92
    public void testThatWeNotifyAnException() throws Exception {
93
        Throwable t = new NullPointerException("npe");
94
        Throwable v = new ClassNotFoundException("cnf", t);
95
96
        Throwable a = new IOException();
97
        ErrorManager.getDefault().annotate(a, v);
98
        ErrorManager.getDefault().notify(a);
99
100
        assertEquals("Last throwable is a", a, MyHandler.lastThrowable);
101
        assertNotNull("And it has a cause", MyHandler.lastThrowable.getCause());
102
103
        StringWriter w = new StringWriter();
104
        MyHandler.lastThrowable.getCause().printStackTrace(new PrintWriter(w));
105
        String msg = w.toString();
106
107
        if (msg.indexOf("npe") == -1) fail("there should be npe: " + msg);
108
        if (msg.indexOf("cnf") == -1) fail("there should be cnf: " + msg);
109
110
    }
111
112
    public void testAnnotatedMessagesShallBePresentInPrintStackTrace() throws Exception {
113
        Throwable t = new NullPointerException("npe");
114
115
        ErrorManager.getDefault().annotate(t, ErrorManager.UNKNOWN, "Ahoj Null!", null, null, null);
116
117
        StringWriter w = new StringWriter();
118
        t.printStackTrace(new PrintWriter(w));
119
        String msg = w.toString();
120
121
        if (msg.indexOf("npe") == -1) fail("there should be npe: " + msg);
122
        if (msg.indexOf("Ahoj Null") == -1) fail("there should be Ahoj Null: " + msg);
123
124
    }
89
    
125
    
90
    //
126
    //
91
    // Manager to delegate to
127
    // Manager to delegate to
Lines 118-137 Link Here
118
            
154
            
119
            lastText = record.getMessage();
155
            lastText = record.getMessage();
120
            lastThrowable = record.getThrown();
156
            lastThrowable = record.getThrown();
121
            if (Level.WARNING == record.getLevel()) {
157
122
                lastSeverity = ErrorManager.WARNING;
158
            Level l = record.getLevel();
123
            }
159
            if (l.intValue() >= Level.FINEST.intValue()) {
124
            if (Level.INFO == record.getLevel()) {
125
                lastSeverity = ErrorManager.INFORMATIONAL;
160
                lastSeverity = ErrorManager.INFORMATIONAL;
126
            }
161
            }
127
            if (Level.CONFIG == record.getLevel()) {
162
            if (l.intValue() >= Level.WARNING.intValue()) {
128
                lastSeverity = ErrorManager.INFORMATIONAL;
163
                lastSeverity = ErrorManager.WARNING;
129
            }
164
            }
130
            if (Level.SEVERE == record.getLevel()) {
165
            if (l.intValue() >= Level.SEVERE.intValue()) {
131
                lastSeverity = ErrorManager.EXCEPTION;
166
                lastSeverity = ErrorManager.EXCEPTION;
132
            }
133
            if (Level.FINE == record.getLevel()) {
134
                lastSeverity = ErrorManager.INFORMATIONAL;
135
            }
167
            }
136
        }
168
        }
137
169
(-)openide/util/test/unit/src/org/openide/util/ExceptionsTest.java (+68 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.openide.util;
15
16
import java.io.PrintWriter;
17
import java.io.StringWriter;
18
import junit.framework.TestCase;
19
import junit.framework.*;
20
21
/**
22
 *
23
 * @author Jaroslav Tulach
24
 */
25
public class ExceptionsTest extends TestCase {
26
    
27
    public ExceptionsTest(String testName) {
28
        super(testName);
29
    }
30
31
    protected void setUp() throws Exception {
32
    }
33
34
    protected void tearDown() throws Exception {
35
    }
36
37
    public void testAttachMessage() {
38
        Exception e = new Exception("Help");
39
        String msg = "me please";
40
        
41
        Exception result = Exceptions.attachMessage(e, msg);
42
43
        assertSame(result, e);
44
45
        StringWriter w = new StringWriter();
46
        result.printStackTrace(new PrintWriter(w));
47
48
        String m = w.toString();
49
50
        if (m.indexOf(msg) == -1) {
51
            fail(msg + " shall be part of output:\n" + m);
52
        }
53
    }
54
55
    public void testAttachLocalizedMessage() {
56
        Exception e = new Exception("Help");
57
        String msg = "me please";
58
        
59
        Exception expResult = e;
60
        Exception result = Exceptions.attachLocalizedMessage(e, msg);
61
        assertEquals(expResult, result);
62
63
        String fnd = Exceptions.findLocalizedMessage(e);
64
65
        assertEquals("The same msg", msg, fnd);
66
    }
67
    
68
}

Return to bug 35067