Hi,

I am checking in the following logging cleanup patch by Rafael Schloming
from Red Hat. See the discussion and review of the patch in bugzilla:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26668

2006-04-03  Rafael H. Schloming  <[EMAIL PROTECTED]>

    Fixes bug #26668
    * java/util/logging/Level.java (parse): Document.
    * java/util/logging/LogManager.java (rootLogger): Removed.
    (LogManager): Just set loggers to new HashMap.
    (getLogManager): Make synchronized. Create and init LogManager if it
    doesn't exist yet.
    (static): Removed block.
    (MANAGER_PROPERTY): New private final string.
    (makeLogManager): Use new property string, move warning to
    createInstance() method.
    (CONFIG_PROPERTY): New private final string.
    (initLogManager): New method.
    (addLogger): Use Logger.root, not rootLogger.
    (findAncestor): Likewise.
    (readConfiguration): Move warning to createInstance() method.
    Add handlers directly to Logger.root. Warn about bad level values.
    (getClassProperty): Use new locateClass() method.
    (getInstanceProperty): Only catch specific newInstance Errors.
    (createInstance): Make private and takes a string to use in warning
    messages. Use new locateClass() method and generate appropriate
    warning message.
    (warn): New methods.
    (locateClass): Locates a class through the context class loader and
    system class loader as backup.
    * java/util/logging/Logger.java (root): New static final field.
    (Logger): Set parent to root.
    (setParent): Directly check root field.

This is almost exactly the patch as Rafael's last revision in the bug
report. The only things I changed was updating the copyright notice,
reshuffle the imports to use HashMap directly and using SystemProperties
to get at the MANAGER_PROPERTY since this is a trusted class that needs
direct access to the property even if the caller context doesn't have
it.

Rafael also created a test-suite for this that needs to be imported into
Mauve later. Thanks a lot for all your work Rafael.

Cheers,

Mark
Index: java/util/logging/Level.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/util/logging/Level.java,v
retrieving revision 1.9
diff -u -r1.9 Level.java
--- java/util/logging/Level.java	2 Jul 2005 20:32:44 -0000	1.9
+++ java/util/logging/Level.java	3 Apr 2006 08:44:30 -0000
@@ -1,5 +1,5 @@
 /* Level.java -- a class for indicating logging levels
-   Copyright (C) 2002, 2005  Free Software Foundation, Inc.
+   Copyright (C) 2002, 2005, 2006  Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -341,6 +341,9 @@
 
     for (int i = 0; i < knownLevels.length; i++)
     {
+      // It's safe to use == instead of .equals here because only the
+      // standard logging levels will be returned by this method, and
+      // they are all created using string literals.
       if (name == knownLevels[i].name)
 	return knownLevels[i];
     }
Index: java/util/logging/LogManager.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/util/logging/LogManager.java,v
retrieving revision 1.18
diff -u -r1.18 LogManager.java
--- java/util/logging/LogManager.java	24 Feb 2006 11:03:08 -0000	1.18
+++ java/util/logging/LogManager.java	3 Apr 2006 08:44:30 -0000
@@ -1,6 +1,6 @@
 /* LogManager.java -- a class for maintaining Loggers and managing
    configuration properties
-   Copyright (C) 2002,2005 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -48,11 +48,14 @@
 import java.net.URL;
 import java.util.Collections;
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Properties;
 import java.util.StringTokenizer;
 
+import gnu.classpath.SystemProperties;
+
 /**
  * The <code>LogManager</code> maintains a hierarchical namespace
  * of Logger objects and manages properties for configuring the logging
@@ -114,7 +117,6 @@
    * a WeakReference to it.
    */
   private Map loggers;
-  final Logger rootLogger;
 
   /**
    * The properties for the logging framework which have been
@@ -135,83 +137,62 @@
    * this case.
    */
   private final PropertyChangeSupport pcs = new PropertyChangeSupport( /* source bean */
-  LogManager.class);
+                                                                      LogManager.class);
 
   protected LogManager()
   {
-    if (logManager != null)
-      throw new IllegalStateException("there can be only one LogManager; use LogManager.getLogManager()");
-
-    logManager = this;
-    loggers = new java.util.HashMap();
-    rootLogger = new Logger("", null);
-    rootLogger.setLevel(Level.INFO);
-    addLogger(rootLogger);
-
-    /* Make sure that Logger.global has the rootLogger as its parent.
-     *
-     * Logger.global is set during class initialization of Logger,
-     * which may or may not be before this code is being executed.
-     * For example, on the Sun 1.3.1 and 1.4.0 JVMs, Logger.global
-     * has been set before this code is being executed. In contrast,
-     * Logger.global still is null on GCJ 3.2.  Since the LogManager
-     * and Logger classes are mutually dependent, both behaviors are
-     * correct.
-     *
-     * This means that we cannot depend on Logger.global to have its
-     * value when this code executes, although that variable is final.
-     * Since Logger.getLogger will always return the same logger for
-     * the same name, the subsequent line works fine irrespective of
-     * the order in which classes are initialized.
-     */
-    Logger.getLogger("global").setParent(rootLogger);
-    Logger.getLogger("global").setUseParentHandlers(true);
+    loggers = new HashMap();
   }
 
   /**
    * Returns the globally shared LogManager instance.
    */
-  public static LogManager getLogManager()
+  public static synchronized LogManager getLogManager()
   {
+    if (logManager == null)
+      {
+        logManager = makeLogManager();
+        initLogManager();
+      }
     return logManager;
   }
 
-  static
-    {
-      makeLogManager();
-
-      /* The Javadoc description of the class explains
-       * what is going on here.
-       */
-      Object configurator = createInstance(System.getProperty("java.util.logging.config.class"),
-                                           /* must be instance of */ Object.class);
-
-      try
-        {
-	  if (configurator == null)
-	    getLogManager().readConfiguration();
-        }
-      catch (IOException ex)
-        {
-	  /* FIXME: Is it ok to ignore exceptions here? */
-        }
-    }
+  private static final String MANAGER_PROPERTY = "java.util.logging.manager";
 
   private static LogManager makeLogManager()
   {
-    String managerClassName;
-    LogManager manager;
+    String managerClassName = SystemProperties.getProperty(MANAGER_PROPERTY);
+    LogManager manager = (LogManager) createInstance
+      (managerClassName, LogManager.class, MANAGER_PROPERTY);
+    if (manager == null)
+      manager = new LogManager();
+    return manager;
+  }
 
-    managerClassName = System.getProperty("java.util.logging.manager");
-    manager = (LogManager) createInstance(managerClassName, LogManager.class);
-    if (manager != null)
-      return manager;
-
-    if (managerClassName != null)
-      System.err.println("WARNING: System property \"java.util.logging.manager\""
-                         + " should be the name of a subclass of java.util.logging.LogManager");
+  private static final String CONFIG_PROPERTY = "java.util.logging.config.class";
 
-    return new LogManager();
+  private static void initLogManager()
+  {
+    LogManager manager = getLogManager();
+    Logger.root.setLevel(Level.INFO);
+    manager.addLogger(Logger.root);
+
+    /* The Javadoc description of the class explains
+     * what is going on here.
+     */
+    Object configurator = createInstance(System.getProperty(CONFIG_PROPERTY),
+                                         /* must be instance of */ Object.class,
+                                         CONFIG_PROPERTY);
+
+    try
+      {
+        if (configurator == null)
+          manager.readConfiguration();
+      }
+    catch (IOException ex)
+      {
+        /* FIXME: Is it ok to ignore exceptions here? */
+      }
   }
 
   /**
@@ -314,7 +295,7 @@
         if(index > -1)
           searchName = searchName.substring(0,index);
         else
-          searchName = "";      
+          searchName = "";
       }
     logger.setLevel(logLevel);
 
@@ -324,12 +305,12 @@
      * When adding "foo.bar", the logger "foo.bar.baz" should change
      * its parent to "foo.bar".
      */
-    if (parent != rootLogger)
+    if (parent != Logger.root)
       {
 	for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
 	  {
 	    Logger possChild = (Logger) ((WeakReference) loggers.get(iter.next()))
-	                       .get();
+              .get();
 	    if ((possChild == null) || (possChild == logger)
 	        || (possChild.getParent() != parent))
 	      continue;
@@ -367,14 +348,14 @@
   {
     String childName = child.getName();
     int childNameLength = childName.length();
-    Logger best = rootLogger;
+    Logger best = Logger.root;
     int bestNameLength = 0;
 
     Logger cand;
     String candName;
     int candNameLength;
 
-    if (child == rootLogger)
+    if (child == Logger.root)
       return null;
 
     for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
@@ -468,7 +449,7 @@
 
 	    if (logger == null)
 	      iter.remove();
-	    else if (logger != rootLogger)
+	    else if (logger != Logger.root)
 	      {
 	        logger.resetLogger();
 	        logger.setLevel(null);
@@ -476,8 +457,8 @@
 	  }
       }
 
-    rootLogger.setLevel(Level.INFO);
-    rootLogger.resetLogger();
+    Logger.root.setLevel(Level.INFO);
+    Logger.root.resetLogger();
   }
 
   /**
@@ -524,11 +505,11 @@
 
         // If no config file could be found use a default configuration.
         if(inputStream == null)
-        {
-          String defaultConfig = "handlers = java.util.logging.ConsoleHandler   \n"
+          {
+            String defaultConfig = "handlers = java.util.logging.ConsoleHandler   \n"
               + ".level=INFO \n";
-          inputStream = new ByteArrayInputStream(defaultConfig.getBytes());
-        }
+            inputStream = new ByteArrayInputStream(defaultConfig.getBytes());
+          }
       }
     else
       inputStream = new java.io.FileInputStream(path);
@@ -574,21 +555,9 @@
 	    while (tokenizer.hasMoreTokens())
 	      {
 		String handlerName = tokenizer.nextToken();
-		try
-		  {
-		    Class handlerClass = ClassLoader.getSystemClassLoader().loadClass(handlerName);
-		    getLogger("").addHandler((Handler) handlerClass
-		                             .newInstance());
-		  }
-		catch (ClassCastException ex)
-		  {
-		    System.err.println("[LogManager] class " + handlerName
-		                       + " is not subclass of java.util.logging.Handler");
-		  }
-		catch (Exception ex)
-		  {
-		    //System.out.println("[LogManager.readConfiguration]"+ex);
-		  }
+                Handler handler = (Handler)
+                  createInstance(handlerName, Handler.class, key);
+                Logger.root.addHandler(handler);
 	      }
 	  }
 
@@ -602,14 +571,19 @@
 		logger = Logger.getLogger(loggerName);
 		addLogger(logger);
 	      }
+            Level level = null;
 	    try
-	      {
-		logger.setLevel(Level.parse(value));
-	      }
-	    catch (Exception _)
-	      {
-		//System.out.println("[LogManager.readConfiguration] "+_);
-	      }
+              {
+                level = Level.parse(value);
+              }
+            catch (IllegalArgumentException e)
+              {
+                warn("bad level \'" + value + "\'", e);
+              }
+            if (level != null)
+              {
+                logger.setLevel(level);
+              }
 	    continue;
 	  }
       }
@@ -748,19 +722,17 @@
    */
   static final Class getClassProperty(String propertyName, Class defaultValue)
   {
-    Class usingClass = null;
+    String propertyValue = logManager.getProperty(propertyName);
 
-    try
-      {
-	String propertyValue = logManager.getProperty(propertyName);
-	if (propertyValue != null)
-	  usingClass = Class.forName(propertyValue);
-	if (usingClass != null)
-	  return usingClass;
-      }
-    catch (Exception _)
-      {
-      }
+    if (propertyValue != null)
+      try
+        {
+          return locateClass(propertyValue);
+        }
+      catch (ClassNotFoundException e)
+        {
+          warn(propertyName + " = " + propertyValue, e);
+        }
 
     return defaultValue;
   }
@@ -774,12 +746,17 @@
 
     try
       {
-	Object obj = klass.newInstance();
-	if (ofClass.isInstance(obj))
-	  return obj;
+        Object obj = klass.newInstance();
+        if (ofClass.isInstance(obj))
+          return obj;
+      }
+    catch (InstantiationException e)
+      {
+        warn(propertyName + " = " + klass.getName(), e);
       }
-    catch (Exception _)
+    catch (IllegalAccessException e)
       {
+        warn(propertyName + " = " + klass.getName(), e);
       }
 
     if (defaultClass == null)
@@ -824,14 +801,17 @@
   }
 
   /**
-   * Creates a new instance of a class specified by name.
+   * Creates a new instance of a class specified by name and verifies
+   * that it is an instance (or subclass of) a given type.
    *
    * @param className the name of the class of which a new instance
    *        should be created.
    *
-   * @param ofClass the class to which the new instance should
-   *        be either an instance or an instance of a subclass.
-   *        FIXME: This description is just terrible.
+   * @param type the object created must be an instance of
+   * <code>type</code> or any subclass of <code>type</code>
+   *
+   * @param property the system property to reference in error
+   * messages
    *
    * @return the new instance, or <code>null</code> if
    *         <code>className</code> is <code>null</code>, if no class
@@ -839,28 +819,89 @@
    *         loading that class, or if the constructor of the class
    *         has thrown an exception.
    */
-  static final Object createInstance(String className, Class ofClass)
+  private static final Object createInstance(String className, Class type,
+                                             String property)
   {
-    Class klass;
+    Class klass = null;
 
     if ((className == null) || (className.length() == 0))
       return null;
 
     try
       {
-	klass = Class.forName(className);
-	if (! ofClass.isAssignableFrom(klass))
-	  return null;
-
-	return klass.newInstance();
+        klass = locateClass(className);
+        if (type.isAssignableFrom(klass))
+          return klass.newInstance();
+        warn(property, className, "not an instance of " + type.getName());
       }
-    catch (Exception _)
+    catch (ClassNotFoundException e)
+      {
+        warn(property, className, "class not found");
+      }
+    catch (IllegalAccessException e)
+      {
+        warn(property, className, "illegal access");
+      }
+    catch (InstantiationException e)
+      {
+        warn(property, className, e);
+      }
+    catch (java.lang.LinkageError e)
+      {
+        warn(property, className, "linkage error");
+      }
+
+    return null;
+  }
+
+  private static final void warn(String property, String klass, Throwable t)
+  {
+    warn(property, klass, null, t);
+  }
+
+  private static final void warn(String property, String klass, String msg)
+  {
+    warn(property, klass, msg, null);
+  }
+
+  private static final void warn(String property, String klass, String msg,
+                                 Throwable t)
+  {
+    warn("error instantiating '" + klass + "' referenced by " + property +
+         (msg == null ? "" : ", " + msg), t);
+  }
+
+  /**
+   * All debug warnings go through this method.
+   */
+
+  private static final void warn(String msg, Throwable t)
+  {
+    System.err.println("WARNING: " + msg);
+    if (t != null)
+      t.printStackTrace(System.err);
+  }
+
+  /**
+   * Locates a class by first checking the system class loader and
+   * then checking the context class loader.
+   *
+   * @param name the fully qualified name of the Class to locate
+   * @return Class the located Class
+   */
+
+  private static Class locateClass(String name) throws ClassNotFoundException
+  {
+    ClassLoader loader = Thread.currentThread().getContextClassLoader();
+    try
       {
-	return null;
+        return Class.forName(name, true, loader);
       }
-    catch (java.lang.LinkageError _)
+    catch (ClassNotFoundException e)
       {
-	return null;
+        loader = ClassLoader.getSystemClassLoader();
+        return Class.forName(name, true, loader);
       }
   }
+
 }
Index: java/util/logging/Logger.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/util/logging/Logger.java,v
retrieving revision 1.12
diff -u -r1.12 Logger.java
--- java/util/logging/Logger.java	12 Aug 2005 14:31:59 -0000	1.12
+++ java/util/logging/Logger.java	3 Apr 2006 08:44:30 -0000
@@ -1,5 +1,5 @@
 /* Logger.java -- a class for logging messages
-   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -67,6 +67,9 @@
  */
 public class Logger
 {
+
+  static final Logger root = new Logger("", null);
+
   /**
    * A logger provided to applications that make only occasional use
    * of the logging framework, typically early prototypes.  Serious
@@ -175,7 +178,7 @@
     /* This is null when the root logger is being constructed,
      * and the root logger afterwards.
      */
-    parent = LogManager.getLogManager().rootLogger;
+    parent = root;
 
     useParentHandlers = (parent != null);
   }
@@ -1148,16 +1151,12 @@
    */
   public synchronized void setParent(Logger parent)
   {
-    LogManager lm;
-
     /* Throw a new NullPointerException if parent is null. */
     parent.getClass();
 
-    lm = LogManager.getLogManager();
-
-    if (this == lm.rootLogger)
+    if (this == root)
         throw new IllegalArgumentException(
-          "only the root logger can have a null parent");
+          "the root logger can only have a null parent");
 
     /* An application is allowed to control an anonymous logger
      * without having the permission to control the logging

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to