1 /*
2 * Copyright (c) 2000, 2006, 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
166 private static final int offValue = Level.OFF.intValue();
167 private LogManager manager;
168 private String name;
169 private final CopyOnWriteArrayList<Handler> handlers =
170 new CopyOnWriteArrayList<Handler>();
171 private String resourceBundleName;
172 private volatile boolean useParentHandlers = true;
173 private volatile Filter filter;
174 private boolean anonymous;
175
176 private ResourceBundle catalog; // Cached resource bundle
177 private String catalogName; // name associated with catalog
178 private Locale catalogLocale; // locale associated with catalog
179
180 // The fields relating to parent-child relationships and levels
181 // are managed under a separate lock, the treeLock.
182 private static Object treeLock = new Object();
183 // We keep weak references from parents to children, but strong
184 // references from children to parents.
185 private volatile Logger parent; // our nearest parent.
186 private ArrayList<WeakReference<Logger>> kids; // WeakReferences to loggers that have us as parent
187 private volatile Level levelObject;
188 private volatile int levelValue; // current effective level value
189
190 /**
191 * GLOBAL_LOGGER_NAME is a name for the global logger.
192 *
193 * @since 1.6
194 */
195 public static final String GLOBAL_LOGGER_NAME = "global";
196
197 /**
198 * Return global logger object with the name Logger.GLOBAL_LOGGER_NAME.
199 *
200 * @return global logger object
201 * @since 1.7
202 */
203 public static final Logger getGlobal() {
204 return global;
205 }
206
349 /**
350 * Create an anonymous Logger. The newly created Logger is not
351 * registered in the LogManager namespace. There will be no
352 * access checks on updates to the logger.
353 * <p>
354 * This factory method is primarily intended for use from applets.
355 * Because the resulting Logger is anonymous it can be kept private
356 * by the creating class. This removes the need for normal security
357 * checks, which in turn allows untrusted applet code to update
358 * the control state of the Logger. For example an applet can do
359 * a setLevel or an addHandler on an anonymous Logger.
360 * <p>
361 * Even although the new logger is anonymous, it is configured
362 * to have the root logger ("") as its parent. This means that
363 * by default it inherits its effective level and handlers
364 * from the root logger.
365 * <p>
366 *
367 * @return a newly created private Logger
368 */
369 public static synchronized Logger getAnonymousLogger() {
370 LogManager manager = LogManager.getLogManager();
371 Logger result = new Logger(null, null);
372 result.anonymous = true;
373 Logger root = manager.getLogger("");
374 result.doSetParent(root);
375 return result;
376 }
377
378 /**
379 * Create an anonymous Logger. The newly created Logger is not
380 * registered in the LogManager namespace. There will be no
381 * access checks on updates to the logger.
382 * <p>
383 * This factory method is primarily intended for use from applets.
384 * Because the resulting Logger is anonymous it can be kept private
385 * by the creating class. This removes the need for normal security
386 * checks, which in turn allows untrusted applet code to update
387 * the control state of the Logger. For example an applet can do
388 * a setLevel or an addHandler on an anonymous Logger.
389 * <p>
390 * Even although the new logger is anonymous, it is configured
391 * to have the root logger ("") as its parent. This means that
392 * by default it inherits its effective level and handlers
393 * from the root logger.
394 * <p>
395 * @param resourceBundleName name of ResourceBundle to be used for localizing
396 * messages for this logger.
397 * May be null if none of the messages require localization.
398 * @return a newly created private Logger
399 * @throws MissingResourceException if the resourceBundleName is non-null and
400 * no corresponding resource can be found.
401 */
402 public static synchronized Logger getAnonymousLogger(String resourceBundleName) {
403 LogManager manager = LogManager.getLogManager();
404 Logger result = new Logger(null, resourceBundleName);
405 result.anonymous = true;
406 Logger root = manager.getLogger("");
407 result.doSetParent(root);
408 return result;
409 }
410
411 /**
412 * Retrieve the localization resource bundle for this
413 * logger for the current default locale. Note that if
414 * the result is null, then the Logger will use a resource
415 * bundle inherited from its parent.
416 *
417 * @return localization bundle (may be null)
418 */
419 public ResourceBundle getResourceBundle() {
420 return findResourceBundle(getResourceBundleName());
421 }
422
423 /**
1363 * the caller does not have LoggingPermission("control").
1364 */
1365 public void setParent(Logger parent) {
1366 if (parent == null) {
1367 throw new NullPointerException();
1368 }
1369 manager.checkAccess();
1370 doSetParent(parent);
1371 }
1372
1373 // Private method to do the work for parenting a child
1374 // Logger onto a parent logger.
1375 private void doSetParent(Logger newParent) {
1376
1377 // System.err.println("doSetParent \"" + getName() + "\" \""
1378 // + newParent.getName() + "\"");
1379
1380 synchronized (treeLock) {
1381
1382 // Remove ourself from any previous parent.
1383 if (parent != null) {
1384 // assert parent.kids != null;
1385 for (Iterator<WeakReference<Logger>> iter = parent.kids.iterator(); iter.hasNext(); ) {
1386 WeakReference<Logger> ref = iter.next();
1387 Logger kid = ref.get();
1388 if (kid == this) {
1389 iter.remove();
1390 break;
1391 }
1392 }
1393 // We have now removed ourself from our parents' kids.
1394 }
1395
1396 // Set our new parent.
1397 parent = newParent;
1398 if (parent.kids == null) {
1399 parent.kids = new ArrayList<WeakReference<Logger>>(2);
1400 }
1401 parent.kids.add(new WeakReference<Logger>(this));
1402
1403 // As a result of the reparenting, the effective level
1404 // may have changed for us and our children.
1405 updateEffectiveLevel();
1406
1407 }
1408 }
1409
1410 // Recalculate the effective level for this node and
1411 // recursively for our children.
1412
1413 private void updateEffectiveLevel() {
1414 // assert Thread.holdsLock(treeLock);
1415
1416 // Figure out our current effective level.
1417 int newLevelValue;
1418 if (levelObject != null) {
1419 newLevelValue = levelObject.intValue();
1420 } else {
1421 if (parent != null) {
1422 newLevelValue = parent.levelValue;
1423 } else {
1424 // This may happen during initialization.
1425 newLevelValue = Level.INFO.intValue();
1426 }
1427 }
1428
1429 // If our effective value hasn't changed, we're done.
1430 if (levelValue == newLevelValue) {
1431 return;
1432 }
1433
1434 levelValue = newLevelValue;
1435
1436 // System.err.println("effective level: \"" + getName() + "\" := " + level);
1437
1438 // Recursively update the level on each of our kids.
1439 if (kids != null) {
1440 for (int i = 0; i < kids.size(); i++) {
1441 WeakReference<Logger> ref = kids.get(i);
1442 Logger kid = ref.get();
1443 if (kid != null) {
1444 kid.updateEffectiveLevel();
1445 }
1446 }
1447 }
1448 }
1449
1450
1451 // Private method to get the potentially inherited
1452 // resource bundle name for this Logger.
1453 // May return null
1454 private String getEffectiveResourceBundleName() {
1455 Logger target = this;
1456 while (target != null) {
1457 String rbn = target.getResourceBundleName();
1458 if (rbn != null) {
1459 return rbn;
1460 }
1461 target = target.getParent();
|
1 /*
2 * Copyright (c) 2000, 2010, 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
166 private static final int offValue = Level.OFF.intValue();
167 private LogManager manager;
168 private String name;
169 private final CopyOnWriteArrayList<Handler> handlers =
170 new CopyOnWriteArrayList<Handler>();
171 private String resourceBundleName;
172 private volatile boolean useParentHandlers = true;
173 private volatile Filter filter;
174 private boolean anonymous;
175
176 private ResourceBundle catalog; // Cached resource bundle
177 private String catalogName; // name associated with catalog
178 private Locale catalogLocale; // locale associated with catalog
179
180 // The fields relating to parent-child relationships and levels
181 // are managed under a separate lock, the treeLock.
182 private static Object treeLock = new Object();
183 // We keep weak references from parents to children, but strong
184 // references from children to parents.
185 private volatile Logger parent; // our nearest parent.
186 private ArrayList<LogManager.LoggerWeakRef> kids; // WeakReferences to loggers that have us as parent
187 private volatile Level levelObject;
188 private volatile int levelValue; // current effective level value
189
190 /**
191 * GLOBAL_LOGGER_NAME is a name for the global logger.
192 *
193 * @since 1.6
194 */
195 public static final String GLOBAL_LOGGER_NAME = "global";
196
197 /**
198 * Return global logger object with the name Logger.GLOBAL_LOGGER_NAME.
199 *
200 * @return global logger object
201 * @since 1.7
202 */
203 public static final Logger getGlobal() {
204 return global;
205 }
206
349 /**
350 * Create an anonymous Logger. The newly created Logger is not
351 * registered in the LogManager namespace. There will be no
352 * access checks on updates to the logger.
353 * <p>
354 * This factory method is primarily intended for use from applets.
355 * Because the resulting Logger is anonymous it can be kept private
356 * by the creating class. This removes the need for normal security
357 * checks, which in turn allows untrusted applet code to update
358 * the control state of the Logger. For example an applet can do
359 * a setLevel or an addHandler on an anonymous Logger.
360 * <p>
361 * Even although the new logger is anonymous, it is configured
362 * to have the root logger ("") as its parent. This means that
363 * by default it inherits its effective level and handlers
364 * from the root logger.
365 * <p>
366 *
367 * @return a newly created private Logger
368 */
369 public static Logger getAnonymousLogger() {
370 return getAnonymousLogger(null);
371 }
372
373 /**
374 * Create an anonymous Logger. The newly created Logger is not
375 * registered in the LogManager namespace. There will be no
376 * access checks on updates to the logger.
377 * <p>
378 * This factory method is primarily intended for use from applets.
379 * Because the resulting Logger is anonymous it can be kept private
380 * by the creating class. This removes the need for normal security
381 * checks, which in turn allows untrusted applet code to update
382 * the control state of the Logger. For example an applet can do
383 * a setLevel or an addHandler on an anonymous Logger.
384 * <p>
385 * Even although the new logger is anonymous, it is configured
386 * to have the root logger ("") as its parent. This means that
387 * by default it inherits its effective level and handlers
388 * from the root logger.
389 * <p>
390 * @param resourceBundleName name of ResourceBundle to be used for localizing
391 * messages for this logger.
392 * May be null if none of the messages require localization.
393 * @return a newly created private Logger
394 * @throws MissingResourceException if the resourceBundleName is non-null and
395 * no corresponding resource can be found.
396 */
397 public static synchronized Logger getAnonymousLogger(String resourceBundleName) {
398 LogManager manager = LogManager.getLogManager();
399 // cleanup some Loggers that have been GC'ed
400 manager.drainLoggerRefQueueBounded();
401 Logger result = new Logger(null, resourceBundleName);
402 result.anonymous = true;
403 Logger root = manager.getLogger("");
404 result.doSetParent(root);
405 return result;
406 }
407
408 /**
409 * Retrieve the localization resource bundle for this
410 * logger for the current default locale. Note that if
411 * the result is null, then the Logger will use a resource
412 * bundle inherited from its parent.
413 *
414 * @return localization bundle (may be null)
415 */
416 public ResourceBundle getResourceBundle() {
417 return findResourceBundle(getResourceBundleName());
418 }
419
420 /**
1360 * the caller does not have LoggingPermission("control").
1361 */
1362 public void setParent(Logger parent) {
1363 if (parent == null) {
1364 throw new NullPointerException();
1365 }
1366 manager.checkAccess();
1367 doSetParent(parent);
1368 }
1369
1370 // Private method to do the work for parenting a child
1371 // Logger onto a parent logger.
1372 private void doSetParent(Logger newParent) {
1373
1374 // System.err.println("doSetParent \"" + getName() + "\" \""
1375 // + newParent.getName() + "\"");
1376
1377 synchronized (treeLock) {
1378
1379 // Remove ourself from any previous parent.
1380 LogManager.LoggerWeakRef ref = null;
1381 if (parent != null) {
1382 // assert parent.kids != null;
1383 for (Iterator<LogManager.LoggerWeakRef> iter = parent.kids.iterator(); iter.hasNext(); ) {
1384 ref = iter.next();
1385 Logger kid = ref.get();
1386 if (kid == this) {
1387 // ref is used down below to complete the reparenting
1388 iter.remove();
1389 break;
1390 } else {
1391 ref = null;
1392 }
1393 }
1394 // We have now removed ourself from our parents' kids.
1395 }
1396
1397 // Set our new parent.
1398 parent = newParent;
1399 if (parent.kids == null) {
1400 parent.kids = new ArrayList<LogManager.LoggerWeakRef>(2);
1401 }
1402 if (ref == null) {
1403 // we didn't have a previous parent
1404 ref = manager.new LoggerWeakRef(this);
1405 }
1406 ref.setParentRef(new WeakReference<Logger>(parent));
1407 parent.kids.add(ref);
1408
1409 // As a result of the reparenting, the effective level
1410 // may have changed for us and our children.
1411 updateEffectiveLevel();
1412
1413 }
1414 }
1415
1416 // Package-level method.
1417 // Remove the weak reference for the specified child Logger from the
1418 // kid list. We should only be called from LoggerWeakRef.dispose().
1419 final void removeChildLogger(LogManager.LoggerWeakRef child) {
1420 synchronized (treeLock) {
1421 for (Iterator<LogManager.LoggerWeakRef> iter = kids.iterator(); iter.hasNext(); ) {
1422 LogManager.LoggerWeakRef ref = iter.next();
1423 if (ref == child) {
1424 iter.remove();
1425 return;
1426 }
1427 }
1428 }
1429 }
1430
1431 // Recalculate the effective level for this node and
1432 // recursively for our children.
1433
1434 private void updateEffectiveLevel() {
1435 // assert Thread.holdsLock(treeLock);
1436
1437 // Figure out our current effective level.
1438 int newLevelValue;
1439 if (levelObject != null) {
1440 newLevelValue = levelObject.intValue();
1441 } else {
1442 if (parent != null) {
1443 newLevelValue = parent.levelValue;
1444 } else {
1445 // This may happen during initialization.
1446 newLevelValue = Level.INFO.intValue();
1447 }
1448 }
1449
1450 // If our effective value hasn't changed, we're done.
1451 if (levelValue == newLevelValue) {
1452 return;
1453 }
1454
1455 levelValue = newLevelValue;
1456
1457 // System.err.println("effective level: \"" + getName() + "\" := " + level);
1458
1459 // Recursively update the level on each of our kids.
1460 if (kids != null) {
1461 for (int i = 0; i < kids.size(); i++) {
1462 LogManager.LoggerWeakRef ref = kids.get(i);
1463 Logger kid = ref.get();
1464 if (kid != null) {
1465 kid.updateEffectiveLevel();
1466 }
1467 }
1468 }
1469 }
1470
1471
1472 // Private method to get the potentially inherited
1473 // resource bundle name for this Logger.
1474 // May return null
1475 private String getEffectiveResourceBundleName() {
1476 Logger target = this;
1477 while (target != null) {
1478 String rbn = target.getResourceBundleName();
1479 if (rbn != null) {
1480 return rbn;
1481 }
1482 target = target.getParent();
|