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

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -29,10 +29,11 @@
 import java.io.*;
 import java.util.*;
 import java.security.*;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
+import java.util.concurrent.CopyOnWriteArrayList;
 import sun.misc.JavaAWTAccess;
 import sun.misc.SharedSecrets;
 
 /**
  * There is a single global LogManager object that is used to

@@ -167,10 +168,13 @@
     // This gets set to false in readConfiguration
     private boolean initializedGlobalHandlers = true;
     // True if JVM death is imminent and the exit hook has been called.
     private boolean deathImminent;
 
+    private final CopyOnWriteArrayList<ConfigurationListener> listeners =
+            new CopyOnWriteArrayList<>();
+
     static {
         manager = AccessController.doPrivileged(new PrivilegedAction<LogManager>() {
             @Override
             public LogManager run() {
                 LogManager mgr = null;

@@ -1166,11 +1170,12 @@
      * be re-read from the same file that was used at startup.
      * <P>
      * Any log level definitions in the new configuration file will be
      * applied using Logger.setLevel(), if the target Logger exists.
      * <p>
-     * A PropertyChangeEvent will be fired after the properties are read.
+     * The {@linkplain #addConfigurationListener(java.util.logging.LogManager.ConfigurationListener)
+     * configuration listeners} will be invoked after the properties are read.
      *
      * @exception  SecurityException  if a security manager exists and if
      *             the caller does not have LoggingPermission("control").
      * @exception  IOException if there are IO problems reading the configuration.
      */

@@ -1300,11 +1305,12 @@
     }
 
     /**
      * Reinitialize the logging properties and reread the logging configuration
      * from the given stream, which should be in java.util.Properties format.
-     * A PropertyChangeEvent will be fired after the properties are read.
+     * The {@linkplain #addConfigurationListener(java.util.logging.LogManager.ConfigurationListener)
+     * configuration listeners} will be invoked after the properties are read.
      * <p>
      * Any log level definitions in the new configuration file will be
      * applied using Logger.setLevel(), if the target Logger exists.
      *
      * @param ins       stream to read properties from

@@ -1333,10 +1339,12 @@
         }
 
         // Set levels on any pre-existing loggers, based on the new properties.
         setLevelsOnExistingLoggers();
 
+        invokeConfigurationListeners();
+
         // Note that we need to reinitialize global handles when
         // they are first referenced.
         synchronized (this) {
             initializedGlobalHandlers = false;
         }

@@ -1618,6 +1626,102 @@
         if (loggingMXBean == null) {
             loggingMXBean =  new Logging();
         }
         return loggingMXBean;
     }
+
+    /**
+     * A configuration listener can be added to the LogManager in
+     * in order to be informed of configuration loads.
+     * When the LogManager reads (or re-reads) its configuration, it
+     * will invoke all configuration listeners that are registered with it.
+     *
+     * @since 1.9
+     */
+    public static abstract class ConfigurationListener {
+
+        private static Void checkPermission() {
+            final SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                sm.checkPermission(controlPermission);
+            }
+            return null;
+        }
+        protected ConfigurationListener() {
+            this(checkPermission());
+        }
+        private ConfigurationListener(Void checked) {
+        }
+
+        /**
+         * This method will be called by the LogManager when its configuration
+         * has been read.
+         * @see #readConfiguration(java.io.InputStream)
+         */
+        public abstract void configurationLoaded();
+
+        @Override
+        public final boolean equals(Object other) {
+            return (other instanceof ConfigurationListener)
+                    ? super.equals(other) : false;
+        }
+
+        @Override
+        public final int hashCode() {
+            return super.hashCode();
+        }
+
+    }
+
+
+    /**
+     * Adds a configuration listener to be invoked when the logging properties
+     * are re-read and the configuration is changed.
+     * Adding multiple instances of the same listener results in
+     * the listener being invoked as many times as it was added when the
+     * configuration is changed.
+     *
+     * @param listener A configuration listener that will be invoked after the
+     *        configuration changed.
+     * @throws SecurityException if a security manager exists and if the
+     * caller does not have LoggingPermission("control").
+     * @throws NullPointerException if the listener is null.
+     *
+     * @since 1.9
+     */
+    public void addConfigurationListener(ConfigurationListener listener) {
+        ConfigurationListener l = Objects.requireNonNull(listener);
+        checkPermission();
+        listeners.add(l);
+    }
+
+    /**
+     * Removes a previously registered configuration listener.
+     * 
+     * If the same listener instance has been added through multiple
+     * invocations of {@code addConfigurationListener}, then an equivalent
+     * number of {@code removeConfigurationListener} invocations are
+     * required to remove all registration of that listener.
+     * <P>
+     * Returns silently if the given listener is {@code null} or is
+     * not found.
+     *
+     * @param listener the configuration listener to remove (can be null)
+     * @throws SecurityException if a security manager exists and if the
+     * caller does not have LoggingPermission("control").
+     *
+     * @since 1.9
+     */
+    public void removeConfigurationListener(ConfigurationListener listener) {
+        checkPermission();
+        if (listener != null) {
+            listeners.remove(listener);
+        }
+    }
+
+    private void invokeConfigurationListeners() {
+        for (ConfigurationListener listener : listeners) {
+            listener.configurationLoaded();
+        }
+    }
+
 }