Fix GWT emulated Logger behavior to match java.util.logging.Logger
specification.  This will also make production logging behavior match
devmode behavior since devmode behavior comes from the JRE implementation.

1. getHandlers() should return an empty array rather then null.
2. getLevel() should return null if the Logger has no level explicitly set
(i.e. if it should be inheriting its level from the first ancestor with an
explicity set level).
3. A logging call which passes the logger's level check should be published to
ancestor loggers' handlers recursively up the tree, irrespective of the
log levels of the ancestor loggers.  This process is only stopped by a false
getUseParentHandlers().

Review at http://gwt-code-reviews.appspot.com/1602804

Review by: unnurg@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10766 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/logging/impl/LoggerImplRegular.java b/user/src/com/google/gwt/logging/impl/LoggerImplRegular.java
index b6e0ba6..d56ec84d 100644
--- a/user/src/com/google/gwt/logging/impl/LoggerImplRegular.java
+++ b/user/src/com/google/gwt/logging/impl/LoggerImplRegular.java
@@ -60,17 +60,11 @@
   }
 
   public Handler[] getHandlers() {
-    if (handlers.size() > 0) {
-      return handlers.toArray(new Handler[handlers.size()]);
-    }
-    return null;
+    return handlers.toArray(new Handler[handlers.size()]);
   }
 
   public Level getLevel() {
-    if (level != null) {
-      return level;
-    }
-    return getParent().getLevel();
+    return level;
   }
 
   public Logger getLoggerHelper(String name) {
@@ -106,7 +100,7 @@
   }
 
   public boolean isLoggable(Level messageLevel) {
-    return getLevel().intValue() <= messageLevel.intValue();
+    return getEffectiveLevel().intValue() <= messageLevel.intValue();
   }
 
   public void log(Level level, String msg) {
@@ -124,11 +118,15 @@
 
   public void log(LogRecord record) {
     if (isLoggable(record.getLevel())) {
-      for (Handler h : handlers) {
-        h.publish(record);
+      for (Handler handler : getHandlers()) {
+        handler.publish(record);
       }
-      if (useParentHandlers && parent != null) {
-        parent.log(record);
+      Logger logger = getUseParentHandlers() ? getParent() : null;
+      while (logger != null) {
+        for (Handler handler : logger.getHandlers()) {
+          handler.publish(record);
+        }
+        logger = logger.getUseParentHandlers() ? logger.getParent() : null;
       }
     }
   }
@@ -163,4 +161,18 @@
     log(Level.WARNING, msg);
   }
 
+  private Level getEffectiveLevel() {
+    if (level != null) {
+      return level;
+    }
+    Logger logger = getParent();
+    while (logger != null) {
+      Level effectiveLevel = logger.getLevel();
+      if (effectiveLevel != null) {
+        return effectiveLevel;
+      }
+      logger = logger.getParent();
+    }
+    return Level.INFO;
+  }
 }