Index: core/src/META-INF/services/org.openide.ErrorManager =================================================================== RCS file: core/src/META-INF/services/org.openide.ErrorManager diff -N core/src/META-INF/services/org.openide.ErrorManager --- core/src/META-INF/services/org.openide.ErrorManager 20 Aug 2002 19:55:39 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1 +0,0 @@ -org.netbeans.core.NbErrorManager Index: core/src/org/netbeans/core/CoreBridgeImpl.java =================================================================== RCS file: /cvs/core/src/org/netbeans/core/CoreBridgeImpl.java,v retrieving revision 1.3 diff -u -r1.3 CoreBridgeImpl.java --- core/src/org/netbeans/core/CoreBridgeImpl.java 12 Sep 2005 09:31:34 -0000 1.3 +++ core/src/org/netbeans/core/CoreBridgeImpl.java 18 Dec 2005 18:41:55 -0000 @@ -13,9 +13,11 @@ package org.netbeans.core; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; +import java.util.logging.LogManager; import org.netbeans.core.startup.Main; import org.netbeans.core.startup.ManifestSection; @@ -27,7 +29,15 @@ implements Runnable { /** counts the number of CLI invocations */ private int numberOfCLIInvocations; - + + static { + String file = System.getProperty("java.util.logging.config.file"); // NOI18N + String clazz = System.getProperty("java.util.logging.config.class"); // NOI18N + if (file == null && clazz == null) { + System.setProperty("java.util.logging.config.class", "org.netbeans.core.NbErrorManager"); // NOI18N + NbErrorManager.registerConfiguration(); + } + } protected void attachToCategory (Object category) { ModuleActions.attachTo(category); Index: core/src/org/netbeans/core/NbErrorManager.java =================================================================== RCS file: /cvs/core/src/org/netbeans/core/NbErrorManager.java,v retrieving revision 1.58 diff -u -r1.58 NbErrorManager.java --- core/src/org/netbeans/core/NbErrorManager.java 25 Aug 2005 02:34:06 -0000 1.58 +++ core/src/org/netbeans/core/NbErrorManager.java 18 Dec 2005 18:41:55 -0000 @@ -13,15 +13,20 @@ package org.netbeans.core; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; +import java.io.SequenceInputStream; import java.io.StringWriter; +import java.io.UnsupportedEncodingException; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -30,11 +35,24 @@ import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; +import java.util.ResourceBundle; import java.util.Set; import java.util.StringTokenizer; import java.util.WeakHashMap; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.Logger; import org.netbeans.core.startup.TopLogging; -import org.openide.ErrorManager; +import org.openide.filesystems.FileAttributeEvent; +import org.openide.filesystems.FileChangeListener; +import org.openide.filesystems.FileEvent; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileRenameEvent; +import org.openide.filesystems.FileUtil; +import org.openide.filesystems.Repository; +import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.xml.sax.SAXParseException; @@ -42,53 +60,56 @@ * * @author Jaroslav Tulach, Jesse Glick */ -public final class NbErrorManager extends ErrorManager { - +public final class NbErrorManager extends Handler implements FileChangeListener { + /** our root logger */ + static NbErrorManager ROOT = new NbErrorManager(); + public NbErrorManager() { - this(null, defaultSeverity(), null); + setLevel(Level.CONFIG); } - - /** - * Construct for testing. - * @see "#18141" - */ - NbErrorManager(PrintStream pw) { - this(null, defaultSeverity(), pw); + + static { + System.setProperty("sun.awt.exception.handler", "org.netbeans.core.NbErrorManager$AWTHandler"); // NOI18N + + FileObject listen = readConfig(); + listen.addFileChangeListener(ROOT); + } - private static int defaultSeverity() { - String dsev = System.getProperty("ErrorManager.minimum"); - // use e.g. 17 to avoid logging WARNING messages. - if (dsev != null) { - try { - return Integer.parseInt(dsev); - } catch (NumberFormatException nfe) { - nfe.printStackTrace(); - } - } - // I.e. 2: avoid logging INFORMATIONAL messages. - return ErrorManager.INFORMATIONAL + 1; + public static void registerConfiguration() { + // just make the class to set the configuation } - private NbErrorManager(String pfx, int sev, PrintStream pw) { - prefix = pfx; - minLogSeverity = sev; - logWriter = pw; - synchronized (uniquifiedIds) { - Integer i = (Integer)uniquifiedIds.get(pfx); - if (i == null) { - uniquifier = 1; - } else { - uniquifier = i.intValue() + 1; + /** Reads the config from folder "Logging" */ + private static FileObject readConfig() { + FileObject fo = null; + try { + fo = Repository.getDefault().getDefaultFileSystem().getRoot(); + fo = FileUtil.createFolder(fo, "Logging"); // NOI18N + FileObject[] arr = fo.getChildren(); + ArrayList list = new ArrayList(); + for (int i = 0; i < arr.length; i++) { + if (arr[i].isData()) { + list.add(arr[i].getInputStream()); + } } - uniquifiedIds.put(pfx, new Integer(uniquifier)); + SequenceInputStream all = new SequenceInputStream(Collections.enumeration(list)); + LogManager.getLogManager().readConfiguration(all); + all.close(); + + Logger root = Logger.getLogger(""); // NOI18N + Handler[] handlers = root.getHandlers(); + for (int i = 0; i < handlers.length; i++) { + root.removeHandler(handlers[i]); + } + root.addHandler(ROOT); + root.setLevel(ROOT.getLevel()); + } catch (IOException ex) { + ex.printStackTrace(); } - //System.err.println("NbErrorManager[" + pfx + " #" + uniquifier + "]: minLogSeverity=" + sev); + return fo; } - /** maps Throwables to java.util.List (Ann) */ - private static final Map map = new WeakHashMap (11); - /** message to print date to */ private static final MessageFormat EXC_HEADER = new MessageFormat( "{0}*********** Exception occurred ************ at {1,time,short} on {1,date,medium}", // NOI18N @@ -96,21 +117,7 @@ ); /** The writer to the log file*/ - private PrintStream logWriter; - - /** Minimum value of severity to write message to the log file*/ - private final int minLogSeverity; - - /** Prefix preprended to customized loggers, if any. */ - private final String prefix; - - // Make sure two distinct EM impls log differently even with the same name. - private final int uniquifier; // 0 for root EM (prefix == null), else >= 1 - private static final Map uniquifiedIds = new HashMap(20); // Map - - static { - System.setProperty("sun.awt.exception.handler", "org.netbeans.core.NbErrorManager$AWTHandler"); // NOI18N - } + static PrintStream logWriter; /** Initializes the log stream. */ @@ -129,70 +136,14 @@ } } - public synchronized Throwable annotate ( - Throwable t, - int severity, String message, String localizedMessage, - Throwable stackTrace, Date date - ) { - Object o = map.get (t); - - List ll; - if (o == null) { - ll = new ArrayList (); - map.put (t, ll); - } else { - ll = (List)o; - } - - ll.add(0, - new Ann (severity, message, localizedMessage, stackTrace, date) - ); - - return t; - } - - - /** Associates annotations with this thread. - * - * @param arr array of annotations (or null) - */ - public synchronized Throwable attachAnnotations (Throwable t, Annotation[] arr) { - Object o = map.get (t); - List l; - if (o == null) { - l = new ArrayList(arr.length + 5); - map.put (t, l); - } else { - l = (List)o; - } - l.addAll(0, Arrays.asList(arr)); - - return t; - } - - /** Honor configured min-severity levels, more or less. - * Actually bump up the effective severity of an exception by one. - * Thus by default INFORMATIONAL stack traces are displayed, but not - * messages. By playing with min log severity levels, you can get - * both, or neither. - * @see "#24056" - */ - public boolean isNotifiable(int severity) { - return isLoggable(severity + 1); - } - /** Notifies all the exceptions associated with * this thread. */ - public synchronized void notify (int severity, Throwable t) { + private synchronized void notify (LogRecord record, Throwable t) { // synchronized to ensure that only one exception is // written to the thread - Exc ex = createExc(t, severity); - - if (!isNotifiable(ex.getSeverity())) { - return; - } + Exc ex = createExc(t, record.getLevel()); //issue 36878 - printing the stack trace on a user error is //disconcerting because it makes it look like something went wrong @@ -203,32 +154,31 @@ //an exception may be annotated as severe, but in the context //it is not - thus we check if *any* annotation is USER, rather than //that the highest level severity in the annotation is USER - boolean wantStackTrace = severity != USER; + boolean wantStackTrace = record.getLevel() != Level.INFO; if (wantStackTrace) { - Annotation[] ann = findAnnotations(t); + LogRecord[] ann = findAnnotations(t); if (ann != null) { for (int i=0; i < ann.length; i++) { - if (ann[i] instanceof Ann) { - if (((Ann) ann[i]).getSeverity() == USER) { - wantStackTrace = false; - break; - } + if (ann[i].getLevel() == Level.INFO) { + wantStackTrace = false; + break; } } } } if (wantStackTrace) { PrintStream log = getLogWriter(); + String prefix = record.getLoggerName(); if (prefix != null) log.print ("[" + prefix + "] "); // NOI18N - String level = ex.getSeverity() == INFORMATIONAL ? "INFORMATIONAL " : "";// NOI18N + String level = ex.getSeverity().intValue() < Level.FINE.intValue() ? "INFORMATIONAL " : "";// NOI18N log.println (EXC_HEADER.format (new Object[] { level, ex.getDate() })); ex.printStackTrace(log); } - if (ex.getSeverity () > INFORMATIONAL) { + if (ex.getSeverity ().intValue() > Level.INFO.intValue()) { NotifyException.notify (ex); } } @@ -237,83 +187,22 @@ * Just create the exception information for a throwable being notified. * Useful for the unit test. */ - Exc createExc(Throwable t, int severity) { - Annotation[] ann = findAnnotations (t); + Exc createExc(Throwable t, Level severity) { + LogRecord[] ann = findAnnotations (t); return new Exc (t, severity, ann, findAnnotations0(t, true, new HashSet())); } - public void log(int severity, String s) { - if (isLoggable (severity)) { - //System.err.println(toString() + " logging '" + s + "' at " + severity); - PrintStream log = getLogWriter (); - - if (prefix != null) { - boolean showUniquifier; - // Print a unique EM sequence # if there is more than one - // with this name. Shortcut: if the # > 1, clearly there are. - if (uniquifier > 1) { - showUniquifier = true; - } else if (uniquifier == 1) { - synchronized (uniquifiedIds) { - int count = ((Integer)uniquifiedIds.get(prefix)).intValue(); - showUniquifier = count > 1; - } - } else { - throw new IllegalStateException("prefix != null yet uniquifier == 0"); - } - if (showUniquifier) { - log.print ("[" + prefix + " #" + uniquifier + "] "); // NOI18N - } else { - log.print ("[" + prefix + "] "); // NOI18N - } - } - log.println(s); + public void log(LogRecord record, String s) { + //System.err.println(toString() + " logging '" + s + "' at " + severity); + PrintStream log = getLogWriter (); + + String prefix = record.getLoggerName(); + if (prefix != null) { + log.print ("[" + prefix + "] "); // NOI18N } + log.println(s); } - /** Allows to test whether messages with given severity will be logged - * or not prior to constraction of complicated and time expensive - * logging messages. - * - * @param severity the severity to check - * @return false if the next call to log method with the same severity will - * discard the message - */ - public boolean isLoggable (int severity) { - return severity >= minLogSeverity; - } - - - /** Returns an instance with given name. The name - * can be dot separated list of names creating - * a hierarchy. - */ - public final ErrorManager getInstance(String name) { - String pfx = (prefix == null) ? name : prefix + '.' + name; - int sev = minLogSeverity; - String prop = pfx; - while (prop != null) { - String value = System.getProperty (prop); - //System.err.println ("Trying; prop=" + prop + " value=" + value); - if (value != null) { - try { - sev = Integer.parseInt (value); - } catch (NumberFormatException nfe) { - notify (WARNING, nfe); - } - break; - } else { - int idx = prop.lastIndexOf ('.'); - if (idx == -1) - prop = null; - else - prop = prop.substring (0, idx); - } - } - //System.err.println ("getInstance: prefix=" + prefix + " mls=" + minLogSeverity + " name=" + name + " prefix2=" + newEM.prefix + " mls2=" + newEM.minLogSeverity); - return new NbErrorManager(pfx, sev, logWriter); - } - /** Method (or field) names in various exception classes which give * a nested exception. Fields should be public, methods public no-arg. * Field names should be prefixed with a dot. @@ -367,16 +256,27 @@ * @param t the exception * @return array of annotations or null */ - public synchronized Annotation[] findAnnotations (Throwable t) { + public synchronized LogRecord[] findAnnotations (Throwable t) { return findAnnotations0(t, false, new HashSet()); } + /** to query LogRecords from exceptions */ + private static final Lookup.Template RECORD = new Lookup.Template(LogRecord.class); /** If recursively is true it is not adviced to print all annotations * because a lot of warnings will be printed. But while searching for * localized message we should scan all the annotations (even recursively). */ - private synchronized Annotation[] findAnnotations0(Throwable t, boolean recursively, Set alreadyVisited) { - List l = (List)map.get (t); + private synchronized LogRecord[] findAnnotations0(Throwable t, boolean recursively, Set alreadyVisited) { + List l = new ArrayList(); + Throwable collect = t; + while (collect != null) { + if (collect instanceof Lookup.Provider) { + Lookup lookup = ((Lookup.Provider)collect).getLookup(); + l.addAll(lookup.lookup(RECORD).allInstances()); + } + collect = collect.getCause(); + } + // MissingResourceException should be printed nicely... --jglick if (t instanceof MissingResourceException) { if (l == null) { @@ -388,11 +288,19 @@ MissingResourceException mre = (MissingResourceException) t; String cn = mre.getClassName (); if (cn != null) { - l.add (new Ann (EXCEPTION, NbBundle.getMessage (NbErrorManager.class, "EXC_MissingResourceException_class_name", cn), null, null, null)); + LogRecord rec = new LogRecord(Level.CONFIG, null); + rec.setResourceBundle(NbBundle.getBundle(NbErrorManager.class)); + rec.setResourceBundleName("EXC_MissingResourceException_class_name"); + rec.setParameters(new Object[] { cn }); + l.add(rec); } String k = mre.getKey (); if (k != null) { - l.add (new Ann (EXCEPTION, NbBundle.getMessage (NbErrorManager.class, "EXC_MissingResourceException_key", k), null, null, null)); + LogRecord rec = new LogRecord(Level.CONFIG, null); + rec.setResourceBundle(NbBundle.getBundle(NbErrorManager.class)); + rec.setResourceBundleName("EXC_MissingResourceException_key"); + rec.setParameters(new Object[] { k }); + l.add(rec); } if (l.size () == 0) l = null; // not clear if null means something other than new Annotation[0] } else { @@ -406,7 +314,9 @@ } else { l = new ArrayList(l); } - l.add(new Ann(UNKNOWN, null, null, t2, null)); + LogRecord rec = new LogRecord(Level.CONFIG, null); + rec.setThrown(t2); + l.add(rec); } } if (t instanceof SAXParseException) { @@ -418,17 +328,24 @@ int col = spe.getColumnNumber(); int line = spe.getLineNumber(); String msg; + Object[] param; if (col != -1 || line != -1) { - msg = NbBundle.getMessage(NbErrorManager.class, "EXC_sax_parse_col_line", new Object[] {String.valueOf(pubid), String.valueOf(sysid), new Integer(col), new Integer(line)}); + msg = "EXC_sax_parse_col_line"; // NOI18N + param = new Object[] {String.valueOf(pubid), String.valueOf(sysid), new Integer(col), new Integer(line)}; } else { - msg = NbBundle.getMessage(NbErrorManager.class, "EXC_sax_parse", String.valueOf(pubid), String.valueOf(sysid)); + msg = "EXC_sax_parse"; // NOI18N + param = new Object[] { String.valueOf(pubid), String.valueOf(sysid) }; } if (l == null) { l = new ArrayList(1); } else { l = new ArrayList(l); } - l.add(new Ann(UNKNOWN, msg, null, null, null)); + LogRecord rec = new LogRecord(Level.CONFIG, null); + rec.setResourceBundle(NbBundle.getBundle(NbErrorManager.class)); + rec.setResourceBundleName(msg); + rec.setParameters(param); + l.add(rec); } } @@ -436,11 +353,11 @@ if (l != null) { ArrayList al = new ArrayList(); for (Iterator i = l.iterator(); i.hasNext(); ) { - Annotation ano = (Annotation)i.next(); - Throwable t1 = ano.getStackTrace(); + LogRecord ano = (LogRecord)i.next(); + Throwable t1 = ano.getThrown(); if ((t1 != null) && (! alreadyVisited.contains(t1))) { alreadyVisited.add(t1); - Annotation[] tmpAnnoArray = findAnnotations0(t1, true, alreadyVisited); + LogRecord[] tmpAnnoArray = findAnnotations0(t1, true, alreadyVisited); if ((tmpAnnoArray != null) && (tmpAnnoArray.length > 0)) { al.addAll(Arrays.asList(tmpAnnoArray)); } @@ -450,85 +367,77 @@ } } - Annotation[] arr; + LogRecord[] arr; if (l == null) { arr = null; } else { - arr = new Annotation[l.size ()]; + arr = new LogRecord[l.size ()]; l.toArray (arr); } return arr; } - public String toString() { - return super.toString() + "<" + prefix + "," + minLogSeverity + ">"; // NOI18N + public void publish(LogRecord record) { + if (record.getThrown() != null) { + notify(record, record.getThrown()); + } else { + log(record, record.getMessage()); + } } - /** Implementation of annotation interface. - */ - private static final class Ann extends Object - implements ErrorManager.Annotation { - private int severity; - private String message; - private String localizedMessage; - private Throwable stackTrace; - private Date date; - - /** Constructor. - */ - public Ann ( - int severity, - String message, - String localizedMessage, - Throwable stackTrace, - Date date - ) { - this.severity = severity; - this.message = message; - this.localizedMessage = localizedMessage; - this.stackTrace = stackTrace; - this.date = date; - } + public void flush() { + logWriter.flush(); + } - /** Non-localized message. - * @return associated message or null - */ - public String getMessage() { - return message; - } - /** Localized message. - * @return message to be presented to the user or null - */ - public String getLocalizedMessage() { - return localizedMessage; - } - /** Stack trace. The stack trace should locate the method - * and possition in the method where error occured. - * - * @return exception representing the location of error or null - */ - public Throwable getStackTrace() { - return stackTrace; - } - /** Date when the exception occured. - * @return the date or null - */ - public java.util.Date getDate() { - return date; + public void close() throws SecurityException { + // nothing needed + } + + /** Extracts localized message from a LogRecord */ + static final String getLocalizedMessage(LogRecord rec) { + ResourceBundle rb = rec.getResourceBundle(); + if (rb == null) { + return null; } - /** Severity of the exception. - * @return number representing the severity - */ - public int getSeverity() { - return severity; + + String msg = rec.getResourceBundleName(); + if (msg == null) { + return null; } - public String toString() { - return "NbEM.Ann[severity=" + severity + ",message=" + message + ",localizedMessage=" + localizedMessage + ",stackTrace=" + stackTrace + ",date=" + date + "]"; // NOI18N + Object[] arr = rec.getParameters(); + if (arr == null) { + arr = new Object[0]; } - } // end of Ann + String format = rb.getString(msg); + return MessageFormat.format(format, arr); + } + + public void fileFolderCreated(FileEvent fe) { + readConfig(); + } + + public void fileDataCreated(FileEvent fe) { + readConfig(); + } + + public void fileChanged(FileEvent fe) { + readConfig(); + } + + public void fileDeleted(FileEvent fe) { + readConfig(); + } + + public void fileRenamed(FileRenameEvent fe) { + readConfig(); + } + + public void fileAttributeChanged(FileAttributeEvent fe) { + readConfig(); + } /** * Another final class that is used to communicate with @@ -539,18 +448,18 @@ /** the original throwable */ private Throwable t; private Date d; - private Annotation[] arr; - private Annotation[] arrAll; // all - recursively - private int severity; + private LogRecord[] arr; + private LogRecord[] arrAll; // all - recursively + private Level severity; /** @param severity if -1 then we will compute the * severity from annotations */ - Exc (Throwable t, int severity, Annotation[] arr, Annotation[] arrAll) { + Exc (Throwable t, Level severity, LogRecord[] arr, LogRecord[] arrAll) { this.t = t; this.severity = severity; - this.arr = arr == null ? new Annotation[0] : arr; - this.arrAll = arrAll == null ? new Annotation[0] : arrAll; + this.arr = arr == null ? new LogRecord[0] : arr; + this.arrAll = arrAll == null ? new LogRecord[0] : arrAll; } /** @return message */ @@ -573,7 +482,7 @@ return (String)find(2); } for (int i = 0; i < arrAll.length; i++) { - String s = arrAll[i].getLocalizedMessage (); + String s = NbErrorManager.getLocalizedMessage(arrAll[i]); if (s != null) { return s; } @@ -591,7 +500,7 @@ return (String)find(2) != null; } for (int i = 0; i < arrAll.length; i++) { - String s = arrAll[i].getLocalizedMessage (); + String s = NbErrorManager.getLocalizedMessage(arrAll[i]); if (s != null) { return true; } @@ -605,22 +514,22 @@ } /** @return the severity of the exception */ - int getSeverity () { - if (severity != UNKNOWN) { + Level getSeverity () { + if (severity != null) { return severity; } - Annotation[] anns = (arrAll != null) ? arrAll : arr; + LogRecord[] anns = (arrAll != null) ? arrAll : arr; for (int i = 0; i < anns.length; i++) { - int s = anns[i].getSeverity (); - if (s > severity) { + Level s = anns[i].getLevel(); + if (severity == null || s.intValue() > severity.intValue()) { severity = s; } } - if (severity == UNKNOWN) { + if (severity == null || severity == Level.ALL) { // no severity specified, assume this is an error - severity = t instanceof Error ? ERROR : EXCEPTION; + severity = t instanceof Error ? Level.SEVERE : Level.WARNING; } return severity; @@ -652,22 +561,23 @@ private void printStackTrace(PrintWriter pw, Set/**/ nestingCheck) { if (t != null && !nestingCheck.add(t)) { // Unlocalized log message - this is for developers of NB, not users - log(ErrorManager.WARNING, "WARNING - ErrorManager detected cyclic exception nesting:"); // NOI18N + Logger l = Logger.getAnonymousLogger(); + l.warning("WARNING - ErrorManager detected cyclic exception nesting:"); // NOI18N Iterator it = nestingCheck.iterator(); while (it.hasNext()) { Throwable t = (Throwable)it.next(); - log(ErrorManager.WARNING, "\t" + t); // NOI18N - Annotation[] anns = findAnnotations(t); + l.warning("\t" + t); // NOI18N + LogRecord[] anns = findAnnotations(t); if (anns != null) { for (int i = 0; i < anns.length; i++) { - Throwable t2 = anns[i].getStackTrace(); + Throwable t2 = anns[i].getThrown(); if (t2 != null) { - log(ErrorManager.WARNING, "\t=> " + t2); // NOI18N + l.warning("\t=> " + t2); // NOI18N } } } } - log(ErrorManager.WARNING, "Be sure not to annotate an exception with itself, directly or indirectly."); // NOI18N + l.warning("Be sure not to annotate an exception with itself, directly or indirectly."); // NOI18N return; } /*Heaeder @@ -687,8 +597,8 @@ for (int i = 0; i < arr.length; i++) { if (arr[i] == null) continue; - Throwable thr = arr[i].getStackTrace(); - String annotation = arr[i].getLocalizedMessage(); + Throwable thr = arr[i].getThrown(); + String annotation = NbErrorManager.getLocalizedMessage(arr[i]); if (annotation == null) annotation = arr[i].getMessage(); /* @@ -741,10 +651,10 @@ for (int i = 0; i < arr.length; i++) { if (arr[i] == null) continue; - Throwable thr = arr[i].getStackTrace(); + Throwable thr = arr[i].getThrown(); if (thr != null) { - Annotation[] ans = findAnnotations (thr); - Exc ex = new Exc (thr, 0, ans, null); + LogRecord[] ans = findAnnotations (thr); + Exc ex = new Exc (thr, null, ans, null); pw.println("==>"); // NOI18N ex.printStackTrace(pw, nestingCheck); } @@ -783,22 +693,22 @@ */ private Object find (int kind, boolean def) { for (int i = 0; i < arr.length; i++) { - Annotation a = arr[i]; + LogRecord a = arr[i]; Object o = null; switch (kind) { case 1: // message o = a.getMessage (); break; case 2: // localized - o = a.getLocalizedMessage (); break; + o = NbErrorManager.getLocalizedMessage(a); break; case 3: // class name { - Throwable t = a.getStackTrace (); + Throwable t = a.getThrown(); o = t == null ? null : t.getClass().getName(); break; } case 4: // date - o = a.getDate (); break; + o = new Date(a.getMillis()); break; } if (o != null) { @@ -834,7 +744,7 @@ if (t.getClass().getName().endsWith(".ExitSecurityException")) { // NOI18N return; } - ErrorManager.getDefault().notify((ERROR << 1), t); + Logger.getAnonymousLogger().throwing(null, null, t); } } } Index: core/src/org/netbeans/core/NotifyException.java =================================================================== RCS file: /cvs/core/src/org/netbeans/core/NotifyException.java,v retrieving revision 1.69 diff -u -r1.69 NotifyException.java --- core/src/org/netbeans/core/NotifyException.java 8 Sep 2005 03:37:19 -0000 1.69 +++ core/src/org/netbeans/core/NotifyException.java 18 Dec 2005 18:41:56 -0000 @@ -26,6 +26,7 @@ import java.io.StringWriter; import java.util.ArrayList; import java.util.ResourceBundle; +import java.util.logging.Level; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; @@ -202,16 +203,16 @@ SwingUtilities.invokeLater (new Runnable () { public void run() { String glm = t.getLocalizedMessage(); - int gs = t.getSeverity(); + Level gs = t.getSeverity(); boolean loc = t.isLocalized(); - if (gs == ErrorManager.WARNING && loc) { + if (gs == Level.WARNING && loc) { DialogDisplayer.getDefault().notify( new NotifyDescriptor.Message(glm, NotifyDescriptor.WARNING_MESSAGE)); - } else if (gs == ErrorManager.USER && loc) { + } else if (gs == Level.INFO && loc) { DialogDisplayer.getDefault().notify( new NotifyDescriptor.Message(glm, NotifyDescriptor.INFORMATION_MESSAGE)); - } else if (gs == ErrorManager.ERROR && loc) { + } else if (gs == Level.SEVERE && loc) { DialogDisplayer.getDefault().notify( new NotifyDescriptor.Message(glm, NotifyDescriptor.ERROR_MESSAGE)); } else { @@ -298,7 +299,7 @@ //throw new RuntimeException ("I am not so exceptional"); //uncomment to test } catch (Exception e) { exceptions.add(new NbErrorManager().createExc( - e, ErrorManager.EXCEPTION)); + e, Level.SEVERE)); next.setVisible(true); } } @@ -363,7 +364,7 @@ } } else { ResourceBundle curBundle = NbBundle.getBundle (NotifyException.class); - if (current.getSeverity() == ErrorManager.WARNING) { + if (current.getSeverity() == Level.WARNING) { // less scary message for warning level descriptor.setMessage ( java.text.MessageFormat.format( @@ -420,7 +421,7 @@ //Do not allow an exception thrown here to trigger an endless //loop exceptions.add(new NbErrorManager().createExc(e, //ugly but works - ErrorManager.EXCEPTION)); + Level.SEVERE)); next.setVisible(true); } return; Index: core/test/unit/src/org/netbeans/core/NbErrorManagerTest.java =================================================================== RCS file: /cvs/core/test/unit/src/org/netbeans/core/NbErrorManagerTest.java,v retrieving revision 1.7 diff -u -r1.7 NbErrorManagerTest.java --- core/test/unit/src/org/netbeans/core/NbErrorManagerTest.java 13 Sep 2005 06:35:37 -0000 1.7 +++ core/test/unit/src/org/netbeans/core/NbErrorManagerTest.java 18 Dec 2005 18:41:56 -0000 @@ -16,10 +16,16 @@ import java.io.*; import java.lang.reflect.InvocationTargetException; import java.util.MissingResourceException; +import java.util.logging.Level; +import java.util.logging.LogManager; import javax.swing.SwingUtilities; import org.netbeans.junit.*; import junit.textui.TestRunner; import org.openide.ErrorManager; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.filesystems.Repository; import org.openide.util.Lookup; import org.xml.sax.SAXParseException; @@ -34,21 +40,21 @@ super(name); } - public static void main(String[] args) { - TestRunner.run(new NbTestSuite(NbErrorManagerTest.class)); - } - - private NbErrorManager err; + private ErrorManager err; private ByteArrayOutputStream w; protected void setUp() throws Exception { + // initialize properties + Class.forName(CoreBridgeImpl.class.getName(), true, CoreBridgeImpl.class.getClassLoader()); + w = new ByteArrayOutputStream(); - err = new NbErrorManager(new PrintStream(w)); + err = ErrorManager.getDefault(); + NbErrorManager.logWriter = new PrintStream(w); System.setProperty("netbeans.user", getWorkDirPath()); } public void testEMFound() throws Exception { - assertEquals(NbErrorManager.class, Lookup.getDefault().lookup(ErrorManager.class).getClass()); + assertNotNull(ErrorManager.getDefault()); } public void testBasicNotify() throws Exception { @@ -74,7 +80,17 @@ err2.log("sub msg #1"); s = w.toString(); assertTrue(s.indexOf("sub msg #1") == -1); - System.setProperty("quux.hoho", "0"); + + // configuration thru system properties is not going to work now + // System.setProperty("quux.hoho", "0"); + FileObject fo = Repository.getDefault().getDefaultFileSystem().getRoot(); + fo = FileUtil.createData(fo, "Logging/SomeLogging.txt"); // NOI18N + FileLock lock = fo.lock(); + OutputStream os = fo.getOutputStream(lock); + os.write("quux.hoho.level=100\n".getBytes()); + os.close(); + lock.releaseLock(); + err2 = err.getInstance("quux.hoho.yaya"); assertTrue(err2.isLoggable(ErrorManager.INFORMATIONAL)); err2.log("sub msg #2"); @@ -187,8 +203,8 @@ public void testNotifyException() throws Exception { IOException ioe = new IOException("unloc msg"); err.annotate(ioe, "loc msg"); - NbErrorManager.Exc x = err.createExc(ioe, ErrorManager.USER); - assertEquals(ErrorManager.USER, x.getSeverity()); + NbErrorManager.Exc x = NbErrorManager.ROOT.createExc(ioe, Level.INFO); + assertEquals(Level.INFO, x.getSeverity()); assertEquals("loc msg", x.getLocalizedMessage()); assertTrue(x.isLocalized()); // could do more here... @@ -202,8 +218,8 @@ // Simple exception is EXCEPTION. Throwable t = new IOException("unloc msg"); - NbErrorManager.Exc x = err.createExc(t, ErrorManager.UNKNOWN); - assertEquals(ErrorManager.EXCEPTION, x.getSeverity()); + NbErrorManager.Exc x = NbErrorManager.ROOT.createExc(t, null); + assertEquals(Level.WARNING, x.getSeverity()); assertEquals("unloc msg", x.getMessage()); assertEquals("unloc msg", x.getLocalizedMessage()); assertFalse(x.isLocalized()); @@ -211,8 +227,8 @@ // Same when there is unloc debug info attached. t = new IOException("unloc msg"); err.annotate(t, ErrorManager.UNKNOWN, "some debug info", null, null, null); - x = err.createExc(t, ErrorManager.UNKNOWN); - assertEquals(ErrorManager.EXCEPTION, x.getSeverity()); + x = NbErrorManager.ROOT.createExc(t, null); + assertEquals(Level.WARNING, x.getSeverity()); assertEquals("unloc msg", x.getMessage()); assertEquals("unloc msg", x.getLocalizedMessage()); assertFalse(x.isLocalized()); @@ -221,8 +237,8 @@ t = new IOException("unloc msg"); Throwable t2 = new IOException("unloc msg #2"); err.annotate(t, ErrorManager.UNKNOWN, null, null, t2, null); - x = err.createExc(t, ErrorManager.UNKNOWN); - assertEquals(ErrorManager.EXCEPTION, x.getSeverity()); + x = NbErrorManager.ROOT.createExc(t, null); + assertEquals(Level.WARNING, x.getSeverity()); assertEquals("unloc msg", x.getMessage()); assertEquals("unloc msg", x.getLocalizedMessage()); assertFalse(x.isLocalized()); @@ -231,8 +247,8 @@ // set the severity for the exception. t = new IOException("unloc msg"); err.annotate(t, ErrorManager.USER, null, "loc msg", null, null); - x = err.createExc(t, ErrorManager.UNKNOWN); - assertEquals(ErrorManager.USER, x.getSeverity()); + x = NbErrorManager.ROOT.createExc(t, null); + assertEquals(Level.INFO, x.getSeverity()); assertEquals("unloc msg", x.getMessage()); assertEquals("loc msg", x.getLocalizedMessage()); assertTrue(x.isLocalized()); @@ -242,8 +258,8 @@ t2 = new IOException("unloc msg #2"); err.annotate(t2, ErrorManager.USER, null, "loc msg", null, null); err.annotate(t, ErrorManager.UNKNOWN, null, null, t2, null); - x = err.createExc(t, ErrorManager.UNKNOWN); - assertEquals(ErrorManager.USER, x.getSeverity()); + x = NbErrorManager.ROOT.createExc(t, null); + assertEquals(Level.INFO, x.getSeverity()); assertEquals("unloc msg", x.getMessage()); assertEquals("loc msg", x.getLocalizedMessage()); assertTrue(x.isLocalized()); @@ -253,8 +269,8 @@ err.annotate(t2, ErrorManager.USER, null, "loc msg", null, null); t = new IOException("loc msg"); err.annotate(t, ErrorManager.USER, null, null, t2, null); - x = err.createExc(t, ErrorManager.UNKNOWN); - assertEquals(ErrorManager.USER, x.getSeverity()); + x = NbErrorManager.ROOT.createExc(t, null); + assertEquals(Level.INFO, x.getSeverity()); assertEquals("loc msg", x.getMessage()); assertEquals("loc msg", x.getLocalizedMessage()); // Note that it is stil considered localized even though the messages Index: openide/util/test/unit/src/org/openide/ErrorManagerDelegatesToLoggingTest.java =================================================================== RCS file: openide/util/test/unit/src/org/openide/ErrorManagerDelegatesToLoggingTest.java diff -N openide/util/test/unit/src/org/openide/ErrorManagerDelegatesToLoggingTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openide/util/test/unit/src/org/openide/ErrorManagerDelegatesToLoggingTest.java 18 Dec 2005 18:41:56 -0000 @@ -0,0 +1,140 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License" You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.openide; + +import java.io.IOException; +import java.io.StringBufferInputStream; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import junit.framework.*; +import org.netbeans.junit.*; + +/** Test for general ErrorManager functionality. + * + * @author Jaroslav Tulach + */ +public class ErrorManagerDelegatesToLoggingTest extends NbTestCase { + + public ErrorManagerDelegatesToLoggingTest(java.lang.String testName) { + super(testName); + } + + protected void setUp () throws IOException { + assertNull ("No ErrorManager in lookup", org.openide.util.Lookup.getDefault ().lookup (ErrorManager.class)); + + + String config = + "handlers=" + MyHandler.class.getName() + "\n" + + ".level=50"; + LogManager.getLogManager().readConfiguration(new StringBufferInputStream(config)); + } + + /** Test of getDefault method, of class org.openide.ErrorManager. */ + public void testGetDefault() { + assertNotNull("There has to be a manager", ErrorManager.getDefault ()); + } + + /** Test of notify method, of class org.openide.ErrorManager. */ + public void testNotify() { + Throwable t = new Throwable (); + ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, t); + MyHandler.assertNotify (ErrorManager.INFORMATIONAL, t); + t = new Throwable (); + ErrorManager.getDefault ().notify (t); + MyHandler.assertNotify (ErrorManager.UNKNOWN, t); + } + + /** Test of log method, of class org.openide.ErrorManager. */ + public void testLog() { + ErrorManager.getDefault ().log (ErrorManager.INFORMATIONAL, "A text"); + MyHandler.assertLog (ErrorManager.INFORMATIONAL, "A text"); + ErrorManager.getDefault ().log ("Another text"); + MyHandler.assertLog (ErrorManager.INFORMATIONAL, "Another text"); + } + + /** Test of isLoggable method, of class org.openide.ErrorManager. */ + public void testIsLoggable() { + ErrorManager.getDefault ().isLoggable(ErrorManager.INFORMATIONAL); + } + + /** Test of annotate method, of class org.openide.ErrorManager. */ + public void testReturnValues () { + Throwable t = new Throwable (); + Throwable value = ErrorManager.getDefault ().annotate(t, ErrorManager.INFORMATIONAL, null, null, null, null); + assertEquals ("Annotate must return the same exception", t, value); + + value = ErrorManager.getDefault ().copyAnnotation (t, new Throwable ()); + assertEquals ("copyAnnotation must return the same exception", t, value); + + value = ErrorManager.getDefault ().attachAnnotations(t, new ErrorManager.Annotation[0]); + assertEquals ("attachAnnotations must return the same exception", t, value); + + } + + // + // Manager to delegate to + // + public static final class MyHandler extends Handler { + public static final StringBuffer messages = new StringBuffer (); + + private String prefix; + + private static int lastSeverity; + private static Throwable lastThrowable; + private static String lastText; + + public static void assertNotify (int sev, Throwable t) { + assertEquals ("Severity is same", sev, lastSeverity); + assertSame ("Throwable is the same", t, lastThrowable); + lastThrowable = null; + lastSeverity = -1; + } + + public static void assertLog (int sev, String t) { + assertEquals ("Severity is same", sev, lastSeverity); + assertEquals ("Text is the same", t, lastText); + lastText = null; + lastSeverity = -1; + } + + public void publish(LogRecord record) { + messages.append(record.getMessage()); + + lastText = record.getMessage(); + lastThrowable = record.getThrown(); + if (Level.WARNING == record.getLevel()) { + lastSeverity = ErrorManager.WARNING; + } + if (Level.INFO == record.getLevel()) { + lastSeverity = ErrorManager.INFORMATIONAL; + } + if (Level.SEVERE == record.getLevel()) { + lastSeverity = ErrorManager.EXCEPTION; + } + if (Level.FINE == record.getLevel()) { + lastSeverity = ErrorManager.UNKNOWN; + } + } + + public void flush() { + } + + public void close() throws SecurityException { + } + + } + +} Index: openide/util/test/unit/src/org/openide/ErrorManagerTest.java =================================================================== RCS file: /cvs/openide/util/test/unit/src/org/openide/ErrorManagerTest.java,v retrieving revision 1.1 diff -u -r1.1 ErrorManagerTest.java --- openide/util/test/unit/src/org/openide/ErrorManagerTest.java 22 Apr 2005 05:01:57 -0000 1.1 +++ openide/util/test/unit/src/org/openide/ErrorManagerTest.java 18 Dec 2005 18:41:56 -0000 @@ -26,10 +26,6 @@ super(testName); } - public static void main(java.lang.String[] args) { - junit.textui.TestRunner.run(suite()); - } - public static Test suite() { TestSuite suite = new NbTestSuite(ErrorManagerTest.class); Index: openide/util/apichanges.xml =================================================================== RCS file: /cvs/openide/util/apichanges.xml,v retrieving revision 1.11 diff -u -r1.11 apichanges.xml --- openide/util/apichanges.xml 21 Nov 2005 07:35:51 -0000 1.11 +++ openide/util/apichanges.xml 18 Dec 2005 18:41:56 -0000 @@ -22,6 +22,22 @@ Actions API + + + Deprecating ErrorManager + + + + + + If not ErrorManager + is registered in lookup, then we no longer print to System.err + but we use Logger + to log the messages and to exceptions. + + + + Ability to create finished RequestProcessor task Index: openide/util/src/org/openide/ErrorManager.java =================================================================== RCS file: /cvs/openide/util/src/org/openide/ErrorManager.java,v retrieving revision 1.2 diff -u -r1.2 ErrorManager.java --- openide/util/src/org/openide/ErrorManager.java 16 Jun 2005 16:19:45 -0000 1.2 +++ openide/util/src/org/openide/ErrorManager.java 18 Dec 2005 18:41:58 -0000 @@ -14,37 +14,29 @@ package org.openide; import java.util.Collection; +import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; +import java.util.ResourceBundle; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import org.openide.util.Enumerations; import org.openide.util.Lookup; import org.openide.util.LookupEvent; import org.openide.util.LookupListener; import org.openide.util.WeakSet; +import org.openide.util.lookup.Lookups; /** - * A system of managing, annotating, and classifying errors and log messages. + * A deprecated system of managing, annotating, and classifying errors and log messages. *

- * Rather than printing raw exceptions to the console, or popping up dialog boxes - * with exceptions, or implementing custom debug or logging facililities, code may - * use the error manager to access logging and error-reporting in a higher-level - * fashion. Standard error manager implementations can then provide generic ways - * of customizing logging levels for different components, and so on. - *

- *

Especially important is the attaching of annotations such as stack traces to - * exceptions, permitting you to throw an exception of a type permitted by your - * API signature while safely encapsulating the root cause of the problem (in terms - * of other nested exceptions). Code should use {@link #notify(Throwable)} rather - * than directly printing caught exceptions, to make sure nested annotations are not lost. - *

- *

Also localized messages may be annotated to exceptions so that code which can deal - * with a caught exception with a user-visible UI can display a polite and helpful message. - * Messages with no localized annotation can be handled in a default way while the details - * are reserved for the log file. - *

- *

- * There may be zero or more instances of ErrorManager in {@link Lookup#getDefault}. - * All will be delegated to, or a simple backup implementation is available if there are none. + * Rather then using the {@link ErrorManager} consider using JDK's {@link Logger} + * for reporting log events, unwanted exceptions, etc. The methods + * in this class which are deprecated are annotated with a description + * how to use use the {@link Logger} methods to achieve the same goal. *

* *
@@ -58,7 +50,9 @@ * try { * foo.doSomething(); * } catch (IOException ioe) { - * ErrorManager.getDefault().notify(ioe); + * Logger.getAnonymousLogger().log(Level.SEVERE, "msg", ioe); + * // used to be + * // ErrorManager.getDefault().notify(ioe); * } * *

If it is not very important but should be sent to the log file:

@@ -66,6 +60,7 @@ * try { * foo.doSomething(); * } catch (IOException ioe) { + * Logger.getAnonymousLogger().log(Level.CONFIG, "msg", ioe); * ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ioe); * } * @@ -75,8 +70,9 @@ * try { * foo.doSomething(); * } catch (IOException ioe) { - * // Also WARNING or ERROR: - * ErrorManager.getDefault().notify(ErrorManager.USER, ioe); + * Logger.getAnonymousLogger().log(Level.INFO, "msg", ioe); + * // used to be: + * // ErrorManager.getDefault().notify(ErrorManager.USER, ioe); * } * *

You can also specify the severity when you are creating the @@ -94,7 +90,8 @@ * doSomethingElse(); * } catch (IllegalArgumentException iae) { * IOException ioe = new IOException("did not work: " + iae); - * ErrorManager.getDefault().annotate(ioe, iae); + * ioe.initCause(iae); + * // used to be: ErrorManager.getDefault().annotate(ioe, iae); * throw ioe; * } * } @@ -125,10 +122,18 @@ *

  * public void doSomething(File f) throws IOException {
  *     if (!f.isFile()) {
- *         IOException e = new IOException("Not a file: " + f); // NOI18N
- *         // For what the user actually sees:
- *         ErrorManager.getDefault().annotate(e,
- *             NbBundle.getMessage(This.class, "EXC_not_a_file", f));
+ *         class LocalizedMsg extends IOException implements Lookup.Provider {
+ *            LogRecord myRecord;
+ *
+ *            public Lookup getLookup() {
+ *              return Lookups.singleton(myRecord);
+ *            }
+ *         }
+ *
+ *         LocalizedMsg e = new LocalizedMsg("Not a file: " + f); // NOI18N
+ *         e.myRecord.setResourceBundle(NbBundle.getBundle(This.class));
+ *         e.myRecord.setResourceBundleName("EXC_not_a_file");
+ *         e.myRecord.setParameters (new Object[] { f });
  *         throw e;
  *     }
  * }
@@ -142,14 +147,33 @@
  * 
*
  * IOException all = null;
+ * Throwable last = null;
  * for (int i = 0; i < things.length; i++) {
  *     try {
  *          things[i].process();
  *     } catch (ThingProcessingException e) {
  *          if (all == null) {
  *              all = new IOException("Could not process one or more things"); // NOI18N
+ *              last = all;
  *          }
- *          ErrorManager.getDefault().annotate(all, e);
+ *
+ *          class LocalizedMsg extends IOException implements Lookup.Provider {
+ *            LogRecord myRecord;
+ *
+ *            public Lookup getLookup() {
+ *              return Lookups.singleton(myRecord);
+ *            }
+ *          }
+ *
+ *          LocalizedMsg loc = new LocalizedMsg("Not a file: " + f); // NOI18N
+ *          loc.myRecord.setResourceBundle(NbBundle.getBundle(This.class));
+ *          loc.myRecord.setResourceBundleName("EXC_not_a_file");
+ *          loc.myRecord.setParameters (new Object[] { f });
+ *
+ *          loc.initCause(e);
+ *          last.initCause(loc);
+ *
+ *          last = e;
  *     }
  * }
  * if (all != null) {
@@ -158,12 +182,12 @@
  * 
*
* - *
Logging a warning message
+ *
Logging a warning message just simply uses the JDK's logging API
*
*
  * public void doSomething(String arg) {
  *     if (arg.length() == 0) {
- *         ErrorManager.getDefault().log(ErrorManager.WARNING,
+ *         Logger.getAnnonymousLogger().log(Leverl.WARNING, 
  *             "Warning: doSomething called on empty string");
  *         return;
  *     }
@@ -172,18 +196,18 @@
  * 
*
* - *
Logging messages for some subcomponent
+ *
Logging messages for some subcomponent can be done easily with JDK's logging API
*
*
  * package org.netbeans.modules.foo;
  * class FooModule {
- *     public static final ErrorManager ERR =
- *         ErrorManager.getDefault().getInstance("org.netbeans.modules.foo");
+ *     public static final Logger ERR =
+ *         Logger.getLogger("org.netbeans.modules.foo");
  * }
  * // ...
  * class Something {
  *     public void doSomething(String arg) {
- *         if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
+ *         if (ERR.isLoggable(Level.FINE)) {
  *             ERR.log("Called doSomething with arg " + arg);
  *         }
  *     }
@@ -194,6 +218,7 @@
  * 
  * 
* @author Jaroslav Tulach, Jesse Glick + * @deprecated use {@link Logger} from the JDK's APIs */ public abstract class ErrorManager extends Object { // XXX note that these levels accidentally used hex rather than binary, @@ -487,6 +512,9 @@ * The set of instances we delegate to. Elements type is ErrorManager. */ private Set delegates = new HashSet(); + + /** fallback logger to send messages to */ + private Logger logger; /** * A set that has to be updated when the list of delegates @@ -504,6 +532,15 @@ public DelegatingErrorManager(String name) { this.name = name; } + + /** Initializes the logger. + */ + Logger logger() { + if (logger == null) { + logger = Logger.getLogger(this.name); + } + return logger; + } /** If the name is not empty creates new instance of * DelegatingErrorManager. Adds it to createdByMe. @@ -550,9 +587,45 @@ /** Calls all delegates. */ public Throwable annotate( - Throwable t, int severity, String message, String localizedMessage, Throwable stackTrace, + Throwable t, int severity, String message, final String localizedMessage, Throwable stackTrace, java.util.Date date ) { + if (delegates.isEmpty()) { + LogRecord rec = new LogRecord(convertSeverity(severity, true, Level.ALL), message); + if (stackTrace != null) { + rec.setThrown(stackTrace); + } + if (date != null) { + rec.setMillis(date.getTime()); + } + if (localizedMessage != null) { + ResourceBundle rb = new ResourceBundle() { + public Object handleGetObject(String key) { + if ("msg".equals(key)) { // NOI18N + return localizedMessage; + } else { + return null; + } + } + + public Enumeration getKeys() { + return Enumerations.singleton("msg"); // NOI18N + } + }; + rec.setResourceBundle(rb); + rec.setResourceBundleName("msg"); // NOI18N + } + + Throwable last = t; + while (last.getCause() != null) { + last = last.getCause(); + } + + last.initCause(new LogException(rec)); + + return t; + } + for (Iterator i = delegates.iterator(); i.hasNext();) { ErrorManager em = (ErrorManager) i.next(); em.annotate(t, severity, message, localizedMessage, stackTrace, date); @@ -564,7 +637,8 @@ /** Calls all delegates. */ public void notify(int severity, Throwable t) { if (delegates.isEmpty()) { - t.printStackTrace(); + logger().log(convertSeverity(severity, true, Level.SEVERE), t.getMessage(), t); + return; } try { @@ -589,26 +663,10 @@ throw new IllegalArgumentException("ErrorManager.log(UNKNOWN, ...) is not permitted"); // NOI18N } - if (delegates.isEmpty() && (severity > INFORMATIONAL)) { - String sev; - switch (severity) { - case WARNING: - sev = "WARNING"; // NOI18N - break; - case USER: - sev = "USER"; // NOI18N - break; - case EXCEPTION: - sev = "EXCEPTION"; // NOI18N - break; - case ERROR: - sev = "ERROR"; // NOI18N - break; - default: - sev = String.valueOf(severity); - break; - } - System.err.println("[" + sev + "] " + s); // NOI18N + if (delegates.isEmpty()) { + Level sev = convertSeverity(severity, false, Level.FINE); + logger().log(sev, s); + return; } for (Iterator i = delegates.iterator(); i.hasNext();) { @@ -617,14 +675,40 @@ } } + private static Level convertSeverity(final int severity, boolean forException, Level def) { + Level sev; + + switch (severity) { + case WARNING: + sev = Level.WARNING; + break; + case USER: + sev = Level.INFO; + break; + case EXCEPTION: + sev = Level.SEVERE; + break; + case ERROR: + sev = Level.SEVERE; + break; + case INFORMATIONAL: + sev = forException ? Level.CONFIG: Level.FINE; + break; + default: + sev = def; + break; + } + return sev; + } + /** Calls all delegates. */ public boolean isLoggable(int severity) { if (severity == UNKNOWN) { throw new IllegalArgumentException("ErrorManager.isLoggable(UNKNOWN) is not permitted"); // NOI18N } - if (delegates.isEmpty() && (severity > INFORMATIONAL)) { - return true; + if (delegates.isEmpty()) { + return logger().isLoggable(convertSeverity(severity, false, null)); } for (Iterator i = delegates.iterator(); i.hasNext();) { @@ -645,7 +729,7 @@ } if (delegates.isEmpty()) { - return true; + return logger().isLoggable(convertSeverity(severity, true, null)); } for (Iterator i = delegates.iterator(); i.hasNext();) { @@ -712,4 +796,19 @@ } } } + + /** An exception that has a log record associated with itself, so + * the NbErrorManager can extract info about the annotation. + */ + private static final class LogException extends Exception implements Lookup.Provider { + private Lookup lookup; + + public LogException(LogRecord rec) { + this.lookup = Lookups.singleton(rec); + } + + public Lookup getLookup() { + return this.lookup; + } + } // end LogException } Index: xtest/nbjunit/src/org/netbeans/junit/Log.java =================================================================== RCS file: xtest/nbjunit/src/org/netbeans/junit/Log.java diff -N xtest/nbjunit/src/org/netbeans/junit/Log.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ xtest/nbjunit/src/org/netbeans/junit/Log.java 18 Dec 2005 18:41:58 -0000 @@ -0,0 +1,68 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.junit; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import junit.framework.Assert; + +/** Collects log messages. + * + * @author Jaroslav Tulach + */ +public class Log extends Handler { + private static NbTestCase current; + + /** Creates a new instance of Log */ + public Log() { + } + + static void configure(Level lev, NbTestCase current) throws IOException { + String s = "handlers=" + Log.class.getName() + "\n" + + ".level=" + lev.intValue() + "\n"; + ByteArrayInputStream is = new ByteArrayInputStream(s.getBytes("utf-8")); + LogManager.getLogManager().readConfiguration(is); + + Log.current = current; + } + + public void publish(LogRecord record) { + Assert.assertNotNull("There is a case: ", current); + + StringBuffer sb = new StringBuffer(); + sb.append('['); + sb.append(record.getLoggerName()); + sb.append("] THREAD: "); + sb.append(Thread.currentThread().getName()); + sb.append(" MSG: "); + sb.append(record.getMessage()); + + current.getLog().println(sb.toString()); + + if (record.getThrown() != null) { + record.getThrown().printStackTrace(current.getLog()); + } + } + + public void flush() { + } + + public void close() throws SecurityException { + } + +} Index: xtest/nbjunit/src/org/netbeans/junit/NbTestCase.java =================================================================== RCS file: /cvs/xtest/nbjunit/src/org/netbeans/junit/NbTestCase.java,v retrieving revision 1.34 diff -u -r1.34 NbTestCase.java --- xtest/nbjunit/src/org/netbeans/junit/NbTestCase.java 7 Dec 2005 09:53:33 -0000 1.34 +++ xtest/nbjunit/src/org/netbeans/junit/NbTestCase.java 18 Dec 2005 18:41:58 -0000 @@ -17,6 +17,7 @@ import java.io.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Field; +import java.util.logging.Level; import junit.framework.TestCase; import junit.framework.TestResult; import junit.framework.AssertionFailedError; @@ -92,6 +93,16 @@ } /** + * Allows easy collecting of log messages send thru java.util.logging API. + * Overwrite and return the log level to collect logs to logging file. + * @see #getLog() + * @return null + */ + protected Level logLevel() { + return null; + } + + /** * Runs the test case and collects the results in TestResult. * overrides JUnit run, because filter check * and handling of {@link #runInEQ} @@ -130,6 +141,12 @@ */ public void runBare() throws Throwable { setUp(); + + Level lev = logLevel(); + if (lev != null) { + Log.configure(lev, this); + } + long now = System.currentTimeMillis(); try { runTest(); Index: xtest/nbjunit/test/unit/src/org/netbeans/junit/LoggingTest.java =================================================================== RCS file: /cvs/xtest/nbjunit/test/unit/src/org/netbeans/junit/LoggingTest.java,v retrieving revision 1.3 diff -u -r1.3 LoggingTest.java --- xtest/nbjunit/test/unit/src/org/netbeans/junit/LoggingTest.java 7 Dec 2005 09:53:33 -0000 1.3 +++ xtest/nbjunit/test/unit/src/org/netbeans/junit/LoggingTest.java 18 Dec 2005 18:41:58 -0000 @@ -14,8 +14,11 @@ package org.netbeans.junit; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.PrintStream; +import java.util.logging.Level; +import java.util.logging.Logger; /** Checks that we can do proper logging. * @@ -37,7 +40,7 @@ NbTestSuite suite = new NbTestSuite(LoggingTest.class); return suite; } - + protected void setUp() throws Exception { clearWorkDir(); } @@ -55,7 +58,7 @@ } /** Test of NbTestCase#trimLogFiles method. It should trim size of all files - * in test case workdir to 1 MB. The method is called at the end of + * in test case workdir to 1 MB. The method is called at the end of * NbTestCase#run method. */ public void testTrimLogFiles() throws IOException { @@ -83,4 +86,29 @@ } } } + + protected Level logLevel() { + return Level.WARNING; + } + + public void testLoggingUtil() throws Exception { + Logger log = Logger.getLogger(getName()); + log.log(Level.SEVERE, "Ahoj"); + log.log(Level.FINE, "Jardo"); + + File f = new File(getWorkDir(), getName() + ".log"); + assertEquals("Log file exists", true, f.exists()); + + byte[] arr = new byte[(int)f.length()]; + FileInputStream is = new FileInputStream(f); + int l = is.read(arr); + assertEquals(l, arr.length); + + String s = new String(arr); + if (s.indexOf("Ahoj") == -1) { + fail("There should be Ahoj\n" + s); + } + assertEquals("Not logged for FINE: " + s, -1, s.indexOf("Jardo")); + } + }