KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > NbErrorManager


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.core;
21
22 import java.io.OutputStreamWriter JavaDoc;
23 import java.io.PrintStream JavaDoc;
24 import java.io.PrintWriter JavaDoc;
25 import java.io.StringWriter JavaDoc;
26 import java.text.MessageFormat JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Arrays JavaDoc;
29 import java.util.Date JavaDoc;
30 import java.util.HashSet JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.ResourceBundle JavaDoc;
34 import java.util.Set JavaDoc;
35 import java.util.concurrent.Callable JavaDoc;
36 import java.util.logging.Handler JavaDoc;
37 import java.util.logging.Level JavaDoc;
38 import java.util.logging.LogRecord JavaDoc;
39 import java.util.logging.Logger JavaDoc;
40
41 /** Wraps errormanager with logger.
42  *
43  * @author Jaroslav Tulach, Jesse Glick
44  */

45 public final class NbErrorManager extends Handler JavaDoc {
46     
47     static Exc createExc(Throwable JavaDoc t, Level JavaDoc severity, LogRecord JavaDoc add) {
48         LogRecord JavaDoc[] ann = findAnnotations(t, add);
49         return new Exc(t, severity, ann, findAnnotations0(t, add, true, new HashSet JavaDoc<Throwable JavaDoc>()));
50     }
51
52     public void publish(LogRecord JavaDoc record) {
53         if (record.getThrown() != null) {
54             Level JavaDoc level = record.getLevel();
55             if (level.intValue() == Level.WARNING.intValue() + 1) {
56                 // unknown level
57
level = null;
58             }
59             if (level != null && level.intValue() == Level.SEVERE.intValue() + 1) {
60                 // unknown level
61
level = null;
62             }
63             Exc ex = createExc(record.getThrown(), level, record.getLevel().intValue() == 1973 ? record : null);
64             NotifyExcPanel.notify(ex);
65         }
66     }
67     
68     public void flush() {
69         //logWriter.flush();
70
}
71     
72     public void close() throws SecurityException JavaDoc {
73         // nothing needed
74
}
75     
76     /** Extracts localized message from a LogRecord */
77     private static final String JavaDoc getLocalizedMessage(LogRecord JavaDoc rec) {
78         ResourceBundle JavaDoc rb = rec.getResourceBundle();
79         if (rb == null) {
80             return null;
81         }
82         
83         String JavaDoc msg = rec.getMessage();
84         if (msg == null) {
85             return null;
86         }
87         
88         String JavaDoc format = rb.getString(msg);
89
90         Object JavaDoc[] arr = rec.getParameters();
91         if (arr == null) {
92             return format;
93         }
94
95         return MessageFormat.format(format, arr);
96     }
97
98     /** Finds annotations associated with given exception.
99      * @param t the exception
100      * @return array of annotations or null
101      */

102     private static LogRecord JavaDoc[] findAnnotations(Throwable JavaDoc t, LogRecord JavaDoc add) {
103         return findAnnotations0(t, add, false, new HashSet JavaDoc<Throwable JavaDoc>());
104     }
105     
106     /** If recursively is true it is not adviced to print all annotations
107      * because a lot of warnings will be printed. But while searching for
108      * localized message we should scan all the annotations (even recursively).
109      */

110     private static LogRecord JavaDoc[] findAnnotations0(Throwable JavaDoc t, LogRecord JavaDoc add, boolean recursively, Set JavaDoc<Throwable JavaDoc> alreadyVisited) {
111         List JavaDoc<LogRecord JavaDoc> l = new ArrayList JavaDoc<LogRecord JavaDoc>();
112         Throwable JavaDoc collect = t;
113         while (collect != null) {
114             if (collect instanceof Callable JavaDoc) {
115                 Object JavaDoc res = null;
116                 try {
117                     res = ((Callable JavaDoc) collect).call();
118                 } catch (Exception JavaDoc ex) {
119                     ex.printStackTrace();
120                 }
121                 if (res instanceof LogRecord JavaDoc[]) {
122                     LogRecord JavaDoc[] arr = (LogRecord JavaDoc[])res;
123                     l.addAll(Arrays.asList(arr));
124                 }
125             }
126             collect = collect.getCause();
127         }
128
129         if (add != null) {
130             l.add(add);
131         }
132
133         
134         if (recursively) {
135             ArrayList JavaDoc<LogRecord JavaDoc> al = new ArrayList JavaDoc<LogRecord JavaDoc>();
136             for (Iterator JavaDoc<LogRecord JavaDoc> i = l.iterator(); i.hasNext(); ) {
137                 LogRecord JavaDoc ano = i.next();
138                 Throwable JavaDoc t1 = ano.getThrown();
139                 if ((t1 != null) && (! alreadyVisited.contains(t1))) {
140                     alreadyVisited.add(t1);
141                     LogRecord JavaDoc[] tmpAnnoArray = findAnnotations0(t1, null, true, alreadyVisited);
142                     if ((tmpAnnoArray != null) && (tmpAnnoArray.length > 0)) {
143                         al.addAll(Arrays.asList(tmpAnnoArray));
144                     }
145                 }
146             }
147             l.addAll(al);
148         }
149
150         Throwable JavaDoc cause = t.getCause();
151         if (cause != null) {
152             LogRecord JavaDoc[] extras = findAnnotations0(cause, null, true, alreadyVisited);
153             if (extras != null && extras.length > 0) {
154                 l.addAll(Arrays.asList(extras));
155             }
156         }
157         
158         LogRecord JavaDoc[] arr;
159         arr = new LogRecord JavaDoc[l.size()];
160         l.toArray(arr);
161         
162         return arr;
163     }
164     
165     /**
166      * Another final class that is used to communicate with
167      * NotifyExcPanel and provides enough information to the dialog.
168      */

169     static final class Exc {
170         /** the original throwable */
171         private Throwable JavaDoc t;
172         private Date JavaDoc d;
173         private LogRecord JavaDoc[] arr;
174         private LogRecord JavaDoc[] arrAll; // all - recursively
175
private Level JavaDoc severity;
176         
177         /** @param severity if -1 then we will compute the
178          * severity from annotations
179          */

180         Exc(Throwable JavaDoc t, Level JavaDoc severity, LogRecord JavaDoc[] arr, LogRecord JavaDoc[] arrAll) {
181             this.t = t;
182             this.severity = severity;
183             this.arr = arr == null ? new LogRecord JavaDoc[0] : arr;
184             this.arrAll = arrAll == null ? new LogRecord JavaDoc[0] : arrAll;
185         }
186         
187         /** @return message */
188         String JavaDoc getMessage() {
189             String JavaDoc m = t.getMessage();
190             if (m != null) {
191                 return m;
192             }
193             return (String JavaDoc)find(1);
194         }
195         
196         /** @return localized message */
197         String JavaDoc getLocalizedMessage() {
198             String JavaDoc m = t.getLocalizedMessage();
199             if (m != null && !m.equals(t.getMessage())) {
200                 return m;
201             }
202             if (arrAll == null) {
203                 // arrAll not filled --> use the old non recursive variant
204
return (String JavaDoc)find(2);
205             }
206             for (int i = 0; i < arrAll.length; i++) {
207                 String JavaDoc s = NbErrorManager.getLocalizedMessage(arrAll[i]);
208                 if (s != null) {
209                     return s;
210                 }
211             }
212             return m;
213         }
214         
215         boolean isLocalized() {
216             String JavaDoc m = t.getLocalizedMessage();
217             if (m != null && !m.equals(t.getMessage())) {
218                 return true;
219             }
220             if (arrAll == null) {
221                 // arrAll not filled --> use the old non recursive variant
222
return (String JavaDoc)find(2) != null;
223             }
224             for (int i = 0; i < arrAll.length; i++) {
225                 String JavaDoc s = NbErrorManager.getLocalizedMessage(arrAll[i]);
226                 if (s != null) {
227                     return true;
228                 }
229             }
230             return false;
231         }
232         
233         /** @return class name of the exception */
234         String JavaDoc getClassName() {
235             return (String JavaDoc)find(3);
236         }
237         
238         /** @return the severity of the exception */
239         Level JavaDoc getSeverity() {
240             if (severity != null) {
241                 return severity;
242             }
243             
244             LogRecord JavaDoc[] anns = (arrAll != null) ? arrAll : arr;
245             for (int i = 0; i < anns.length; i++) {
246                 Level JavaDoc s = anns[i].getLevel();
247                 if (severity == null || s.intValue() > severity.intValue()) {
248                     severity = s;
249                 }
250             }
251             
252             if (severity == null || severity == Level.ALL) {
253                 // no severity specified, assume this is an error
254
severity = t instanceof Error JavaDoc ? Level.SEVERE : Level.WARNING;
255             }
256             
257             return severity;
258         }
259         
260         /** @return date assigned to the exception */
261         Date JavaDoc getDate() {
262             if (d == null) {
263                 d = (Date JavaDoc)find(4);
264             }
265             return d;
266         }
267         
268         void printStackTrace(PrintStream JavaDoc ps) {
269             printStackTrace(new PrintWriter JavaDoc(new OutputStreamWriter JavaDoc(ps)));
270         }
271         /** Prints stack trace of all annotations and if
272          * there is no annotation trace then of the exception
273          */

274         void printStackTrace(PrintWriter JavaDoc pw) {
275             // #19487: don't go into an endless loop here
276
printStackTrace(pw, new HashSet JavaDoc<Throwable JavaDoc>(10));
277         }
278         
279         private void printStackTrace(PrintWriter JavaDoc pw, Set JavaDoc<Throwable JavaDoc> nestingCheck) {
280             if (t != null && !nestingCheck.add(t)) {
281                 // Unlocalized log message - this is for developers of NB, not users
282
Logger JavaDoc l = Logger.getAnonymousLogger();
283                 l.warning("WARNING - ErrorManager detected cyclic exception nesting:"); // NOI18N
284
Iterator JavaDoc it = nestingCheck.iterator();
285                 while (it.hasNext()) {
286                     Throwable JavaDoc t = (Throwable JavaDoc)it.next();
287                     l.warning("\t" + t); // NOI18N
288
LogRecord JavaDoc[] anns = findAnnotations(t, null);
289                     if (anns != null) {
290                         for (int i = 0; i < anns.length; i++) {
291                             Throwable JavaDoc t2 = anns[i].getThrown();
292                             if (t2 != null) {
293                                 l.warning("\t=> " + t2); // NOI18N
294
}
295                         }
296                     }
297                 }
298                 l.warning("Be sure not to annotate an exception with itself, directly or indirectly."); // NOI18N
299
return;
300             }
301             /*Heaeder
302             pw.print (getDate ());
303             pw.print (": "); // NOI18N
304             pw.print (getClassName ());
305             pw.print (": "); // NOI18N
306             String theMessage = getMessage();
307             if (theMessage != null) {
308                 pw.print(theMessage);
309             } else {
310                 pw.print("<no message>"); // NOI18N
311             }
312             pw.println ();
313              */

314             /*Annotations */
315             for (int i = 0; i < arr.length; i++) {
316                 if (arr[i] == null) continue;
317                 
318                 Throwable JavaDoc thr = arr[i].getThrown();
319                 String JavaDoc annotation = NbErrorManager.getLocalizedMessage(arr[i]);
320                 
321                 if (annotation == null) annotation = arr[i].getMessage();
322                 /*
323                 if (annotation == null && thr != null) annotation = thr.getLocalizedMessage();
324                 if (annotation == null && thr != null) annotation = thr.getMessage();
325                  */

326                 
327                 if (annotation != null) {
328                     if (thr == null) {
329                         pw.println("Annotation: "+annotation);// NOI18N
330
}
331                     //else pw.println ("Nested annotation: "+annotation);// NOI18N
332
}
333             }
334             
335             // ok, print trace of the original exception too
336
// Attempt to show an annotation indicating where the exception
337
// was caught. Not 100% reliable but often helpful.
338
if (t instanceof VirtualMachineError JavaDoc) {
339                 // Decomposition may not work here, e.g. for StackOverflowError.
340
// Play it safe.
341
t.printStackTrace(pw);
342             } else {
343                 // All other kinds of throwables we check for a stack trace.
344
// First try to find where the throwable was caught.
345
StackTraceElement JavaDoc[] tStack = t.getStackTrace();
346                 StackTraceElement JavaDoc[] hereStack = new Throwable JavaDoc().getStackTrace();
347                 int idx = -1;
348                 for (int i = 1; i <= Math.min(tStack.length, hereStack.length); i++) {
349                     if (!tStack[tStack.length - i].equals(hereStack[hereStack.length - i])) {
350                         idx = tStack.length - i + 1;
351                         break;
352                     }
353                 }
354                 String JavaDoc[] tLines = decompose(t);
355                 for (int i = 0; i < tLines.length; i++) {
356                     if (i == idx) {
357                         pw.print("[catch]"); // NOI18N
358
// Also translate following tab -> space since formatting is bad in
359
// Output Window (#8104) and some mail agents screw it up etc.
360
if (tLines[i].charAt(0) == '\t') {
361                             pw.print(' ');
362                             tLines[i] = tLines[i].substring(1);
363                         }
364                     }
365                     pw.println(tLines[i]);
366                 }
367             }
368             /*Nested annotations */
369             for (int i = 0; i < arr.length; i++) {
370                 if (arr[i] == null) continue;
371                 
372                 Throwable JavaDoc thr = arr[i].getThrown();
373                 if (thr != null) {
374                     LogRecord JavaDoc[] ans = findAnnotations(thr, null);
375                     Exc ex = new Exc(thr, null, ans, null);
376                     pw.println("==>"); // NOI18N
377
ex.printStackTrace(pw, nestingCheck);
378                 }
379             }
380         }
381         
382         /** Get a throwable's stack trace, decomposed into individual lines. */
383         private String JavaDoc[] decompose(Throwable JavaDoc t) {
384             StringWriter JavaDoc sw = new StringWriter JavaDoc();
385             t.printStackTrace(new PrintWriter JavaDoc(sw));
386             return sw.toString().split("(\r\n?|\n)($|(?=\\s*at ))"); // NOI18N
387
}
388         
389         /**
390          * Method that iterates over annotations to find out
391          * the first annotation that brings the requested value.
392          *
393          * @param kind what to look for (1, 2, 3, 4, ...);
394          * @return the found object
395          */

396         private Object JavaDoc find(int kind) {
397             return find(kind, true);
398         }
399         
400         /**
401          * Method that iterates over annotations to find out
402          * the first annotation that brings the requested value.
403          *
404          * @param kind what to look for (1, 2, 3, 4, ...);
405          * @return the found object
406          */

407         private Object JavaDoc find(int kind, boolean def) {
408             for (int i = 0; i < arr.length; i++) {
409                 LogRecord JavaDoc a = arr[i];
410                 
411                 Object JavaDoc o = null;
412                 switch (kind) {
413                     case 1: // message
414
o = a.getMessage(); break;
415                     case 2: // localized
416
o = NbErrorManager.getLocalizedMessage(a); break;
417                     case 3: // class name
418
{
419                         Throwable JavaDoc t = a.getThrown();
420                         o = t == null ? null : t.getClass().getName();
421                         break;
422                     }
423                     case 4: // date
424
o = new Date JavaDoc(a.getMillis()); break;
425                 }
426                 
427                 if (o != null) {
428                     return o;
429                 }
430             }
431             
432             if (!def)
433                 return null;
434             switch (kind) {
435                 case 1: // message
436
return t.getMessage();
437                 case 2: // loc.msg.
438
return t.getLocalizedMessage();
439                 case 3: // class name
440
return t.getClass().getName();
441                 case 4: // date
442
return new Date JavaDoc();
443                 default:
444                     throw new IllegalArgumentException JavaDoc(
445                         "Unknown " + Integer.valueOf(kind) // NOI18N
446
);
447             }
448         }
449     }
450     
451 }
452
Popular Tags