1 /* Logger.java -- a class for logging messages
2 Copyright (C) 2002, 2004, 2006, 2007 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.util.logging;
41 /*import gnu.java.lang.CPStringBuilder;
43 import java.util.List;
44 import java.util.MissingResourceException;
45 import java.util.ResourceBundle;
46 import java.security.AccessController;
47 import java.security.PrivilegedAction;*/
50 * A Logger is used for logging information about events. Usually, there is a
51 * seprate logger for each subsystem or component, although there is a shared
52 * instance for components that make only occasional use of the logging
55 * It is common to name a logger after the name of a corresponding Java package.
56 * Loggers are organized into a hierarchical namespace; for example, the logger
57 * <code>"org.gnu.foo"</code> is the <em>parent</em> of logger
58 * <code>"org.gnu.foo.bar"</code>.
60 * A logger for a named subsystem can be obtained through {@link
61 * java.util.logging.Logger#getLogger(java.lang.String)}. However, only code
62 * which has been granted the permission to control the logging infrastructure
63 * will be allowed to customize that logger. Untrusted code can obtain a
64 * private, anonymous logger through {@link #getAnonymousLogger()} if it wants
65 * to perform any modifications to the logger.
67 * FIXME: Write more documentation.
69 * @author Sascha Brawer (brawer@acm.org)
73 static final Logger root = new Logger("", null);
76 * A logger provided to applications that make only occasional use of the
77 * logging framework, typically early prototypes. Serious products are
78 * supposed to create and use their own Loggers, so they can be controlled
81 public static final Logger globalLog;
84 * Use to lock methods on this class instead of calling synchronize on methods
85 * to avoid deadlocks. Yeah, no kidding, we got them :)
87 private static final Object[] lock = new Object[0];
91 // Our class might be initialized from an unprivileged context
92 globalLog = new Logger("global", null);/*(Logger) AccessController.doPrivileged(new PrivilegedAction()
96 return getLogger("global");
102 * The name of the Logger, or <code>null</code> if the logger is anonymous.
104 * A previous version of the GNU Classpath implementation granted untrusted
105 * code the permission to control any logger whose name was null. However,
106 * test code revealed that the Sun J2SE 1.4 reference implementation enforces
107 * the security control for any logger that was not created through
108 * getAnonymousLogger, even if it has a null name. Therefore, a separate flag
109 * {@link Logger#anonymous} was introduced.
111 private final String name;
114 * The name of the resource bundle used for localization.
116 * This variable cannot be declared as <code>final</code> because its value
117 * can change as a result of calling getLogger(String,String).
119 private String resourceBundleName;
122 * The resource bundle used for localization.
124 * This variable cannot be declared as <code>final</code> because its value
125 * can change as a result of calling getLogger(String,String).
127 //private ResourceBundle resourceBundle;
129 //private Filter filter;
131 //private final List handlerList = new java.util.ArrayList(4);
133 //private Handler[] handlers = new Handler[0];
136 * Indicates whether or not this logger is anonymous. While a
137 * LoggingPermission is required for any modifications to a normal logger,
138 * untrusted code can obtain an anonymous logger and modify it according to
141 * A previous version of the GNU Classpath implementation granted access to
142 * every logger whose name was null. However, test code revealed that the Sun
143 * J2SE 1.4 reference implementation enforces the security control for any
144 * logger that was not created through getAnonymousLogger, even if it has a
147 private boolean anonymous;
149 private boolean useParentHandlers;
153 private Logger parent;
156 * Constructs a Logger for a subsystem. Most applications do not need to
157 * create new Loggers explicitly; instead, they should call the static factory
158 * methods {@link #getLogger(java.lang.String,java.lang.String) getLogger}
159 * (with ResourceBundle for localization) or
160 * {@link #getLogger(java.lang.String) getLogger} (without ResourceBundle),
163 * @param name the name for the logger, for example "java.awt" or
164 * "com.foo.bar". The name should be based on the name of the
165 * package issuing log records and consist of dot-separated Java
167 * @param resourceBundleName the name of a resource bundle for localizing
168 * messages, or <code>null</code> to indicate that messages do
169 * not need to be localized.
170 * @throws java.util.MissingResourceException if
171 * <code>resourceBundleName</code> is not <code>null</code>
172 * and no such bundle could be located.
174 protected Logger(String name, String resourceBundleName)
175 //throws MissingResourceException
178 this.resourceBundleName = resourceBundleName;
180 /*if (resourceBundleName == null)
181 resourceBundle = null;
183 resourceBundle = ResourceBundle.getBundle(resourceBundleName);*/
188 * This is null when the root logger is being constructed, and the root
193 useParentHandlers = (parent != null);
197 * Finds a registered logger for a subsystem, or creates one in case no logger
198 * has been registered yet.
200 * @param name the name for the logger, for example "java.awt" or
201 * "com.foo.bar". The name should be based on the name of the
202 * package issuing log records and consist of dot-separated Java
204 * @throws IllegalArgumentException if a logger for the subsystem identified
205 * by <code>name</code> has already been created, but uses a a
206 * resource bundle for localizing messages.
207 * @throws NullPointerException if <code>name</code> is <code>null</code>.
208 * @return a logger for the subsystem specified by <code>name</code> that
209 * does not localize messages.
211 public static Logger getLogger(String name)
213 return getLogger(name, null);
217 * Finds a registered logger for a subsystem, or creates one in case no logger
218 * has been registered yet.
220 * If a logger with the specified name has already been registered, the
221 * behavior depends on the resource bundle that is currently associated with
222 * the existing logger.
224 * <li>If the existing logger uses the same resource bundle as specified by
225 * <code>resourceBundleName</code>, the existing logger is returned.</li>
226 * <li>If the existing logger currently does not localize messages, the
227 * existing logger is modified to use the bundle specified by
228 * <code>resourceBundleName</code>. The existing logger is then returned.
229 * Therefore, all subsystems currently using this logger will produce
230 * localized messages from now on.</li>
231 * <li>If the existing logger already has an associated resource bundle, but
232 * a different one than specified by <code>resourceBundleName</code>, an
233 * <code>IllegalArgumentException</code> is thrown.</li>
236 * @param name the name for the logger, for example "java.awt" or
237 * "org.gnu.foo". The name should be based on the name of the
238 * package issuing log records and consist of dot-separated Java
240 * @param resourceBundleName the name of a resource bundle for localizing
241 * messages, or <code>null</code> to indicate that messages do
242 * not need to be localized.
243 * @return a logger for the subsystem specified by <code>name</code>.
244 * @throws java.util.MissingResourceException if
245 * <code>resourceBundleName</code> is not <code>null</code>
246 * and no such bundle could be located.
247 * @throws IllegalArgumentException if a logger for the subsystem identified
248 * by <code>name</code> has already been created, but uses a
249 * different resource bundle for localizing messages.
250 * @throws NullPointerException if <code>name</code> is <code>null</code>.
252 public static Logger getLogger(String name, String resourceBundleName)
254 LogManager lm = LogManager.getLogManager();
258 throw new /*NullPointer*/Exception("NullPointerException");
261 * Without synchronized(lm), it could happen that another thread would
262 * create a logger between our calls to getLogger and addLogger. While
263 * addLogger would indicate this by returning false, we could not be sure
264 * that this other logger was still existing when we called getLogger a
265 * second time in order to retrieve it -- note that LogManager is only
266 * allowed to keep weak references to registered loggers, so Loggers can be
267 * garbage collected at any time in general, and between our call to
268 * addLogger and our second call go getLogger in particular. Of course, we
269 * assume here that LogManager.addLogger etc. are synchronizing on the
270 * global LogManager object. There is a comment in the implementation of
271 * LogManager.addLogger referring to this comment here, so that any change
272 * in the synchronization of LogManager will be reflected here.
278 result = lm.getLogger(name);
281 boolean couldBeAdded;
283 result = new Logger(name, resourceBundleName);
284 couldBeAdded = lm.addLogger(result);
286 throw new /*IllegalState*/Exception("cannot register new logger");
291 * The logger already exists. Make sure it uses the same
292 * resource bundle for localizing messages.
294 /*String existingBundleName = result.getResourceBundleName();
297 * The Sun J2SE 1.4 reference implementation will return the
298 * registered logger object, even if it does not have a resource
299 * bundle associated with it. However, it seems to change the
300 * resourceBundle of the registered logger to the bundle whose
301 * name was passed to getLogger.
303 /*if ((existingBundleName == null) &&
304 (resourceBundleName != null))
307 * If ResourceBundle.getBundle throws an exception, the
308 * existing logger will be unchanged. This would be
309 * different if the assignment to resourceBundleName came
312 /*result.resourceBundle =
313 ResourceBundle.getBundle(resourceBundleName);
315 result.resourceBundleName = resourceBundleName;
319 if ((existingBundleName != resourceBundleName)
320 && ((existingBundleName == null)
321 || !existingBundleName.equals(resourceBundleName)))
323 throw new IllegalArgumentException();
333 * Creates a new, unnamed logger. Unnamed loggers are not registered in the
334 * namespace of the LogManager, and no special security permission is required
335 * for changing their state. Therefore, untrusted applets are able to modify
336 * their private logger instance obtained through this method.
338 * The parent of the newly created logger will the the root logger, from which
339 * the level threshold and the handlers are inherited.
341 /*public static Logger getAnonymousLogger()
343 return getAnonymousLogger(null);
347 * Creates a new, unnamed logger. Unnamed loggers are not registered in the
348 * namespace of the LogManager, and no special security permission is required
349 * for changing their state. Therefore, untrusted applets are able to modify
350 * their private logger instance obtained through this method.
352 * The parent of the newly created logger will the the root logger, from which
353 * the level threshold and the handlers are inherited.
355 * @param resourceBundleName the name of a resource bundle for localizing
356 * messages, or <code>null</code> to indicate that messages do
357 * not need to be localized.
358 * @throws java.util.MissingResourceException if
359 * <code>resourceBundleName</code> is not <code>null</code>
360 * and no such bundle could be located.
362 /*public static Logger getAnonymousLogger(String resourceBundleName)
363 throws MissingResourceException
367 result = new Logger(null, resourceBundleName);
368 result.anonymous = true;
373 * Returns the name of the resource bundle that is being used for localizing
376 * @return the name of the resource bundle used for localizing messages, or
377 * <code>null</code> if the parent's resource bundle is used for
380 /*public String getResourceBundleName()
384 return resourceBundleName;
389 * Returns the resource bundle that is being used for localizing messages.
391 * @return the resource bundle used for localizing messages, or
392 * <code>null</code> if the parent's resource bundle is used for
395 /*public ResourceBundle getResourceBundle()
399 return resourceBundle;
404 * Returns the severity level threshold for this <code>Handler</code>. All
405 * log records with a lower severity level will be discarded; a log record of
406 * the same or a higher level will be published unless an installed
407 * <code>Filter</code> decides to discard it.
409 * @return the severity level below which all log messages will be discarded,
410 * or <code>null</code> if the logger inherits the threshold from
413 public Level getLevel()
422 * Returns whether or not a message of the specified level would be logged by
425 * @throws NullPointerException if <code>level</code> is <code>null</code>.
427 public boolean isLoggable(Level level)
431 if (this.level != null)
432 return this.level.intValue() <= level.intValue();
435 return parent.isLoggable(level);
442 * Sets the severity level threshold for this <code>Handler</code>. All log
443 * records with a lower severity level will be discarded immediately. A log
444 * record of the same or a higher level will be published unless an installed
445 * <code>Filter</code> decides to discard it.
447 * @param level the severity level below which all log messages will be
448 * discarded, or <code>null</code> to indicate that the logger
449 * should inherit the threshold from its parent.
450 * @throws SecurityException if this logger is not anonymous, a security
451 * manager exists, and the caller is not granted the permission to
452 * control the logging infrastructure by having
453 * LoggingPermission("control"). Untrusted code can obtain an
454 * anonymous logger through the static factory method
455 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
457 public void setLevel(Level level)
462 * An application is allowed to control an anonymous logger without
463 * having the permission to control the logging infrastructure.
466 LogManager.getLogManager().checkAccess();*/
472 /*public Filter getFilter()
481 * @throws SecurityException if this logger is not anonymous, a security
482 * manager exists, and the caller is not granted the permission to
483 * control the logging infrastructure by having
484 * LoggingPermission("control"). Untrusted code can obtain an
485 * anonymous logger through the static factory method
486 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
488 /*public void setFilter(Filter filter) throws SecurityException
493 * An application is allowed to control an anonymous logger without
494 * having the permission to control the logging infrastructure.
497 LogManager.getLogManager().checkAccess();
499 this.filter = filter;
504 * Returns the name of this logger.
506 * @return the name of this logger, or <code>null</code> if the logger is
509 public String getName()
512 * Note that the name of a logger cannot be changed during its lifetime, so
513 * no synchronization is needed.
519 * Passes a record to registered handlers, provided the record is considered
520 * as loggable both by {@link #isLoggable(Level)} and a possibly installed
521 * custom {@link #setFilter(Filter) filter}.
523 * If the logger has been configured to use parent handlers, the record will
524 * be forwarded to the parent of this logger in addition to being processed by
525 * the handlers registered with this logger.
527 * The other logging methods in this class are convenience methods that merely
528 * create a new LogRecord and pass it to this method. Therefore, subclasses
529 * usually just need to override this single method for customizing the
532 * @param record the log record to be inspected and possibly forwarded.
534 public void log(LogRecord record)
536 // TODO System.println("Unimplemented Logger.log(LogRecord)");
537 /*synchronized (lock)
539 if (!isLoggable(record.getLevel()))
542 if ((filter != null) && ! filter.isLoggable(record))
546 * If no logger name has been set for the log record, use the name of
549 /*if (record.getLoggerName() == null)
550 record.setLoggerName(name);
553 * Avoid that some other thread is changing the logger hierarchy while
554 * we are traversing it.
556 /*synchronized (LogManager.getLogManager())
558 Logger curLogger = this;
563 * The Sun J2SE 1.4 reference implementation seems to call the
564 * filter only for the logger whose log method is called, never
565 * for any of its parents. Also, parent loggers publish log
566 * record whatever their level might be. This is pretty weird,
567 * but GNU Classpath tries to be as compatible as possible to
568 * the reference implementation.
570 /*for (int i = 0; i < curLogger.handlers.length; i++)
571 curLogger.handlers[i].publish(record);
573 if (curLogger.getUseParentHandlers() == false)
576 curLogger = curLogger.getParent();
578 while (parent != null);
583 public void log(Level level, String message)
585 if (isLoggable(level))
586 log(level, message, (Object[]) null);
589 public void log(Level level, String message, Object param)
593 if (isLoggable(level))
595 /*StackTraceElement*/ Object caller = getCallerStackFrame();
596 logp(level, /*caller != null ? caller.getClassName() : */"<unknown>",
597 /*caller != null ? caller.getMethodName() : */"<unknown>",
603 public void log(Level level, String message, Object[] params)
607 if (isLoggable(level))
609 /*StackTraceElement*/ Object caller = getCallerStackFrame();
610 logp(level, /*caller != null ? caller.getClassName() : */"<unknown>",
611 /*caller != null ? caller.getMethodName() : */"<unknown>",
618 public void log(Level level, String message, Throwable thrown)
622 if (isLoggable(level))
624 /*StackTraceElement*/ Object caller = getCallerStackFrame();
625 logp(level, /*caller != null ? caller.getClassName() : */"<unknown>",
626 /*caller != null ? caller.getMethodName() : */"<unknown>",
632 public void logp(Level level, String sourceClass, String sourceMethod,
637 logp(level, sourceClass, sourceMethod, message, (Object[]) null);
641 public void logp(Level level, String sourceClass, String sourceMethod,
642 String message, Object param)
646 logp(level, sourceClass, sourceMethod, message, new Object[] { param });
651 /*private ResourceBundle findResourceBundle()
655 if (resourceBundle != null)
656 return resourceBundle;
659 return parent.findResourceBundle();
665 private void logImpl(Level level, String sourceClass, String sourceMethod,
666 String message, Object[] params)
670 LogRecord rec = new LogRecord(level, message);
672 //rec.setResourceBundle(findResourceBundle());
673 rec.setSourceClassName(sourceClass);
674 rec.setSourceMethodName(sourceMethod);
675 rec.setParameters(params);
681 public void logp(Level level, String sourceClass, String sourceMethod,
682 String message, Object[] params)
686 logImpl(level, sourceClass, sourceMethod, message, params);
690 public void logp(Level level, String sourceClass, String sourceMethod,
691 String message, Throwable thrown)
695 LogRecord rec = new LogRecord(level, message);
697 //rec.setResourceBundle(resourceBundle);
698 rec.setSourceClassName(sourceClass);
699 rec.setSourceMethodName(sourceMethod);
700 rec.setThrown(thrown);
706 public void logrb(Level level, String sourceClass, String sourceMethod,
707 String bundleName, String message)
711 logrb(level, sourceClass, sourceMethod, bundleName, message,
716 public void logrb(Level level, String sourceClass, String sourceMethod,
717 String bundleName, String message, Object param)
721 logrb(level, sourceClass, sourceMethod, bundleName, message,
722 new Object[] { param });
726 public void logrb(Level level, String sourceClass, String sourceMethod,
727 String bundleName, String message, Object[] params)
731 LogRecord rec = new LogRecord(level, message);
733 //rec.setResourceBundleName(bundleName);
734 rec.setSourceClassName(sourceClass);
735 rec.setSourceMethodName(sourceMethod);
736 rec.setParameters(params);
742 public void logrb(Level level, String sourceClass, String sourceMethod,
743 String bundleName, String message, Throwable thrown)
747 LogRecord rec = new LogRecord(level, message);
749 //rec.setResourceBundleName(bundleName);
750 rec.setSourceClassName(sourceClass);
751 rec.setSourceMethodName(sourceMethod);
752 rec.setThrown(thrown);
758 public void entering(String sourceClass, String sourceMethod)
762 if (isLoggable(Level.FINER))
763 logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
767 public void entering(String sourceClass, String sourceMethod, Object param)
771 if (isLoggable(Level.FINER))
772 logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", param);
776 public void entering(String sourceClass, String sourceMethod, Object[] params)
780 if (isLoggable(Level.FINER))
782 //CPStringBuilder buf = new CPStringBuilder(80);
783 //buf.append("ENTRY");
784 String buf = "ENTRY";
785 for (int i = 0; i < params.length; i++)
787 buf += " {" + i + "}"; //buf.append(" {");
792 logp(Level.FINER, sourceClass, sourceMethod, buf.toString(), params);
797 public void exiting(String sourceClass, String sourceMethod)
801 if (isLoggable(Level.FINER))
802 logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
806 public void exiting(String sourceClass, String sourceMethod, Object result)
810 if (isLoggable(Level.FINER))
811 logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
815 public void throwing(String sourceClass, String sourceMethod, Throwable thrown)
819 if (isLoggable(Level.FINER))
820 logp(Level.FINER, sourceClass, sourceMethod, "THROW", thrown);
825 * Logs a message with severity level SEVERE, indicating a serious failure
826 * that prevents normal program execution. Messages at this level should be
827 * understandable to an inexperienced, non-technical end user. Ideally, they
828 * explain in simple words what actions the user can take in order to resolve
832 * @param message the message text, also used as look-up key if the logger is
833 * localizing messages with a resource bundle. While it is possible
834 * to pass <code>null</code>, this is not recommended, since a
835 * logging message without text is unlikely to be helpful.
837 public void severe(String message)
841 if (isLoggable(Level.SEVERE))
842 log(Level.SEVERE, message);
847 * Logs a message with severity level WARNING, indicating a potential problem
848 * that does not prevent normal program execution. Messages at this level
849 * should be understandable to an inexperienced, non-technical end user.
850 * Ideally, they explain in simple words what actions the user can take in
851 * order to resolve the problem.
854 * @param message the message text, also used as look-up key if the logger is
855 * localizing messages with a resource bundle. While it is possible
856 * to pass <code>null</code>, this is not recommended, since a
857 * logging message without text is unlikely to be helpful.
859 public void warning(String message)
863 if (isLoggable(Level.WARNING))
864 log(Level.WARNING, message);
869 * Logs a message with severity level INFO. {@link Level#INFO} is intended for
870 * purely informational messages that do not indicate error or warning
871 * situations. In the default logging configuration, INFO messages will be
872 * written to the system console. For this reason, the INFO level should be
873 * used only for messages that are important to end users and system
874 * administrators. Messages at this level should be understandable to an
875 * inexperienced, non-technical user.
877 * @param message the message text, also used as look-up key if the logger is
878 * localizing messages with a resource bundle. While it is possible
879 * to pass <code>null</code>, this is not recommended, since a
880 * logging message without text is unlikely to be helpful.
882 public void info(String message)
886 if (isLoggable(Level.INFO))
887 log(Level.INFO, message);
892 * Logs a message with severity level CONFIG. {@link Level#CONFIG} is intended
893 * for static configuration messages, for example about the windowing
894 * environment, the operating system version, etc.
896 * @param message the message text, also used as look-up key if the logger is
897 * localizing messages with a resource bundle. While it is possible
898 * to pass <code>null</code>, this is not recommended, since a
899 * logging message without text is unlikely to be helpful.
901 public void config(String message)
905 if (isLoggable(Level.CONFIG))
906 log(Level.CONFIG, message);
911 * Logs a message with severity level FINE. {@link Level#FINE} is intended for
912 * messages that are relevant for developers using the component generating
913 * log messages. Examples include minor, recoverable failures, or possible
916 * @param message the message text, also used as look-up key if the logger is
917 * localizing messages with a resource bundle. While it is possible
918 * to pass <code>null</code>, this is not recommended, since a
919 * logging message without text is unlikely to be helpful.
921 public void fine(String message)
925 if (isLoggable(Level.FINE))
926 log(Level.FINE, message);
931 * Logs a message with severity level FINER. {@link Level#FINER} is intended
932 * for rather detailed tracing, for example entering a method, returning from
933 * a method, or throwing an exception.
935 * @param message the message text, also used as look-up key if the logger is
936 * localizing messages with a resource bundle. While it is possible
937 * to pass <code>null</code>, this is not recommended, since a
938 * logging message without text is unlikely to be helpful.
940 public void finer(String message)
944 if (isLoggable(Level.FINER))
945 log(Level.FINER, message);
950 * Logs a message with severity level FINEST. {@link Level#FINEST} is intended
951 * for highly detailed tracing, for example reaching a certain point inside
952 * the body of a method.
954 * @param message the message text, also used as look-up key if the logger is
955 * localizing messages with a resource bundle. While it is possible
956 * to pass <code>null</code>, this is not recommended, since a
957 * logging message without text is unlikely to be helpful.
959 public void finest(String message)
963 if (isLoggable(Level.FINEST))
964 log(Level.FINEST, message);
969 * Adds a handler to the set of handlers that get notified when a log record
970 * is to be published.
972 * @param handler the handler to be added.
973 * @throws NullPointerException if <code>handler</code> is <code>null</code>.
974 * @throws SecurityException if this logger is not anonymous, a security
975 * manager exists, and the caller is not granted the permission to
976 * control the logging infrastructure by having
977 * LoggingPermission("control"). Untrusted code can obtain an
978 * anonymous logger through the static factory method
979 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
981 public void addHandler(StreamHandler handler) //throws SecurityException
983 // TODO System.println("Unimplemented Logger.addHandler(StreamHandler)");
984 /*synchronized (lock)
987 throw new NullPointerException();
990 * An application is allowed to control an anonymous logger without
991 * having the permission to control the logging infrastructure.
994 LogManager.getLogManager().checkAccess();
996 if (! handlerList.contains(handler))
998 handlerList.add(handler);
999 handlers = getHandlers();
1005 * Removes a handler from the set of handlers that get notified when a log
1006 * record is to be published.
1008 * @param handler the handler to be removed.
1009 * @throws SecurityException if this logger is not anonymous, a security
1010 * manager exists, and the caller is not granted the permission to
1011 * control the logging infrastructure by having
1012 * LoggingPermission("control"). Untrusted code can obtain an
1013 * anonymous logger through the static factory method {@link
1014 * #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
1015 * @throws NullPointerException if <code>handler</code> is <code>null</code>.
1017 /*public void removeHandler(Handler handler) throws SecurityException
1022 * An application is allowed to control an anonymous logger without
1023 * having the permission to control the logging infrastructure.
1026 LogManager.getLogManager().checkAccess();
1028 if (handler == null)
1029 throw new NullPointerException();
1031 handlerList.remove(handler);
1032 handlers = getHandlers();
1037 * Returns the handlers currently registered for this Logger. When a log
1038 * record has been deemed as being loggable, it will be passed to all
1039 * registered handlers for publication. In addition, if the logger uses parent
1040 * handlers (see {@link #getUseParentHandlers() getUseParentHandlers} and
1041 * {@link #setUseParentHandlers(boolean) setUseParentHandlers}, the log
1042 * record will be passed to the parent's handlers.
1044 public Handler[] getHandlers()
1046 /*synchronized (lock)
1049 * We cannot return our internal handlers array because we do not have
1050 * any guarantee that the caller would not change the array entries.
1052 /*return (Handler[]) handlerList.toArray(new Handler[handlerList.size()]);
1054 // TODO System.println("Unimplemented Logger.getHandlers()");
1055 return new Handler[0];
1059 * Returns whether or not this Logger forwards log records to handlers
1060 * registered for its parent loggers.
1062 * @return <code>false</code> if this Logger sends log records merely to
1063 * Handlers registered with itself; <code>true</code> if this Logger
1064 * sends log records not only to Handlers registered with itself, but
1065 * also to those Handlers registered with parent loggers.
1067 /*public boolean getUseParentHandlers()
1071 return useParentHandlers;
1076 * Sets whether or not this Logger forwards log records to handlers registered
1077 * for its parent loggers.
1079 * @param useParentHandlers <code>false</code> to let this Logger send log
1080 * records merely to Handlers registered with itself;
1081 * <code>true</code> to let this Logger send log records not only
1082 * to Handlers registered with itself, but also to those Handlers
1083 * registered with parent loggers.
1084 * @throws SecurityException if this logger is not anonymous, a security
1085 * manager exists, and the caller is not granted the permission to
1086 * control the logging infrastructure by having
1087 * LoggingPermission("control"). Untrusted code can obtain an
1088 * anonymous logger through the static factory method
1089 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
1091 public void setUseParentHandlers(boolean useParentHandlers)
1096 * An application is allowed to control an anonymous logger without
1097 * having the permission to control the logging infrastructure.
1100 LogManager.getLogManager().checkAccess();*/
1102 this.useParentHandlers = useParentHandlers;
1107 * Returns the parent of this logger. By default, the parent is assigned by
1108 * the LogManager by inspecting the logger's name.
1110 * @return the parent of this logger (as detemined by the LogManager by
1111 * inspecting logger names), the root logger if no other logger has a
1112 * name which is a prefix of this logger's name, or <code>null</code>
1113 * for the root logger.
1115 public Logger getParent()
1124 * Sets the parent of this logger. Usually, applications do not call this
1125 * method directly. Instead, the LogManager will ensure that the tree of
1126 * loggers reflects the hierarchical logger namespace. Basically, this method
1127 * should not be public at all, but the GNU implementation follows the API
1130 * @throws NullPointerException if <code>parent</code> is <code>null</code>.
1131 * @throws SecurityException if this logger is not anonymous, a security
1132 * manager exists, and the caller is not granted the permission to
1133 * control the logging infrastructure by having
1134 * LoggingPermission("control"). Untrusted code can obtain an
1135 * anonymous logger through the static factory method
1136 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
1138 public void setParent(Logger parent)
1143 throw new /*NullPointer*/Exception("NullPointerException");
1146 throw new /*IllegalArgument*/Exception(
1147 "the root logger can only have a null parent");
1150 * An application is allowed to control an anonymous logger without
1151 * having the permission to control the logging infrastructure.
1154 LogManager.getLogManager().checkAccess();*/
1156 this.parent = parent;
1161 * Gets the StackTraceElement of the first class that is not this class. That
1162 * should be the initial caller of a logging method.
1164 * @return caller of the initial logging method or null if unknown.
1166 private Object/*StackTraceElement*/ getCallerStackFrame()
1168 /*Throwable t = new Throwable();
1169 StackTraceElement[] stackTrace = t.getStackTrace();
1172 // skip to stackentries until this class
1173 while (index < stackTrace.length
1174 && ! stackTrace[index].getClassName().equals(getClass().getName()))
1177 // skip the stackentries of this class
1178 while (index < stackTrace.length
1179 && stackTrace[index].getClassName().equals(getClass().getName()))
1182 return index < stackTrace.length ? stackTrace[index] : null;*/
1183 // TODO System.println("Logger.getCallerStackFrame() invoked");
1188 * Reset and close handlers attached to this logger. This function is package
1189 * private because it must only be available to the LogManager.
1191 /*void resetLogger()
1193 for (int i = 0; i < handlers.length; i++)
1195 handlers[i].close();
1196 handlerList.remove(handlers[i]);
1198 handlers = getHandlers();