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

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2000, 2013, 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 --- 1,7 ---- /* ! * 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,38 **** --- 29,39 ---- 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,176 **** --- 168,180 ---- // 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,1176 **** * 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. * * @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. */ --- 1170,1181 ---- * 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> ! * 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,1310 **** } /** * 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. * <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 --- 1305,1316 ---- } /** * Reinitialize the logging properties and reread the logging configuration * from the given stream, which should be in java.util.Properties format. ! * 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,1342 **** --- 1339,1350 ---- } // 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,1623 **** --- 1626,1727 ---- 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(); + } + } + }