Source Code Cross Referenced for ErrorManager.java in  » IDE-Netbeans » openide » org » openide » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » openide » org.openide 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         *
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * The contents of this file are subject to the terms of either the GNU
007:         * General Public License Version 2 only ("GPL") or the Common
008:         * Development and Distribution License("CDDL") (collectively, the
009:         * "License"). You may not use this file except in compliance with the
010:         * License. You can obtain a copy of the License at
011:         * http://www.netbeans.org/cddl-gplv2.html
012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013:         * specific language governing permissions and limitations under the
014:         * License.  When distributing the software, include this License Header
015:         * Notice in each file and include the License file at
016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
017:         * particular file as subject to the "Classpath" exception as provided
018:         * by Sun in the GPL Version 2 section of the License file that
019:         * accompanied this code. If applicable, add the following below the
020:         * License Header, with the fields enclosed by brackets [] replaced by
021:         * your own identifying information:
022:         * "Portions Copyrighted [year] [name of copyright owner]"
023:         *
024:         * Contributor(s):
025:         *
026:         * The Original Software is NetBeans. The Initial Developer of the Original
027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028:         * Microsystems, Inc. All Rights Reserved.
029:         *
030:         * If you wish your version of this file to be governed by only the CDDL
031:         * or only the GPL Version 2, indicate your decision by adding
032:         * "[Contributor] elects to include this software in this distribution
033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
034:         * single choice of license, a recipient has the option to distribute
035:         * your version of this file under either the CDDL, the GPL Version 2 or
036:         * to extend the choice of license to its licensees as provided above.
037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
038:         * Version 2 license, then the option applies only if the new code is
039:         * made subject to such option by the copyright holder.
040:         */
041:
042:        package org.openide;
043:
044:        import java.io.IOException;
045:        import java.io.PrintStream;
046:        import java.io.PrintWriter;
047:        import java.io.StringWriter;
048:        import java.util.ArrayList;
049:        import java.util.Collection;
050:        import java.util.Enumeration;
051:        import java.util.HashSet;
052:        import java.util.LinkedHashSet;
053:        import java.util.List;
054:        import java.util.Map;
055:        import java.util.ResourceBundle;
056:        import java.util.Set;
057:        import java.util.WeakHashMap;
058:        import java.util.concurrent.Callable;
059:        import java.util.logging.Level;
060:        import java.util.logging.LogRecord;
061:        import java.util.logging.Logger;
062:        import org.openide.util.Enumerations;
063:        import org.openide.util.Lookup;
064:        import org.openide.util.LookupEvent;
065:        import org.openide.util.LookupListener;
066:        import org.openide.util.WeakSet;
067:
068:        /**
069:         * A more or less <em>deprecated</em> system of managing, annotating, and classifying errors
070:         *  and log messages. Instead of <code>ErrorManager</code> use
071:         * {@link Logger} as described in <a href="@TOP@/org/openide/util/doc-files/logging.html">NetBeans logging guide</a>.
072:         * <p>
073:         * Rather then using the {@link ErrorManager} consider using JDK's {@link Logger}
074:         * for reporting log events, unwanted exceptions, etc.  The methods
075:         * in this class which are deprecated are annotated with a description
076:         * how to use use the {@link Logger} methods to achieve the same goal.
077:         * </p>
078:         * <p>
079:         * The levels in descending order are:
080:         * <ul>
081:         * <li>ERROR (highest value)
082:         * <li>EXCEPTION
083:         * <li>USER
084:         * <li>WARNING
085:         * <li>INFORMATIONAL
086:         * <li>UNKNOWN (lowest value)
087:         * </ul>
088:         * </p>
089:         *
090:         * <div class="nonnormative">
091:         * <p>How to...</p>
092:         * <dl>
093:         *
094:         * <dt>Handle an exception</dt>
095:         * <dd>
096:         * <p>If it might be an important error (show the user):</p>
097:         * <pre>
098:         * try {
099:         *     foo.doSomething();
100:         * } catch (IOException ioe) {
101:         * <!--
102:         *     Logger.getLogger(YourClass.class.getName()).log(Level.SEVERE, "msg", ioe);
103:         *     // used to be
104:         * -->
105:         * ErrorManager.getDefault().notify(ioe);
106:         * <!--
107:         * }
108:         * -->
109:         * </pre>
110:         * <p>If it is not very important but should be sent to the log file:</p>
111:         * <pre>
112:         * try {
113:         *     foo.doSomething();
114:         * } catch (IOException ioe) {
115:         *     Logger.getLogger(YourClass.class.getName()).log(Level.CONFIG, "msg", ioe);
116:         *     // used to be:
117:         *     // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ioe);
118:         * }
119:         * </pre>
120:         * <p>If it is the normal outcome of a user action
121:         * and there is no need to show stack traces to the user:</p>
122:         * <pre>
123:         * try {
124:         *     foo.doSomething();
125:         * } catch (IOException ioe) {
126:         * <!--
127:         *     Logger.getAnonymousLogger().log(Level.INFO, "msg", ioe);
128:         *     // used to be:
129:         * -->
130:         *     ErrorManager.getDefault().notify(ErrorManager.USER, ioe);
131:         * }
132:         * </pre>
133:         * <p>You can also specify the severity when you are creating the
134:         * exception (by annotating it), rather than relying on the notifier
135:         * to do this. In that case, if the notifier just use the plain form
136:         * of <code>notify</code> (i.e. <code>UNKNOWN</code> severity), the
137:         * annotated severity is used.</p>
138:         * </dd>
139:         *
140:         * <dt>Retain nested stacktraces / change exception type</dt>
141:         * <dd>
142:         * <pre>
143:         * public void doSomething() throws IOException {
144:         *     try {
145:         *         doSomethingElse();
146:         *     } catch (IllegalArgumentException iae) {
147:         *         IOException ioe = new IOException("did not work: " + iae);
148:         *         ioe.initCause(iae);
149:         *         // used to be: ErrorManager.getDefault().annotate(ioe, iae);
150:         *         throw ioe;
151:         *     }
152:         * }
153:         * </pre>
154:         * <p>You can also just use JDK 1.4 causes:</p>
155:         * <pre>
156:         * public void doSomething() throws IOException {
157:         *     try {
158:         *         doSomethingElse();
159:         *     } catch (IllegalArgumentException iae) {
160:         *         IOException ioe = new IOException("did not work: " + iae);
161:         *         ioe.initCause(iae);
162:         *         throw ioe;
163:         *     }
164:         * }
165:         * // ...
166:         * try {
167:         *     foo.doSomething();
168:         * } catch (IOException ioe) {
169:         *     // The IllegalArgumentException is still available here:
170:         *     ErrorManager.getDefault().notify(ioe);
171:         *     // or use logging
172:         *     Logger.getLogger(YourClass.class.getName()).log(Level.SEVERE, null, ioe);
173:         * }
174:         * </pre>
175:         * </dd>
176:         *
177:         * <dt>Provide a user-visible (localized) message</dt>
178:         * <dd>
179:         * <pre>
180:         * public void doSomething(File f) throws IOException {
181:         *     if (!f.isFile()) {
182:         *         IOException e = new IOException("Not a file: " + f); // NOI18N
183:         *         // For what the user actually sees:
184:         *         ErrorManager.getDefault().annotate(e,
185:         *             NbBundle.getMessage(This.class, "EXC_not_a_file", f));
186:         *         throw e;
187:         *     }
188:         * }
189:         * </pre>
190:         * <p>You can also add the message when the exception is caught rather
191:         * than when it is thrown. You could even have one piece of code throw
192:         * an exception, another annotate it, and yet another notify it.
193:         * </dd>
194:         *
195:         * <dt>Collecting several exceptions and wrapping them in one</dt>
196:         * <dd>
197:         * <pre>
198:         * IOException all = null;
199:         * for (int i = 0; i &lt; things.length; i++) {
200:         *     try {
201:         *          things[i].process();
202:         *     } catch (ThingProcessingException e) {
203:         *          if (all == null) {
204:         *              all = new IOException("Could not process one or more things"); // NOI18N
205:         *          }
206:         *          ErrorManager.getDefault().annotate(all, e);
207:         *     }
208:         * }
209:         * if (all != null) {
210:         *     throw all;
211:         * }
212:         * </pre>
213:         * <dd>
214:         *
215:         * <dt>Logging a warning message just simply uses the JDK's logging API</dt>
216:         * <dd>
217:         * <pre>
218:         * public void doSomething(String arg) {
219:         *     if (arg.length() == 0) {
220:         *         Logger.getLogger(YourClass.class.getName()).log(Leverl.WARNING,
221:         *             "Warning: doSomething called on empty string");
222:         *         return;
223:         *     }
224:         *     // ...
225:         * }
226:         * </pre>
227:         * </dd>
228:         *
229:         * <dt>Logging messages for some subcomponent can be done easily with JDK's logging API</dt>
230:         * <dd>
231:         * <pre>
232:         * package org.netbeans.modules.foo;
233:         * class FooModule {
234:         *     public static final Logger ERR =
235:         *         Logger.getLogger("org.netbeans.modules.foo");
236:         * }
237:         * // ...
238:         * class Something {
239:         *     public void doSomething(String arg) {
240:         *         LogRecord rec = new LogRecord(Level.FINE, "MSG_Key");
241:         *         // where in the Bundle.properties one has:
242:         *         // MSG_Key=Called doSomething with arg {0}
243:         *         rec.setResourceBundle(NbBundle.getBundle(Something.class));
244:         *         rec.setParameters(new Object[] { arg });
245:         *         ERR.log(rec);
246:         *     }
247:         * }
248:         * </pre>
249:         * </dd>
250:         *
251:         * </dl>
252:         * </div>
253:         * @author Jaroslav Tulach, Jesse Glick
254:         */
255:        public abstract class ErrorManager extends Object {
256:            // XXX deprecate error manager after phase II and III are done. See:
257:            // http://openide.netbeans.org/tutorial/reviews/opinions_35067.html
258:
259:            /**
260:             * Undefined severity.
261:             * May be used only in {@link #notify(int, Throwable)}
262:             * and {@link #annotate(Throwable, int, String, String, Throwable, Date)}.
263:             */
264:            public static final int UNKNOWN = 0x00000000;
265:
266:            /** Message that would be useful for tracing events but which need not be a problem. */
267:            public static final int INFORMATIONAL = 0x00000001;
268:
269:            /** Something went wrong in the software, but it is continuing and the user need not be bothered. */
270:            public static final int WARNING = 0x00000010;
271:
272:            /** Something the user should be aware of. */
273:            public static final int USER = 0x00000100;
274:
275:            /** Something went wrong, though it can be recovered. */
276:            public static final int EXCEPTION = 0x00001000;
277:
278:            /** Serious problem, application may be crippled. */
279:            public static final int ERROR = 0x00010000;
280:
281:            /** We keep a reference to our proxy ErrorManager here. */
282:            private static DelegatingErrorManager current;
283:
284:            /** Getter for the default version of error manager.
285:             * @return the error manager installed in the system
286:             * @since 2.1
287:             */
288:            public static ErrorManager getDefault() {
289:                synchronized (ErrorManager.class) {
290:                    if (current != null) {
291:                        return current;
292:                    }
293:                }
294:
295:                return getDefaultDelegate();
296:            }
297:
298:            private static DelegatingErrorManager getDefaultDelegate() {
299:                DelegatingErrorManager c = new DelegatingErrorManager(""); // NOI18N
300:
301:                try {
302:                    c.initialize();
303:
304:                    synchronized (ErrorManager.class) {
305:                        if (current == null) {
306:                            current = c;
307:
308:                            // r is not null after c.initialize();
309:                            current.r.addLookupListener(current);
310:                        }
311:                    }
312:                } catch (RuntimeException e) {
313:                    // #20467
314:                    e.printStackTrace();
315:                    current = c;
316:                } catch (LinkageError e) {
317:                    // #20467
318:                    e.printStackTrace();
319:                    current = c;
320:                }
321:
322:                return current;
323:            }
324:
325:            /** Associates annotations with an exception.
326:             *
327:             * @param t the exception
328:             * @param arr array of annotations (or <code>null</code>)
329:             * @return the same exception <code>t</code> (as a convenience)
330:             */
331:            public abstract Throwable attachAnnotations(Throwable t,
332:                    Annotation[] arr);
333:
334:            /** Finds annotations associated with a given exception.
335:             * @param t the exception
336:             * @return array of annotations or <code>null</code>
337:             */
338:            public abstract Annotation[] findAnnotations(Throwable t);
339:
340:            /** Annotates given exception with given values. All the
341:             * previous annotations are kept and this new one is added at
342:             * the top of the annotation stack (index 0 of the annotation
343:             * array).
344:             *
345:             * @param t the exception
346:             * @param severity integer describing severity, e.g. {@link #EXCEPTION}
347:             * @param message message to attach to the exception or <code>null</code>
348:             * @param localizedMessage localized message for the user or <code>null</code>
349:             * @param stackTrace exception representing the stack trace or <code>null</code>
350:             * @param date date or <code>null</code>
351:             * @return the same exception <code>t</code> (as a convenience)
352:             */
353:            public abstract Throwable annotate(Throwable t, int severity,
354:                    String message, String localizedMessage,
355:                    Throwable stackTrace, java.util.Date date);
356:
357:            /** Prints the exception to the log file and (possibly) notifies the user.
358:             * Use of {@link #UNKNOWN} severity means that the error manager should automatically
359:             * select an appropriate severity level, for example based on the contents of
360:             * annotations in the throwable.
361:             * @param severity the severity to be applied to the exception (overrides default), e.g. {@link #EXCEPTION}
362:             * @param t the exception to notify
363:             */
364:            public abstract void notify(int severity, Throwable t);
365:
366:            /** Prints the exception to the log file and (possibly) notifies the user.
367:             * Guesses at the severity.
368:             * @param t the exception to notify
369:             * @see #UNKNOWN
370:             * @see #notify(int, Throwable)
371:             */
372:            public final void notify(Throwable t) {
373:                notify(UNKNOWN, t);
374:            }
375:
376:            /** Logs the message to a file and (possibly) tells the user.
377:             * @param severity the severity to be applied (overrides default)
378:             * @param s the log message
379:             */
380:            public abstract void log(int severity, String s);
381:
382:            // not yet: after phase III: * @deprecated use {@link Logger#log}
383:
384:            /** Logs the message to log file and (possibly) tells the user.
385:             * Uses a default severity.
386:             * @param s the log message
387:             */
388:            public final void log(String s) {
389:                // not yet: after phase III: * @deprecated {@link Logger#log}
390:                log(INFORMATIONAL, s);
391:            }
392:
393:            /** Test whether a messages with given severity will be logged in advance.
394:             * Can be used to avoid the construction of complicated and expensive
395:             * logging messages.
396:             * <p>The default implementation just returns true. Subclasses
397:             * should override to be more precise - <strong>treat this method as abstract</strong>.
398:             * @param severity the severity to check, e.g. {@link #EXCEPTION}
399:             * @return <code>false</code> if the next call to {@link #log(int,String)} with this severity will
400:             *    discard the message
401:             */
402:            public boolean isLoggable(int severity) {
403:                // not yet: after phase III: * @deprecated Use {@link Logger#isLoggable}
404:                return true;
405:            }
406:
407:            /**
408:             * Test whether a throwable, if {@link #notify(int, Throwable) notified} at the given
409:             * level, will actually be displayed in any way (even to a log file etc.).
410:             * If not, there is no point in constructing it.
411:             * <p>This method is distinct from {@link #isLoggable} because an error manager
412:             * implementation may choose to notify stack traces at a level where it would
413:             * not log messages. See issue #24056 for justification.
414:             * <p>The default implementation just calls {@link #isLoggable}. Subclasses
415:             * should override to be more precise - <strong>treat this method as abstract</strong>.
416:             * @param severity a notification severity
417:             * @return true if a throwable notified at this severity will be used; false if it will be ignored
418:             * @since 3.18
419:             */
420:            public boolean isNotifiable(int severity) {
421:                return isLoggable(severity);
422:            }
423:
424:            /** Returns an instance with given name.
425:             * <p>By convention, you can name error managers the same as packages (or classes)
426:             * they are designed to report information from.
427:             * For example, <code>org.netbeans.modules.mymodule.ComplicatedParser</code>.
428:             * <p>The error manager implementation should provide some way of configuring e.g.
429:             * the logging level for error managers of different names. For example, in the basic
430:             * NetBeans core implementation, you can define a system property with the same name
431:             * as the future error manager (or a package prefix of it) whose value is the numeric
432:             * logging level (e.g. <samp>-J-Dorg.netbeans.modules.mymodule.ComplicatedParser=0</samp>
433:             * to log everything). Other implementations may have quite different ways of configuring
434:             * the error managers.
435:             * @param name the desired identifying name
436:             * @return a new error manager keyed off of that name
437:             */
438:            public abstract ErrorManager getInstance(String name);
439:
440:            //
441:            // Helper methods
442:            //
443:
444:            /** Annotates given exception with given values. All the
445:             * previous annotations are kept and this new is added at
446:             * the top of the annotation stack (index 0 of the annotation
447:             * array).
448:             *
449:             * @param t the exception
450:             * @param localizedMessage localized message for the user or null
451:             * @return the same exception <code>t</code> (as a convenience)
452:             */
453:            public final Throwable annotate(Throwable t, String localizedMessage) {
454:                return annotate(t, UNKNOWN, null, localizedMessage, null, null);
455:            }
456:
457:            /** Annotates target exception with given exception. All the
458:             * previous annotations are kept and this new is added at
459:             * the top of the annotation stack (index 0 of the annotation
460:             * array).
461:             * <p>Consider using {@link Throwable#initCause} instead; this
462:             * will be correctly reported by the NetBeans error manager, and
463:             * also works properly with {@link Throwable#printStackTrace()}.
464:             * @param target the exception to be annotated
465:             * @param t the exception that will be added
466:             * @return the same exception <code>target</code> (as a convenience)
467:             */
468:            public final Throwable annotate(Throwable target, Throwable t) {
469:                return annotate(target, UNKNOWN, null, null, t, null);
470:            }
471:
472:            /** Takes annotations from one exception and associates
473:             * them with another one.
474:             *
475:             * @param t the exception to annotate
476:             * @param copyFrom exception to take annotations from
477:             * @return the same exception <code>t</code> (as a convenience)
478:             * @deprecated Now does the same thing as {@link #annotate(Throwable,Throwable)}
479:             *             except marks the annotation {@link #UNKNOWN} severity. Otherwise
480:             *             you used to have inadvertent data loss when <code>copyFrom</code>
481:             *             had annotations of its own: the subannotations were kept but the
482:             *             main stack trace in <code>copyFrom</code> was discarded. In practice
483:             *             you usually want to keep all of <code>copyFrom</code>; if for some
484:             *             reason you just want to keep annotations, please do so explicitly
485:             *             using {@link #findAnnotations} and {@link #attachAnnotations}.
486:             */
487:            @Deprecated
488:            public final Throwable copyAnnotation(Throwable t,
489:                    Throwable copyFrom) {
490:                // Cf. #17874 for the change in behavior.
491:
492:                /*
493:                Annotation[] arr = findAnnotations (copyFrom);
494:
495:                if (arr != null) {
496:                    return attachAnnotations (
497:                               t, arr
498:                           );
499:                } else {
500:                 */
501:                return annotate(t, UNKNOWN, null, null, copyFrom, null);
502:
503:                /*
504:                }
505:                 */
506:            }
507:
508:            /** Annotation that can be attached to an error.
509:             */
510:            public static interface Annotation {
511:                /** Non-localized message.
512:                 * @return associated message or <code>null</code>
513:                 */
514:                public abstract String getMessage();
515:
516:                /** Localized message.
517:                 * @return message to be presented to the user or <code>null</code>
518:                 */
519:                public abstract String getLocalizedMessage();
520:
521:                /** Stack trace. The stack trace should locate the method
522:                 * and position in the method where the error occurred.
523:                 *
524:                 * @return exception representing the location of the error or <code>null</code>
525:                 */
526:                public abstract Throwable getStackTrace();
527:
528:                /** Time at which the exception occurred.
529:                 * @return the time or <code>null</code>
530:                 */
531:                public abstract java.util.Date getDate();
532:
533:                /** Severity of the exception.
534:                 * {@link #UNKNOWN} serves as the default.
535:                 * @return number representing the severity, e.g. {@link ErrorManager#EXCEPTION}
536:                 */
537:                public abstract int getSeverity();
538:            }
539:
540:            // end of Annotation
541:
542:            /**
543:             * Implementation of ErrorManager that delegates to the ones found by
544:             * lookup.
545:             */
546:            private static class DelegatingErrorManager extends ErrorManager
547:                    implements  LookupListener {
548:                private String name = null;
549:
550:                /**
551:                 * The set of instances we delegate to.
552:                 */
553:                private Set<ErrorManager> delegates = new HashSet<ErrorManager>();
554:
555:                /** fallback logger to send messages to */
556:                private Logger logger;
557:
558:                /**
559:                 * A set that has to be updated when the list of delegates
560:                 * changes. All instances created by getInstance are held here.
561:                 */
562:                private WeakSet<DelegatingErrorManager> createdByMe = new WeakSet<DelegatingErrorManager>();
563:
564:                /** If we are the "central" delagate this is not null and
565:                 * we listen on the result. On newly created delegates this
566:                 * is null.
567:                 */
568:                Lookup.Result<ErrorManager> r;
569:
570:                public DelegatingErrorManager(String name) {
571:                    this .name = name;
572:                }
573:
574:                /** Initializes the logger.
575:                 */
576:                Logger logger() {
577:                    if (logger == null) {
578:                        logger = Logger.getLogger(this .name);
579:                    }
580:                    return logger;
581:                }
582:
583:                /** If the name is not empty creates new instance of
584:                 * DelegatingErrorManager. Adds it to createdByMe.
585:                 */
586:                public ErrorManager getInstance(String name) {
587:                    if ((name == null) || ("".equals(name))) { // NOI18N
588:
589:                        return this ;
590:                    }
591:
592:                    DelegatingErrorManager dem = new DelegatingErrorManager(
593:                            name);
594:
595:                    synchronized (this ) {
596:                        attachNewDelegates(dem, name);
597:                        createdByMe.add(dem);
598:                    }
599:
600:                    return dem;
601:                }
602:
603:                /** Calls all delegates. */
604:                public Throwable attachAnnotations(Throwable t, Annotation[] arr) {
605:                    for (ErrorManager em : delegates) {
606:                        em.attachAnnotations(t, arr);
607:                    }
608:
609:                    return t;
610:                }
611:
612:                /** Calls all delegates. */
613:                public Annotation[] findAnnotations(Throwable t) {
614:                    for (ErrorManager em : delegates) {
615:                        Annotation[] res = em.findAnnotations(t);
616:
617:                        if ((res != null) && (res.length > 0)) {
618:                            return res;
619:                        }
620:                    }
621:
622:                    return new Annotation[0];
623:                }
624:
625:                /** Calls all delegates. */
626:                public Throwable annotate(Throwable t, int severity,
627:                        String message, final String localizedMessage,
628:                        Throwable stackTrace, java.util.Date date) {
629:                    if (delegates.isEmpty()) {
630:                        LogRecord rec = new LogRecord(convertSeverity(severity,
631:                                true, Level.ALL), message);
632:                        if (stackTrace != null) {
633:                            rec.setThrown(stackTrace);
634:                        }
635:                        if (date != null) {
636:                            rec.setMillis(date.getTime());
637:                        }
638:                        if (localizedMessage != null) {
639:                            ResourceBundle rb = new ResourceBundle() {
640:                                public Object handleGetObject(String key) {
641:                                    if ("msg".equals(key)) { // NOI18N
642:                                        return localizedMessage;
643:                                    } else {
644:                                        return null;
645:                                    }
646:                                }
647:
648:                                public Enumeration<String> getKeys() {
649:                                    return Enumerations.singleton("msg"); // NOI18N
650:                                }
651:                            };
652:                            rec.setResourceBundle(rb);
653:                            rec.setMessage("msg"); // NOI18N
654:                        }
655:
656:                        AnnException ann = AnnException.findOrCreate(t, true);
657:                        ann.addRecord(rec);
658:
659:                        return t;
660:                    }
661:
662:                    for (ErrorManager em : delegates) {
663:                        em.annotate(t, severity, message, localizedMessage,
664:                                stackTrace, date);
665:                    }
666:
667:                    return t;
668:                }
669:
670:                /** Calls all delegates. */
671:                public void notify(int severity, Throwable t) {
672:                    if (delegates.isEmpty()) {
673:                        if (enterLogger())
674:                            return;
675:                        try {
676:                            AnnException ext = AnnException.extras.get(t);
677:                            if (ext != null) {
678:                                t = ext;
679:                            }
680:                            logger().log(
681:                                    convertSeverity(severity, true,
682:                                            OwnLevel.UNKNOWN), t.getMessage(),
683:                                    t);
684:                        } finally {
685:                            exitLogger();
686:                        }
687:                        return;
688:                    }
689:
690:                    try {
691:                        for (ErrorManager em : delegates) {
692:                            em.notify(severity, t);
693:                        }
694:                    } catch (RuntimeException e) {
695:                        // #20467
696:                        e.printStackTrace();
697:                        t.printStackTrace();
698:                    } catch (LinkageError e) {
699:                        // #20467
700:                        e.printStackTrace();
701:                        t.printStackTrace();
702:                    }
703:                }
704:
705:                /** Calls all delegates. */
706:                public void log(int severity, String s) {
707:                    if (severity == UNKNOWN) {
708:                        throw new IllegalArgumentException(
709:                                "ErrorManager.log(UNKNOWN, ...) is not permitted"); // NOI18N
710:                    }
711:
712:                    if (delegates.isEmpty()) {
713:                        Level sev = convertSeverity(severity, false, Level.FINE);
714:                        if (enterLogger())
715:                            return;
716:                        try {
717:                            logger().log(sev, s);
718:                        } finally {
719:                            exitLogger();
720:                        }
721:                        return;
722:                    }
723:
724:                    for (ErrorManager em : delegates) {
725:                        em.log(severity, s);
726:                    }
727:                }
728:
729:                private static Level convertSeverity(final int severity,
730:                        boolean forException, Level def) {
731:                    Level sev = def;
732:
733:                    if (severity >= ERROR) {
734:                        sev = Level.SEVERE;
735:                    } else if (severity >= EXCEPTION) {
736:                        sev = Level.SEVERE;
737:                    } else if (severity >= USER) {
738:                        sev = OwnLevel.USER;
739:                    } else if (severity >= WARNING) {
740:                        sev = Level.WARNING;
741:                    } else if (severity >= INFORMATIONAL) {
742:                        sev = forException ? Level.INFO : Level.FINE;
743:                    }
744:                    return sev;
745:                }
746:
747:                /** Calls all delegates. */
748:                public boolean isLoggable(int severity) {
749:                    if (severity == UNKNOWN) {
750:                        throw new IllegalArgumentException(
751:                                "ErrorManager.isLoggable(UNKNOWN) is not permitted"); // NOI18N
752:                    }
753:
754:                    if (delegates.isEmpty()) {
755:                        return logger().isLoggable(
756:                                convertSeverity(severity, false, null));
757:                    }
758:
759:                    for (ErrorManager em : delegates) {
760:                        if (em.isLoggable(severity)) {
761:                            return true;
762:                        }
763:                    }
764:
765:                    return false;
766:                }
767:
768:                /** Calls all delegates. */
769:                public boolean isNotifiable(int severity) {
770:                    if (severity == UNKNOWN) {
771:                        throw new IllegalArgumentException(
772:                                "ErrorManager.isNotifiable(UNKNOWN) is not permitted"); // NOI18N
773:                    }
774:
775:                    if (delegates.isEmpty()) {
776:                        return logger().isLoggable(
777:                                convertSeverity(severity, true, null));
778:                    }
779:
780:                    for (ErrorManager em : delegates) {
781:                        if (em.isNotifiable(severity)) {
782:                            return true;
783:                        }
784:                    }
785:
786:                    return false;
787:                }
788:
789:                /**
790:                 * Updates the list of delegates. Also updates all instances created
791:                 * by ourselves.
792:                 */
793:                public synchronized void setDelegates(
794:                        Collection<? extends ErrorManager> newDelegates) {
795:                    delegates = new LinkedHashSet<ErrorManager>(newDelegates);
796:
797:                    for (DelegatingErrorManager dem : createdByMe) {
798:                        attachNewDelegates(dem, dem.getName());
799:                    }
800:                }
801:
802:                private String getName() {
803:                    return name;
804:                }
805:
806:                /**
807:                 * Takes all our delegates, asks them for an instance identified by
808:                 * name and adds those results as new delegates for dem.
809:                 * @param String name
810:                 * @param DelagatingErrorManager d the instance to which we will attach
811:                 */
812:                private void attachNewDelegates(DelegatingErrorManager dem,
813:                        String name) {
814:                    Set<ErrorManager> newDelegatesForDem = new HashSet<ErrorManager>();
815:
816:                    for (ErrorManager e : delegates) {
817:                        newDelegatesForDem.add(e.getInstance(name));
818:                    }
819:
820:                    dem.setDelegates(newDelegatesForDem);
821:                }
822:
823:                /** Blocks on lookup and after the lookup returns updates
824:                 * delegates and adds a listener.
825:                 */
826:                public void initialize() {
827:                    r = Lookup.getDefault().lookupResult(ErrorManager.class);
828:                    setDelegates(r.allInstances());
829:                }
830:
831:                /** Updates the delegates.*/
832:                public void resultChanged(LookupEvent ev) {
833:                    if (r != null) {
834:                        setDelegates(r.allInstances());
835:                    }
836:                }
837:
838:                private static volatile Thread lastThread;
839:
840:                private static boolean enterLogger() {
841:                    if (lastThread == Thread.currentThread()) {
842:                        new Exception(
843:                                "using error manager from inside a logger")
844:                                .printStackTrace(); // NOI18N
845:                        return true;
846:                    }
847:                    lastThread = Thread.currentThread();
848:                    return false;
849:                }
850:
851:                private static void exitLogger() {
852:                    lastThread = null;
853:                }
854:            }
855:
856:            /** An exception that has a log record associated with itself, so
857:             * the NbErrorManager can extract info about the annotation.
858:             */
859:            private static final class AnnException extends Exception implements 
860:                    Callable<LogRecord[]> {
861:                private List<LogRecord> records;
862:                /** additional mapping from throwables that refuse initCause call */
863:                private static Map<Throwable, AnnException> extras = new WeakHashMap<Throwable, AnnException>();
864:
865:                public String getMessage() {
866:                    StringBuilder sb = new StringBuilder();
867:                    String sep = "";
868:                    for (LogRecord r : records) {
869:                        if (r.getMessage() != null) {
870:                            sb.append(sep);
871:                            sb.append(r.getMessage());
872:                            sep = "\n";
873:                        }
874:                    }
875:                    return sb.toString();
876:                }
877:
878:                static AnnException findOrCreate(Throwable t, boolean create) {
879:                    if (t instanceof  AnnException) {
880:                        return (AnnException) t;
881:                    }
882:                    if (t.getCause() == null) {
883:                        if (create) {
884:                            try {
885:                                t.initCause(new AnnException());
886:                            } catch (IllegalStateException x) {
887:                                AnnException ann = extras.get(t);
888:                                if (ann == null) {
889:                                    ann = new AnnException();
890:                                    ann.initCause(t);
891:                                    Logger.getLogger(
892:                                            ErrorManager.class.getName()).log(
893:                                            Level.FINE,
894:                                            "getCause was null yet initCause failed for "
895:                                                    + t, x);
896:                                    extras.put(t, ann);
897:                                }
898:                                return ann;
899:                            }
900:                        }
901:                        return (AnnException) t.getCause();
902:                    }
903:                    return findOrCreate(t.getCause(), create);
904:                }
905:
906:                private AnnException() {
907:                }
908:
909:                public synchronized void addRecord(LogRecord rec) {
910:                    if (records == null) {
911:                        records = new ArrayList<LogRecord>();
912:                    }
913:                    records.add(rec);
914:                }
915:
916:                public LogRecord[] call() {
917:                    List<LogRecord> r = records;
918:                    LogRecord[] empty = new LogRecord[0];
919:                    return r == null ? empty : r.toArray(empty);
920:                }
921:
922:                public void printStackTrace(PrintStream s) {
923:                    super .printStackTrace(s);
924:                    logRecords(s);
925:                }
926:
927:                public void printStackTrace(PrintWriter s) {
928:                    super .printStackTrace(s);
929:                    logRecords(s);
930:                }
931:
932:                public void printStackTrace() {
933:                    printStackTrace(System.err);
934:                }
935:
936:                private void logRecords(Appendable a) {
937:                    List<LogRecord> r = records;
938:                    if (r == null) {
939:                        return;
940:                    }
941:                    try {
942:
943:                        for (LogRecord log : r) {
944:                            if (log.getMessage() != null) {
945:                                a.append(log.getMessage()).append("\n");
946:                                ;
947:                            }
948:                            if (log.getThrown() != null) {
949:                                StringWriter w = new StringWriter();
950:                                log.getThrown().printStackTrace(
951:                                        new PrintWriter(w));
952:                                a.append(w.toString()).append("\n");
953:                            }
954:                        }
955:                    } catch (IOException ex) {
956:                        ex.printStackTrace();
957:                    }
958:                }
959:            } // end AnnException
960:
961:            private static final class OwnLevel extends Level {
962:                public static final Level USER = new OwnLevel("USER", 1973); // NOI18N
963:                public static final Level UNKNOWN = new OwnLevel("SEVERE",
964:                        Level.SEVERE.intValue() + 1); // NOI18N
965:
966:                private OwnLevel(String s, int i) {
967:                    super (s, i);
968:                }
969:            } // end of UserLevel
970:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.