SUGGESTED FIX
Please, see a suggested fix below:
% sccs sccsdiff -r1.51 -r1.53 -c LogManager.java
------- LogManager.java -------
*** /tmp/geta10520 Mon Sep 4 09:27:22 2006
--- /tmp/getb10520 Mon Sep 4 09:27:22 2006
***************
*** 11,16 ****
--- 11,17 ----
import java.io.*;
import java.util.*;
import java.security.*;
+ import java.lang.ref.WeakReference;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.net.URL;
***************
*** 137,143 ****
private final static Level defaultLevel = Level.INFO;
// Table of known loggers. Maps names to Loggers.
! private Hashtable<String,Logger> loggers = new Hashtable<String,Logger>();
// Tree of known loggers
private LogNode root = new LogNode(null);
private Logger rootLogger;
--- 138,145 ----
private final static Level defaultLevel = Level.INFO;
// Table of known loggers. Maps names to Loggers.
! private Hashtable<String,WeakReference<Logger>> loggers =
! new Hashtable<String,WeakReference<Logger>>();
// Tree of known loggers
private LogNode root = new LogNode(null);
private Logger rootLogger;
***************
*** 302,307 ****
--- 304,355 ----
changes.removePropertyChangeListener(l);
}
+ // Add new per logger handlers.
+ // We need to raise privilege here. All our decisions will
+ // be made based on the logging configuration, which can
+ // only be modified by trusted code.
+ private void loadLoggerHandlers(final Logger logger, final String handlersPropertyName,
+ final String name, final boolean addingHandlers) {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ String names[] = parseClassNames(handlersPropertyName);
+ for (int i = 0; i < names.length; i++) {
+ String word = names[i];
+ try {
+ Class clz = ClassLoader.getSystemClassLoader().loadClass(word);
+ Handler h = (Handler) clz.newInstance();
+ try {
+ // Check if there is a property defining the
+ // this handler's level.
+ String levs = getProperty(word + ".level");
+ if (levs != null) {
+ h.setLevel(Level.parse(levs));
+ }
+ } catch (Exception ex) {
+ System.err.println("Can't set level for " + word);
+ // Probably a bad level. Drop through.
+ }
+ // Add this Handler to the logger
+ if (addingHandlers) {
+ logger.addHandler(h);
+ }
+ if (logger != rootLogger) {
+ boolean useParent = getBooleanProperty(name +
+ ".useParentHandlers", true);
+ if (!useParent) {
+ logger.setUseParentHandlers(false);
+ }
+ }
+ } catch (Exception ex) {
+ System.err.println("Can't load log handler \"" + word + "\"");
+ System.err.println("" + ex);
+ ex.printStackTrace();
+ }
+ }
+ return null;
+ }});
+ }
+
/**
* Add a named logger. This does nothing and returns false if a logger
* with the same name is already registered.
***************
*** 324,339 ****
throw new NullPointerException();
}
! Logger old = loggers.get(name);
! if (old != null) {
! // We already have a registered logger with the given name.
! return false;
}
// We're adding a new logger.
! // Note that we are creating a strong reference here that will
! // keep the Logger in existence indefinitely.
! loggers.put(name, logger);
// Apply any initial level defined for the new logger.
Level level = getLevelProperty(name+".level", null);
--- 372,393 ----
throw new NullPointerException();
}
! WeakReference<Logger> ref = loggers.get(name);
! if (ref != null) {
! if (ref.get() == null) {
! // Hashtable holds stale weak reference
! // to a logger which has been GC-ed.
! // Allow to register new one.
! loggers.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.
! loggers.put(name, new WeakReference(logger));
// Apply any initial level defined for the new logger.
Level level = getLevelProperty(name+".level", null);
***************
*** 344,384 ****
// Do we have a per logger handler too?
// Note: this will add a 200ms penalty
if (getProperty(name+".handlers") != null) {
! // This code is taken from the root handler initialization
! AccessController.doPrivileged(new PrivilegedAction() {
! public Object run() {
! // Add new per logger handlers.
! String names[] = parseClassNames(name+".handlers");
! for (int i = 0; i < names.length; i++) {
! String word = names[i];
! try {
! Class clz = ClassLoader.getSystemClassLoader().loadClass(word);
! Handler h = (Handler) clz.newInstance();
! try {
! // Check if there is a property defining the
! // this handler's level.
! String levs = getProperty(word + ".level");
! if (levs != null) {
! h.setLevel(Level.parse(levs));
! }
! boolean useParent = getBooleanProperty(name + ".useParentHandlers", true);
! if (!useParent) {
! getLogger(name).setUseParentHandlers(false);
! }
! } catch (Exception ex) {
! System.err.println("Can't set level for " + word);
! // Probably a bad level. Drop through.
! }
! // Add this Handler to the logger
! getLogger(name).addHandler(h);
! } catch (Exception ex) {
! System.err.println("Can't load log handler \"" + word + "\"");
! System.err.println("" + ex);
! ex.printStackTrace();
! }
! }
! return null;
! }});
} // do we have per logger handlers
// If any of the logger's parents have levels defined,
--- 398,404 ----
// Do we have a per logger handler too?
// Note: this will add a 200ms penalty
if (getProperty(name+".handlers") != null) {
! loadLoggerHandlers(logger, name+".handlers", name, true);
} // do we have per logger handlers
// If any of the logger's parents have levels defined,
***************
*** 390,441 ****
break;
}
String pname = name.substring(0,ix2);
! if (getProperty(pname+".level") != null) {
! // This pname has a level definition. Make sure it exists.
! Logger plogger = Logger.getLogger(pname);
! }
// While we are walking up the tree I can check for our
// own root logger and get its handlers initialized too with
! // the same code
if (getProperty(pname+".handlers") != null) {
! final String nname=pname;
!
! AccessController.doPrivileged(new PrivilegedAction() {
! public Object run() {
! String names[] = parseClassNames(nname+".handlers");
!
! for (int i = 0; i < names.length; i++) {
! String word = names[i];
! try {
! Class clz = ClassLoader.getSystemClassLoader().loadClass(word);
! Handler h = (Handler) clz.newInstance();
! try {
! // Check if there is a property defining the
! // handler's level.
! String levs = getProperty(word + ".level");
! if (levs != null) {
! h.setLevel(Level.parse(levs));
! }
! } catch (Exception ex) {
! System.err.println("Can't set level for " + word);
! // Probably a bad level. Drop through.
! }
! if (getLogger(nname) == null ) {
! Logger nplogger=Logger.getLogger(nname);
! addLogger(nplogger);
! }
! boolean useParent = getBooleanProperty(nname + ".useParentHandlers", true);
! if (!useParent) {
! getLogger(nname).setUseParentHandlers(false);
! }
! } catch (Exception ex) {
! System.err.println("Can't load log handler \"" + word + "\"");
! System.err.println("" + ex);
! ex.printStackTrace();
! }
! }
! return null;
! }});
} //found a parent handler
ix = ix2+1;
--- 410,422 ----
break;
}
String pname = name.substring(0,ix2);
!
// While we are walking up the tree I can check for our
// own root logger and get its handlers initialized too with
! // the same code.
if (getProperty(pname+".handlers") != null) {
! loadLoggerHandlers(Logger.getLogger(pname),
! pname+".handlers", pname, false);
} //found a parent handler
ix = ix2+1;
***************
*** 443,455 ****
// Find the new node and its parent.
LogNode node = findNode(name);
! node.logger = logger;
Logger parent = null;
LogNode nodep = node.parent;
while (nodep != null) {
! if (nodep.logger != null) {
! parent = nodep.logger;
! break;
}
nodep = nodep.parent;
}
--- 424,439 ----
// Find the new node and its parent.
LogNode node = findNode(name);
! node.loggerRef = new WeakReference(logger);
Logger parent = null;
LogNode nodep = node.parent;
while (nodep != null) {
! WeakReference<Logger> nodeRef = nodep.loggerRef;
! if (nodeRef != null) {
! parent = nodeRef.get();
! if (parent != null) {
! break;
! }
}
nodep = nodep.parent;
}
***************
*** 543,549 ****
* @return matching logger or null if none is found
*/
public synchronized Logger getLogger(String name) {
! return loggers.get(name);
}
/**
--- 527,543 ----
* @return matching logger or null if none is found
*/
public synchronized Logger getLogger(String name) {
! WeakReference<Logger> ref = loggers.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.
! loggers.remove(name);
! }
! return logger;
}
/**
***************
*** 555,560 ****
--- 549,567 ----
* @return enumeration of logger name strings
*/
public synchronized Enumeration<String> getLoggerNames() {
+ Enumeration<String> keys = loggers.keys();
+
+ // This loop is needed for consistency. Some of the loggers
+ // can be GC-ed, so we usually delete them in such a case.
+ // However, we want this function to return the corresponding state.
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+ WeakReference ref = loggers.get(key);
+ if (loggers.get(key).get() == null) {
+ // Stale reference - delete the entry
+ loggers.remove(key);
+ }
+ }
return loggers.keys();
}
***************
*** 876,914 ****
// Avoid allocating global handlers.
return;
}
!
! // We need to raise privilege here. All our decisions will
! // be made based on the logging configuration, which can
! // only be modified by trusted code.
! AccessController.doPrivileged(new PrivilegedAction() {
! public Object run() {
! // Add new global handlers.
! String names[] = parseClassNames("handlers");
! for (int i = 0; i < names.length; i++) {
! String word = names[i];
! try {
! Class clz = ClassLoader.getSystemClassLoader().loadClass(word);
! Handler h = (Handler) clz.newInstance();
! try {
! // Check if there is a property defining the
! // handler's level.
! String levs = getProperty(word + ".level");
! if (levs != null) {
! h.setLevel(Level.parse(levs));
! }
! } catch (Exception ex) {
! System.err.println("Can't set level for " + word);
! // Probably a bad level. Drop through.
! }
! rootLogger.addHandler(h);
! } catch (Exception ex) {
! System.err.println("Can't load log handler \"" + word + "\"");
! System.err.println("" + ex);
! ex.printStackTrace();
! }
! }
! return null;
! }});
}
--- 883,889 ----
// Avoid allocating global handlers.
return;
}
! loadLoggerHandlers(rootLogger, "handlers", null, true);
}
***************
*** 935,941 ****
// Nested class to represent a node in our tree of named loggers.
private static class LogNode {
HashMap<Object,Object> children;
! Logger logger;
LogNode parent;
LogNode(LogNode parent) {
--- 910,916 ----
// Nested class to represent a node in our tree of named loggers.
private static class LogNode {
HashMap<Object,Object> children;
! WeakReference<Logger> loggerRef;
LogNode parent;
LogNode(LogNode parent) {
***************
*** 951,960 ****
Iterator values = children.values().iterator();
while (values.hasNext()) {
LogNode node = (LogNode) values.next();
! if (node.logger == null) {
node.walkAndSetParent(parent);
} else {
! doSetParent(node.logger, parent);
}
}
}
--- 926,936 ----
Iterator values = children.values().iterator();
while (values.hasNext()) {
LogNode node = (LogNode) values.next();
! WeakReference<Logger> ref = node.loggerRef;
! if (ref == null || ref.get() == null) {
node.walkAndSetParent(parent);
} else {
! doSetParent(ref.get(), parent);
}
}
}
|