src/share/classes/java/util/logging/Logger.java

Print this page

        

@@ -216,16 +216,50 @@
  * @since 1.4
  */
 public class Logger {
     private static final Handler emptyHandlers[] = new Handler[0];
     private static final int offValue = Level.OFF.intValue();
-    private LogManager manager;
+
+    static final String SYSTEM_LOGGER_RB_NAME = "sun.util.logging.resources.logging";
+
+    // This class is immutable and it is important that it remains so.
+    private static final class LoggerBundle {
+        final String resourceBundleName; // Base name of the bundle.
+        final ResourceBundle userBundle; // Bundle set through setResourceBundle.
+        private LoggerBundle(String resourceBundleName, ResourceBundle bundle) {
+            this.resourceBundleName = resourceBundleName;
+            this.userBundle = bundle;
+        }
+        boolean isSystemBundle() {
+            return SYSTEM_LOGGER_RB_NAME.equals(resourceBundleName);
+        }
+        static LoggerBundle get(String name, ResourceBundle bundle) {
+            if (name == null && bundle == null) {
+                return NO_RESOURCE_BUNDLE;
+            } else if (SYSTEM_LOGGER_RB_NAME.equals(name) && bundle == null) {
+                return SYSTEM_BUNDLE;
+            } else {
+                return new LoggerBundle(name, bundle);
+            }
+        }
+    }
+
+    // This instance will be shared by all loggers created by the system
+    // code
+    private static final LoggerBundle SYSTEM_BUNDLE =
+            new LoggerBundle(SYSTEM_LOGGER_RB_NAME, null);
+
+    // This instance indicates that no resource bundle has been specified yet,
+    // and it will be shared by all loggers which have no resource bundle.
+    private static final LoggerBundle NO_RESOURCE_BUNDLE =
+            new LoggerBundle(null, null);
+
+    private volatile LogManager manager;
     private String name;
     private final CopyOnWriteArrayList<Handler> handlers =
         new CopyOnWriteArrayList<>();
-    private String resourceBundleName;  // Base name of the bundle.
-    private ResourceBundle userBundle;  // Bundle set through setResourceBundle.
+    private volatile LoggerBundle loggerBundle = NO_RESOURCE_BUNDLE;
     private volatile boolean useParentHandlers = true;
     private volatile Filter filter;
     private boolean anonymous;
 
     // Cache to speed up behavior of findResourceBundle:

@@ -339,10 +373,11 @@
         this(name, resourceBundleName, null, LogManager.getLogManager());
     }
 
     Logger(String name, String resourceBundleName, Class<?> caller, LogManager manager) {
         this.manager = manager;
+        assert this.loggerBundle == NO_RESOURCE_BUNDLE;
         setupResourceInfo(resourceBundleName, caller);
         this.name = name;
         levelValue = Level.INFO.intValue();
     }
 

@@ -364,10 +399,11 @@
     // This constructor is used only to create the global Logger.
     // It is needed to break a cyclic dependence between the LogManager
     // and Logger static initializers causing deadlocks.
     private Logger(String name) {
         // The manager field is not initialized here.
+        assert this.loggerBundle == NO_RESOURCE_BUNDLE;
         this.name = name;
         levelValue = Level.INFO.intValue();
     }
 
     // It is called from LoggerContext.addLocalLogger() when the logger

@@ -639,11 +675,11 @@
      * bundle or resource bundle name inherited from its parent.
      *
      * @return localization bundle name (may be {@code null})
      */
     public String getResourceBundleName() {
-        return resourceBundleName;
+        return loggerBundle.resourceBundleName;
     }
 
     /**
      * Set a filter to control output on this Logger.
      * <P>

@@ -708,12 +744,13 @@
     // private support method for logging.
     // We fill in the logger name, resource bundle name, and
     // resource bundle and then call "void log(LogRecord)".
     private void doLog(LogRecord lr) {
         lr.setLoggerName(name);
-        final ResourceBundle bundle = getEffectiveResourceBundle();
-        final String ebname = getEffectiveResourceBundleName();
+        final LoggerBundle lb = getEffectiveLoggerBundle();
+        final ResourceBundle  bundle = lb.userBundle;
+        final String ebname = lb.resourceBundleName;
         if (ebname != null && bundle != null) {
             lr.setResourceBundleName(ebname);
             lr.setResourceBundle(bundle);
         }
         log(lr);

@@ -1755,12 +1792,10 @@
      */
     public boolean getUseParentHandlers() {
         return useParentHandlers;
     }
 
-    static final String SYSTEM_LOGGER_RB_NAME = "sun.util.logging.resources.logging";
-
     private static ResourceBundle findSystemResourceBundle(final Locale locale) {
         // the resource bundle is in a restricted package
         return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() {
             @Override
             public ResourceBundle run() {

@@ -1799,15 +1834,16 @@
         if (name == null) {
             return null;
         }
 
         Locale currentLocale = Locale.getDefault();
+        final LoggerBundle lb = loggerBundle;
 
         // Normally we should hit on our simple one entry cache.
-        if (userBundle != null &&
-                name.equals(resourceBundleName)) {
-            return userBundle;
+        if (lb.userBundle != null &&
+                name.equals(lb.resourceBundleName)) {
+            return lb.userBundle;
         } else if (catalog != null && currentLocale.equals(catalogLocale)
                 && name.equals(catalogName)) {
             return catalog;
         }
 

@@ -1862,21 +1898,22 @@
     // that a suitable ResourceBundle exists before setting the
     // resourceBundleName field.
     // Synchronized to prevent races in setting the fields.
     private synchronized void setupResourceInfo(String name,
                                                 Class<?> callersClass) {
-        if (resourceBundleName != null) {
+        final LoggerBundle lb = loggerBundle;
+        if (lb.resourceBundleName != null) {
             // this Logger already has a ResourceBundle
 
-            if (resourceBundleName.equals(name)) {
+            if (lb.resourceBundleName.equals(name)) {
                 // the names match so there is nothing more to do
                 return;
             }
 
             // cannot change ResourceBundles once they are set
             throw new IllegalArgumentException(
-                resourceBundleName + " != " + name);
+                lb.resourceBundleName + " != " + name);
         }
 
         if (name == null) {
             return;
         }

@@ -1888,11 +1925,11 @@
             // the bundle using it
             this.callersClassLoaderRef = null;
             throw new MissingResourceException("Can't find " + name + " bundle",
                                                 name, "");
         }
-        resourceBundleName = name;
+        loggerBundle = LoggerBundle.get(name, lb.userBundle);
     }
 
     /**
      * Sets a resource bundle on this logger.
      * All messages will be logged using the given resource bundle for its

@@ -1918,20 +1955,20 @@
         if (baseName == null || baseName.isEmpty()) {
             throw new IllegalArgumentException("resource bundle must have a name");
         }
 
         synchronized (this) {
-            final boolean canReplaceResourceBundle = resourceBundleName == null
-                    || resourceBundleName.equals(baseName);
+            LoggerBundle lb = loggerBundle;
+            final boolean canReplaceResourceBundle = lb.resourceBundleName == null
+                    || lb.resourceBundleName.equals(baseName);
 
             if (!canReplaceResourceBundle) {
                 throw new IllegalArgumentException("can't replace resource bundle");
             }
 
 
-            userBundle = bundle;
-            resourceBundleName = baseName;
+            loggerBundle = LoggerBundle.get(baseName, bundle);
         }
     }
 
     /**
      * Return the parent for this Logger.

@@ -2080,47 +2117,55 @@
         }
     }
 
 
     // Private method to get the potentially inherited
-    // resource bundle name for this Logger.
-    // May return null
-    private String getEffectiveResourceBundleName() {
-        Logger target = this;
-        while (target != null) {
-            String rbn = target.getResourceBundleName();
-            if (rbn != null) {
-                return rbn;
-            }
-            target = target.getParent();
-        }
-        return null;
+    // resource bundle and resource bundle name for this Logger.
+    // This method never returns null.
+    private LoggerBundle getEffectiveLoggerBundle() {
+        final LoggerBundle lb = loggerBundle;
+        if (lb.isSystemBundle()) {
+            return SYSTEM_BUNDLE;
+        }
+
+        // first take care of this logger
+        final ResourceBundle b = getResourceBundle();
+        if (b != null && b == lb.userBundle) {
+            return lb;
+        } else if (b != null) {
+            // either lb.userBundle is null or getResourceBundle() is
+            // overriden
+            final String rbName = getResourceBundleName();
+            if (!SYSTEM_LOGGER_RB_NAME.equals(rbName)
+                    && !SYSTEM_LOGGER_RB_NAME.equals(b.getBaseBundleName())) {
+                return LoggerBundle.get(rbName, b);
+            } else {
+                return SYSTEM_BUNDLE;
     }
-
-
-    private ResourceBundle getEffectiveResourceBundle() {
-        Logger target = this;
-        if (SYSTEM_LOGGER_RB_NAME.equals(resourceBundleName)) return null;
-        ResourceBundle localRB = getResourceBundle();
-        if (localRB != null) {
-            return localRB;
         }
 
+        // no resource bundle was specified on this logger, look up the
+        // parent stack.
+        Logger target = this.parent;
         while (target != null) {
-            final ResourceBundle rb = target.userBundle;
-            if (rb != null) {
-                return rb;
-            }
-            final String rbn = target.getResourceBundleName();
-            if (rbn != null) {
-                if (!SYSTEM_LOGGER_RB_NAME.equals(rbn)) {
-                    return findResourceBundle(rbn, true);
+            final LoggerBundle trb = target.loggerBundle;
+            if (trb.isSystemBundle()) {
+                return SYSTEM_BUNDLE;
+            }
+            if (trb.userBundle != null) {
+                return trb;
+            }
+            final String rbName = target.getResourceBundleName();
+            if (rbName != null) {
+                if (!SYSTEM_LOGGER_RB_NAME.equals(rbName)) {
+                    return LoggerBundle.get(rbName,
+                            findResourceBundle(rbName, true));
                 } else {
-                    return null;
+                    return SYSTEM_BUNDLE;
                 }
             }
             target = target.getParent();
         }
-        return null;
+        return NO_RESOURCE_BUNDLE;
     }
 
 }