1 /*
2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
152 private volatile Properties props = new Properties();
153 private final static Level defaultLevel = Level.INFO;
154
155 // LoggerContext for system loggers and user loggers
156 private final LoggerContext systemContext = new SystemLoggerContext();
157 private final LoggerContext userContext = new LoggerContext();
158 // non final field - make it volatile to make sure that other threads
159 // will see the new value once ensureLogManagerInitialized() has finished
160 // executing.
161 private volatile Logger rootLogger;
162 // Have we done the primordial reading of the configuration file?
163 // (Must be done after a suitable amount of java.lang.System
164 // initialization has been done)
165 private volatile boolean readPrimordialConfiguration;
166 // Have we initialized global (root) handlers yet?
167 // This gets set to false in readConfiguration
168 private boolean initializedGlobalHandlers = true;
169 // True if JVM death is imminent and the exit hook has been called.
170 private boolean deathImminent;
171
172 static {
173 manager = AccessController.doPrivileged(new PrivilegedAction<LogManager>() {
174 @Override
175 public LogManager run() {
176 LogManager mgr = null;
177 String cname = null;
178 try {
179 cname = System.getProperty("java.util.logging.manager");
180 if (cname != null) {
181 try {
182 Class<?> clz = ClassLoader.getSystemClassLoader()
183 .loadClass(cname);
184 mgr = (LogManager) clz.newInstance();
185 } catch (ClassNotFoundException ex) {
186 Class<?> clz = Thread.currentThread()
187 .getContextClassLoader().loadClass(cname);
188 mgr = (LogManager) clz.newInstance();
189 }
190 }
191 } catch (Exception ex) {
1151 * return value from {@code LogManager.getLogger()} for null to properly
1152 * handle the case where the Logger has been garbage collected in the
1153 * time since its name was returned by this method.
1154 *
1155 * @return enumeration of logger name strings
1156 */
1157 public Enumeration<String> getLoggerNames() {
1158 return getUserContext().getLoggerNames();
1159 }
1160
1161 /**
1162 * Reinitialize the logging properties and reread the logging configuration.
1163 * <p>
1164 * The same rules are used for locating the configuration properties
1165 * as are used at startup. So normally the logging properties will
1166 * be re-read from the same file that was used at startup.
1167 * <P>
1168 * Any log level definitions in the new configuration file will be
1169 * applied using Logger.setLevel(), if the target Logger exists.
1170 * <p>
1171 * A PropertyChangeEvent will be fired after the properties are read.
1172 *
1173 * @exception SecurityException if a security manager exists and if
1174 * the caller does not have LoggingPermission("control").
1175 * @exception IOException if there are IO problems reading the configuration.
1176 */
1177 public void readConfiguration() throws IOException, SecurityException {
1178 checkPermission();
1179
1180 // if a configuration class is specified, load it and use it.
1181 String cname = System.getProperty("java.util.logging.config.class");
1182 if (cname != null) {
1183 try {
1184 // Instantiate the named class. It is its constructor's
1185 // responsibility to initialize the logging configuration, by
1186 // calling readConfiguration(InputStream) with a suitable stream.
1187 try {
1188 Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
1189 clz.newInstance();
1190 return;
1191 } catch (ClassNotFoundException ex) {
1285 }
1286 if (hands.charAt(end) == ',') {
1287 break;
1288 }
1289 end++;
1290 }
1291 String word = hands.substring(ix, end);
1292 ix = end+1;
1293 word = word.trim();
1294 if (word.length() == 0) {
1295 continue;
1296 }
1297 result.add(word);
1298 }
1299 return result.toArray(new String[result.size()]);
1300 }
1301
1302 /**
1303 * Reinitialize the logging properties and reread the logging configuration
1304 * from the given stream, which should be in java.util.Properties format.
1305 * A PropertyChangeEvent will be fired after the properties are read.
1306 * <p>
1307 * Any log level definitions in the new configuration file will be
1308 * applied using Logger.setLevel(), if the target Logger exists.
1309 *
1310 * @param ins stream to read properties from
1311 * @exception SecurityException if a security manager exists and if
1312 * the caller does not have LoggingPermission("control").
1313 * @exception IOException if there are problems reading from the stream.
1314 */
1315 public void readConfiguration(InputStream ins) throws IOException, SecurityException {
1316 checkPermission();
1317 reset();
1318
1319 // Load the properties
1320 props.load(ins);
1321 // Instantiate new configuration objects.
1322 String names[] = parseClassNames("config");
1323
1324 for (String word : names) {
1325 try {
1326 Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word);
1327 clz.newInstance();
1328 } catch (Exception ex) {
1329 System.err.println("Can't load config class \"" + word + "\"");
1330 System.err.println("" + ex);
1331 // ex.printStackTrace();
1332 }
1333 }
1334
1335 // Set levels on any pre-existing loggers, based on the new properties.
1336 setLevelsOnExistingLoggers();
1337
1338 // Note that we need to reinitialize global handles when
1339 // they are first referenced.
1340 synchronized (this) {
1341 initializedGlobalHandlers = false;
1342 }
1343 }
1344
1345 /**
1346 * Get the value of a logging property.
1347 * The method returns null if the property is not found.
1348 * @param name property name
1349 * @return property value
1350 */
1351 public String getProperty(String name) {
1352 return props.getProperty(name);
1353 }
1354
1355 // Package private method to get a String property.
1356 // If the property is not defined we return the given
1357 // default value.
1358 String getStringProperty(String name, String defaultValue) {
1359 String val = getProperty(name);
1360 if (val == null) {
1361 return defaultValue;
1362 }
1363 return val.trim();
1603 * Returns <tt>LoggingMXBean</tt> for managing loggers.
1604 * An alternative way to manage loggers is through the
1605 * {@link java.lang.management.PlatformLoggingMXBean} interface
1606 * that can be obtained by calling:
1607 * <pre>
1608 * PlatformLoggingMXBean logging = {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
1609 * ManagementFactory.getPlatformMXBean}(PlatformLoggingMXBean.class);
1610 * </pre>
1611 *
1612 * @return a {@link LoggingMXBean} object.
1613 *
1614 * @see java.lang.management.PlatformLoggingMXBean
1615 * @since 1.5
1616 */
1617 public static synchronized LoggingMXBean getLoggingMXBean() {
1618 if (loggingMXBean == null) {
1619 loggingMXBean = new Logging();
1620 }
1621 return loggingMXBean;
1622 }
1623 }
|
1 /*
2 * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
152 private volatile Properties props = new Properties();
153 private final static Level defaultLevel = Level.INFO;
154
155 // LoggerContext for system loggers and user loggers
156 private final LoggerContext systemContext = new SystemLoggerContext();
157 private final LoggerContext userContext = new LoggerContext();
158 // non final field - make it volatile to make sure that other threads
159 // will see the new value once ensureLogManagerInitialized() has finished
160 // executing.
161 private volatile Logger rootLogger;
162 // Have we done the primordial reading of the configuration file?
163 // (Must be done after a suitable amount of java.lang.System
164 // initialization has been done)
165 private volatile boolean readPrimordialConfiguration;
166 // Have we initialized global (root) handlers yet?
167 // This gets set to false in readConfiguration
168 private boolean initializedGlobalHandlers = true;
169 // True if JVM death is imminent and the exit hook has been called.
170 private boolean deathImminent;
171
172 private final Map<Object, Runnable> listeners =
173 Collections.synchronizedMap(new IdentityHashMap<>());
174
175 static {
176 manager = AccessController.doPrivileged(new PrivilegedAction<LogManager>() {
177 @Override
178 public LogManager run() {
179 LogManager mgr = null;
180 String cname = null;
181 try {
182 cname = System.getProperty("java.util.logging.manager");
183 if (cname != null) {
184 try {
185 Class<?> clz = ClassLoader.getSystemClassLoader()
186 .loadClass(cname);
187 mgr = (LogManager) clz.newInstance();
188 } catch (ClassNotFoundException ex) {
189 Class<?> clz = Thread.currentThread()
190 .getContextClassLoader().loadClass(cname);
191 mgr = (LogManager) clz.newInstance();
192 }
193 }
194 } catch (Exception ex) {
1154 * return value from {@code LogManager.getLogger()} for null to properly
1155 * handle the case where the Logger has been garbage collected in the
1156 * time since its name was returned by this method.
1157 *
1158 * @return enumeration of logger name strings
1159 */
1160 public Enumeration<String> getLoggerNames() {
1161 return getUserContext().getLoggerNames();
1162 }
1163
1164 /**
1165 * Reinitialize the logging properties and reread the logging configuration.
1166 * <p>
1167 * The same rules are used for locating the configuration properties
1168 * as are used at startup. So normally the logging properties will
1169 * be re-read from the same file that was used at startup.
1170 * <P>
1171 * Any log level definitions in the new configuration file will be
1172 * applied using Logger.setLevel(), if the target Logger exists.
1173 * <p>
1174 * Any {@linkplain #addConfigurationListener registered configuration
1175 * listener} will be invoked after the properties are read.
1176 *
1177 * @exception SecurityException if a security manager exists and if
1178 * the caller does not have LoggingPermission("control").
1179 * @exception IOException if there are IO problems reading the configuration.
1180 */
1181 public void readConfiguration() throws IOException, SecurityException {
1182 checkPermission();
1183
1184 // if a configuration class is specified, load it and use it.
1185 String cname = System.getProperty("java.util.logging.config.class");
1186 if (cname != null) {
1187 try {
1188 // Instantiate the named class. It is its constructor's
1189 // responsibility to initialize the logging configuration, by
1190 // calling readConfiguration(InputStream) with a suitable stream.
1191 try {
1192 Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
1193 clz.newInstance();
1194 return;
1195 } catch (ClassNotFoundException ex) {
1289 }
1290 if (hands.charAt(end) == ',') {
1291 break;
1292 }
1293 end++;
1294 }
1295 String word = hands.substring(ix, end);
1296 ix = end+1;
1297 word = word.trim();
1298 if (word.length() == 0) {
1299 continue;
1300 }
1301 result.add(word);
1302 }
1303 return result.toArray(new String[result.size()]);
1304 }
1305
1306 /**
1307 * Reinitialize the logging properties and reread the logging configuration
1308 * from the given stream, which should be in java.util.Properties format.
1309 * Any {@linkplain #addConfigurationListener registered configuration
1310 * listener} will be invoked after the properties are read.
1311 * <p>
1312 * Any log level definitions in the new configuration file will be
1313 * applied using Logger.setLevel(), if the target Logger exists.
1314 *
1315 * @param ins stream to read properties from
1316 * @exception SecurityException if a security manager exists and if
1317 * the caller does not have LoggingPermission("control").
1318 * @exception IOException if there are problems reading from the stream.
1319 */
1320 public void readConfiguration(InputStream ins) throws IOException, SecurityException {
1321 checkPermission();
1322 reset();
1323
1324 // Load the properties
1325 props.load(ins);
1326 // Instantiate new configuration objects.
1327 String names[] = parseClassNames("config");
1328
1329 for (String word : names) {
1330 try {
1331 Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word);
1332 clz.newInstance();
1333 } catch (Exception ex) {
1334 System.err.println("Can't load config class \"" + word + "\"");
1335 System.err.println("" + ex);
1336 // ex.printStackTrace();
1337 }
1338 }
1339
1340 // Set levels on any pre-existing loggers, based on the new properties.
1341 setLevelsOnExistingLoggers();
1342
1343 try {
1344 invokeConfigurationListeners();
1345 } finally {
1346 // Note that we need to reinitialize global handles when
1347 // they are first referenced.
1348 synchronized (this) {
1349 initializedGlobalHandlers = false;
1350 }
1351 }
1352 }
1353
1354 /**
1355 * Get the value of a logging property.
1356 * The method returns null if the property is not found.
1357 * @param name property name
1358 * @return property value
1359 */
1360 public String getProperty(String name) {
1361 return props.getProperty(name);
1362 }
1363
1364 // Package private method to get a String property.
1365 // If the property is not defined we return the given
1366 // default value.
1367 String getStringProperty(String name, String defaultValue) {
1368 String val = getProperty(name);
1369 if (val == null) {
1370 return defaultValue;
1371 }
1372 return val.trim();
1612 * Returns <tt>LoggingMXBean</tt> for managing loggers.
1613 * An alternative way to manage loggers is through the
1614 * {@link java.lang.management.PlatformLoggingMXBean} interface
1615 * that can be obtained by calling:
1616 * <pre>
1617 * PlatformLoggingMXBean logging = {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
1618 * ManagementFactory.getPlatformMXBean}(PlatformLoggingMXBean.class);
1619 * </pre>
1620 *
1621 * @return a {@link LoggingMXBean} object.
1622 *
1623 * @see java.lang.management.PlatformLoggingMXBean
1624 * @since 1.5
1625 */
1626 public static synchronized LoggingMXBean getLoggingMXBean() {
1627 if (loggingMXBean == null) {
1628 loggingMXBean = new Logging();
1629 }
1630 return loggingMXBean;
1631 }
1632
1633 /**
1634 * Adds a configuration listener to be invoked each time the logging
1635 * configuration is read.
1636 * If the listener is already registered the method does nothing.
1637 * <p>
1638 * The listener is invoked with privileges that are restricted by the
1639 * calling context of this method.
1640 * The order in which the listeners are invoked is unspecified.
1641 * <p>
1642 * It is recommended that listeners do not throw errors or exceptions.
1643 *
1644 * If a listener terminates with an uncaught error or exception then
1645 * the first exception will be propagated to the caller of
1646 * {@link #readConfiguration()} (or {@link #readConfiguration(java.io.InputStream)})
1647 * after all listeners have been invoked.
1648 *
1649 * @param listener A configuration listener that will be invoked after the
1650 * configuration changed.
1651 * @return This LogManager.
1652 * @throws SecurityException if a security manager exists and if the
1653 * caller does not have LoggingPermission("control").
1654 * @throws NullPointerException if the listener is null.
1655 *
1656 * @since 1.9
1657 */
1658 public LogManager addConfigurationListener(Runnable listener) {
1659 final Runnable r = Objects.requireNonNull(listener);
1660 checkPermission();
1661 final SecurityManager sm = System.getSecurityManager();
1662 final AccessControlContext acc =
1663 sm == null ? null : AccessController.getContext();
1664 final PrivilegedAction<Void> pa =
1665 acc == null ? null : () -> { r.run() ; return null; };
1666 final Runnable pr =
1667 acc == null ? r : () -> AccessController.doPrivileged(pa, acc);
1668 // Will do nothing if already registered.
1669 listeners.putIfAbsent(r, pr);
1670 return this;
1671 }
1672
1673 /**
1674 * Removes a previously registered configuration listener.
1675 *
1676 * Returns silently if the listener is not found.
1677 *
1678 * @param listener the configuration listener to remove.
1679 * @throws NullPointerException if the listener is null.
1680 * @throws SecurityException if a security manager exists and if the
1681 * caller does not have LoggingPermission("control").
1682 *
1683 * @since 1.9
1684 */
1685 public void removeConfigurationListener(Runnable listener) {
1686 final Runnable key = Objects.requireNonNull(listener);
1687 checkPermission();
1688 listeners.remove(key);
1689 }
1690
1691 private void invokeConfigurationListeners() {
1692 Throwable t = null;
1693
1694 // We're using an IdentityHashMap because we want to compare
1695 // keys using identity (==).
1696 // We don't want to loop within a block synchronized on 'listeners'
1697 // to avoid invoking listeners from yet another synchronized block.
1698 // So we're taking a snapshot of the values list to avoid the risk of
1699 // ConcurrentModificationException while looping.
1700 //
1701 for (Runnable c : listeners.values().toArray(new Runnable[0])) {
1702 try {
1703 c.run();
1704 } catch (ThreadDeath death) {
1705 throw death;
1706 } catch (Error | RuntimeException x) {
1707 if (t == null) t = x;
1708 else t.addSuppressed(x);
1709 }
1710 }
1711 // Listeners are not supposed to throw exceptions, but if that
1712 // happens, we will rethrow the first error or exception that is raised
1713 // after all listeners have been invoked.
1714 if (t instanceof Error) throw (Error)t;
1715 if (t instanceof RuntimeException) throw (RuntimeException)t;
1716 }
1717
1718 }
|