1 /*
2 * Copyright (c) 2000, 2017, 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
379 // We use initializedCalled to break the recursion.
380 initializedCalled = true;
381 try {
382 AccessController.doPrivileged(new PrivilegedAction<Object>() {
383 @Override
384 public Object run() {
385 assert rootLogger == null;
386 assert initializedCalled && !initializationDone;
387
388 // create root logger before reading primordial
389 // configuration - to ensure that it will be added
390 // before the global logger, and not after.
391 final Logger root = owner.rootLogger = owner.new RootLogger();
392
393 // Read configuration.
394 owner.readPrimordialConfiguration();
395
396 // Create and retain Logger for the root of the namespace.
397 owner.addLogger(root);
398
399 // For backward compatibility: add any handlers configured using
400 // ".handlers"
401 owner.createLoggerHandlers("", ".handlers")
402 .stream()
403 .forEach(root::addHandler);
404
405 // Initialize level if not yet initialized
406 if (!root.isLevelInitialized()) {
407 root.setLevel(defaultLevel);
408 }
409
410 // Adding the global Logger.
411 // Do not call Logger.getGlobal() here as this might trigger
412 // subtle inter-dependency issues.
413 @SuppressWarnings("deprecation")
414 final Logger global = Logger.global;
415
416 // Make sure the global logger will be registered in the
417 // global manager
418 owner.addLogger(global);
419 return null;
420 }
421 });
422 } finally {
423 initializationDone = true;
424 }
978 }
979 });
980 }
981
982 private void setLoggerHandlers(final Logger logger, final String name,
983 final String handlersPropertyName,
984 List<Handler> handlers)
985 {
986 final boolean ensureCloseOnReset = ! handlers.isEmpty()
987 && getBooleanProperty(handlersPropertyName + ".ensureCloseOnReset",true);
988 int count = 0;
989 for (Handler hdl : handlers) {
990 logger.addHandler(hdl);
991 if (++count == 1 && ensureCloseOnReset) {
992 // add this logger to the closeOnResetLoggers list.
993 closeOnResetLoggers.addIfAbsent(CloseOnReset.create(logger));
994 }
995 }
996 }
997
998 private List<Handler> createLoggerHandlers(final String name, final String handlersPropertyName)
999 {
1000 String names[] = parseClassNames(handlersPropertyName);
1001 List<Handler> handlers = new ArrayList<>(names.length);
1002 for (String type : names) {
1003 try {
1004 @SuppressWarnings("deprecation")
1005 Object o = ClassLoader.getSystemClassLoader().loadClass(type).newInstance();
1006 Handler hdl = (Handler) o;
1007 // Check if there is a property defining the
1008 // this handler's level.
1009 String levs = getProperty(type + ".level");
1010 if (levs != null) {
1011 Level l = Level.findLevel(levs);
1012 if (l != null) {
1013 hdl.setLevel(l);
1014 } else {
1015 // Probably a bad level. Drop through.
1016 System.err.println("Can't set level for " + type);
1017 }
1018 }
1158 // - minimum: 0.02 ms
1159 // - maximum: 10.9 ms
1160 //
1161 private final static int MAX_ITERATIONS = 400;
1162 final void drainLoggerRefQueueBounded() {
1163 for (int i = 0; i < MAX_ITERATIONS; i++) {
1164 if (loggerRefQueue == null) {
1165 // haven't finished loading LogManager yet
1166 break;
1167 }
1168
1169 LoggerWeakRef ref = (LoggerWeakRef) loggerRefQueue.poll();
1170 if (ref == null) {
1171 break;
1172 }
1173 // a Logger object has been GC'ed so clean it up
1174 ref.dispose();
1175 }
1176 }
1177
1178 /**
1179 * Add a named logger. This does nothing and returns false if a logger
1180 * with the same name is already registered.
1181 * <p>
1182 * The Logger factory methods call this method to register each
1183 * newly created Logger.
1184 * <p>
1185 * The application should retain its own reference to the Logger
1186 * object to avoid it being garbage collected. The LogManager
1187 * may only retain a weak reference.
1188 *
1189 * @param logger the new logger.
1190 * @return true if the argument logger was registered successfully,
1191 * false if a logger of that name already exists.
1192 * @exception NullPointerException if the logger name is null.
1193 */
1194 public boolean addLogger(Logger logger) {
1195 final String name = logger.getName();
1196 if (name == null) {
1197 throw new NullPointerException();
1198 }
1199 drainLoggerRefQueueBounded();
1200 LoggerContext cx = getUserContext();
1201 if (cx.addLocalLogger(logger)) {
1202 // Do we have a per logger handler too?
1203 // Note: this will add a 200ms penalty
1204 loadLoggerHandlers(logger, name, name + ".handlers");
1205 return true;
1206 } else {
1207 return false;
1208 }
1209 }
1210
1211 // Private method to set a level on a logger.
1212 // If necessary, we raise privilege before doing the call.
1213 private static void doSetLevel(final Logger logger, final Level level) {
1214 SecurityManager sm = System.getSecurityManager();
1215 if (sm == null) {
1216 // There is no security manager, so things are easy.
1217 logger.setLevel(level);
1218 return;
1219 }
1220 // There is a security manager. Raise privilege before
1221 // calling setLevel.
1222 AccessController.doPrivileged(new PrivilegedAction<Object>() {
1223 @Override
1224 public Object run() {
1225 logger.setLevel(level);
|
1 /*
2 * Copyright (c) 2000, 2018, 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
379 // We use initializedCalled to break the recursion.
380 initializedCalled = true;
381 try {
382 AccessController.doPrivileged(new PrivilegedAction<Object>() {
383 @Override
384 public Object run() {
385 assert rootLogger == null;
386 assert initializedCalled && !initializationDone;
387
388 // create root logger before reading primordial
389 // configuration - to ensure that it will be added
390 // before the global logger, and not after.
391 final Logger root = owner.rootLogger = owner.new RootLogger();
392
393 // Read configuration.
394 owner.readPrimordialConfiguration();
395
396 // Create and retain Logger for the root of the namespace.
397 owner.addLogger(root);
398
399 // Initialize level if not yet initialized
400 if (!root.isLevelInitialized()) {
401 root.setLevel(defaultLevel);
402 }
403
404 // Adding the global Logger.
405 // Do not call Logger.getGlobal() here as this might trigger
406 // subtle inter-dependency issues.
407 @SuppressWarnings("deprecation")
408 final Logger global = Logger.global;
409
410 // Make sure the global logger will be registered in the
411 // global manager
412 owner.addLogger(global);
413 return null;
414 }
415 });
416 } finally {
417 initializationDone = true;
418 }
972 }
973 });
974 }
975
976 private void setLoggerHandlers(final Logger logger, final String name,
977 final String handlersPropertyName,
978 List<Handler> handlers)
979 {
980 final boolean ensureCloseOnReset = ! handlers.isEmpty()
981 && getBooleanProperty(handlersPropertyName + ".ensureCloseOnReset",true);
982 int count = 0;
983 for (Handler hdl : handlers) {
984 logger.addHandler(hdl);
985 if (++count == 1 && ensureCloseOnReset) {
986 // add this logger to the closeOnResetLoggers list.
987 closeOnResetLoggers.addIfAbsent(CloseOnReset.create(logger));
988 }
989 }
990 }
991
992 private List<Handler> createLoggerHandlers(final String name,
993 final String handlersPropertyName)
994 {
995 String names[] = parseClassNames(handlersPropertyName);
996 List<Handler> handlers = new ArrayList<>(names.length);
997 for (String type : names) {
998 try {
999 @SuppressWarnings("deprecation")
1000 Object o = ClassLoader.getSystemClassLoader().loadClass(type).newInstance();
1001 Handler hdl = (Handler) o;
1002 // Check if there is a property defining the
1003 // this handler's level.
1004 String levs = getProperty(type + ".level");
1005 if (levs != null) {
1006 Level l = Level.findLevel(levs);
1007 if (l != null) {
1008 hdl.setLevel(l);
1009 } else {
1010 // Probably a bad level. Drop through.
1011 System.err.println("Can't set level for " + type);
1012 }
1013 }
1153 // - minimum: 0.02 ms
1154 // - maximum: 10.9 ms
1155 //
1156 private final static int MAX_ITERATIONS = 400;
1157 final void drainLoggerRefQueueBounded() {
1158 for (int i = 0; i < MAX_ITERATIONS; i++) {
1159 if (loggerRefQueue == null) {
1160 // haven't finished loading LogManager yet
1161 break;
1162 }
1163
1164 LoggerWeakRef ref = (LoggerWeakRef) loggerRefQueue.poll();
1165 if (ref == null) {
1166 break;
1167 }
1168 // a Logger object has been GC'ed so clean it up
1169 ref.dispose();
1170 }
1171 }
1172
1173 @SuppressWarnings("deprecation")
1174 private boolean isSpecialLogger(Logger logger) {
1175 assert logger != null;
1176 return logger == rootLogger || logger == Logger.global;
1177 }
1178
1179 /**
1180 * Add a named logger. This does nothing and returns false if a logger
1181 * with the same name is already registered.
1182 * <p>
1183 * The Logger factory methods call this method to register each
1184 * newly created Logger.
1185 * <p>
1186 * The application should retain its own reference to the Logger
1187 * object to avoid it being garbage collected. The LogManager
1188 * may only retain a weak reference.
1189 *
1190 * @param logger the new logger.
1191 * @return true if the argument logger was registered successfully,
1192 * false if a logger of that name already exists.
1193 * @exception NullPointerException if the logger name is null.
1194 */
1195 public boolean addLogger(Logger logger) {
1196 final String name = logger.getName();
1197 if (name == null) {
1198 throw new NullPointerException();
1199 }
1200 drainLoggerRefQueueBounded();
1201 LoggerContext cx = getUserContext();
1202 if (cx.addLocalLogger(logger)) {
1203 // Do we have a per logger handler too?
1204 // Note: this will add a 200ms penalty
1205 loadLoggerHandlers(logger, name, name + ".handlers");
1206 return true;
1207 } else if (isSpecialLogger(logger)
1208 && !initializationDone
1209 && initializedCalled
1210 && configurationLock.isHeldByCurrentThread()) {
1211 // Called just after reading the primordial configuration, in
1212 // the same thread that read it.
1213 // The root and global logger would already be present in the context
1214 // by this point, but we would not have called loadLoggerHandlers
1215 // yet.
1216 // For backward compatibility: add any handlers configured using
1217 // ".handlers" to the root logger, or any handlers configured
1218 // with "global.handlers" to the global logger.
1219 loadLoggerHandlers(logger, name, name + ".handlers");
1220 return true;
1221 } else {
1222 return false;
1223 }
1224 }
1225
1226 // Private method to set a level on a logger.
1227 // If necessary, we raise privilege before doing the call.
1228 private static void doSetLevel(final Logger logger, final Level level) {
1229 SecurityManager sm = System.getSecurityManager();
1230 if (sm == null) {
1231 // There is no security manager, so things are easy.
1232 logger.setLevel(level);
1233 return;
1234 }
1235 // There is a security manager. Raise privilege before
1236 // calling setLevel.
1237 AccessController.doPrivileged(new PrivilegedAction<Object>() {
1238 @Override
1239 public Object run() {
1240 logger.setLevel(level);
|