/** * Method to find a named logger. * * <p>Note that since untrusted code may create loggers with arbitrary names this method should * not be relied on to find Loggers for security sensitive logging. It is also important to note * that the Logger associated with the String {@code name} may be garbage collected at any time if * there is no strong reference to the Logger. The caller of this method must check the return * value for null in order to properly handle the case where the Logger has been garbage * collected. * * <p> * * @param name name of the logger * @return matching logger or null if none is found */ public synchronized Logger getLogger(String name) { LoggerWeakRef ref = namedLoggers.get(name); if (ref == null) { return null; } Logger logger = ref.get(); if (logger == null) { // Hashtable holds stale weak reference // to a logger which has been GC-ed. namedLoggers.remove(name); } return logger; }
// Recursive method to walk the tree below a node and set // a new parent logger. void walkAndSetParent(Logger parent) { if (children == null) { return; } Iterator<LogNode> values = children.values().iterator(); while (values.hasNext()) { LogNode node = values.next(); LoggerWeakRef ref = node.loggerRef; Logger logger = (ref == null) ? null : ref.get(); if (logger == null) { node.walkAndSetParent(parent); } else { doSetParent(logger, parent); } } }
final synchronized void drainLoggerRefQueueBounded() { for (int i = 0; i < MAX_ITERATIONS; i++) { if (loggerRefQueue == null) { // haven't finished loading LogManager yet break; } // this hack is needed to build this for release jdk6 WeakReference<Logger> dummy = (WeakReference<Logger>) loggerRefQueue.poll(); LoggerWeakRef ref = (LoggerWeakRef) dummy; if (ref == null) { break; } // a Logger object has been GC'ed so clean it up ref.dispose(); } }
/** * Add a named logger. This does nothing and returns false if a logger with the same name is * already registered. * * <p>The Logger factory methods call this method to register each newly created Logger. * * <p>The application should retain its own reference to the Logger object to avoid it being * garbage collected. The LogManager may only retain a weak reference. * * @param logger the new logger. * @return true if the argument logger was registered successfully, false if a logger of that name * already exists. * @exception NullPointerException if the logger name is null. */ public synchronized boolean addLogger(Logger logger) { final String name = logger.getName(); if (name == null) { throw new NullPointerException(); } // cleanup some Loggers that have been GC'ed drainLoggerRefQueueBounded(); LoggerWeakRef ref = namedLoggers.get(name); if (ref != null) { if (ref.get() == null) { // It's possible that the Logger was GC'ed after the // drainLoggerRefQueueBounded() call above so allow // a new one to be registered. namedLoggers.remove(name); } else { // We already have a registered logger with the given name. return false; } } // We're adding a new logger. // Note that we are creating a weak reference here. ref = new LoggerWeakRef(logger); namedLoggers.put(name, ref); // Apply any initial level defined for the new logger. Level level = getLevelProperty(name + ".level", null); if (level != null) { doSetLevel(logger, level); } // Do we have a per logger handler too? // Note: this will add a 200ms penalty loadLoggerHandlers(logger, name, name + ".handlers"); processParentHandlers(logger, name); // Find the new node and its parent. LogNode node = findNode(name); node.loggerRef = ref; Logger parent = null; LogNode nodep = node.parent; while (nodep != null) { LoggerWeakRef nodeRef = nodep.loggerRef; if (nodeRef != null) { parent = nodeRef.get(); if (parent != null) { break; } } nodep = nodep.parent; } if (parent != null) { doSetParent(logger, parent); } // Walk over the children and tell them we are their new parent. node.walkAndSetParent(logger); // new LogNode is ready so tell the LoggerWeakRef about it ref.setNode(node); return true; }