23 * questions.
24 */
25
26
27 package java.util.logging;
28
29 import java.lang.ref.WeakReference;
30 import java.lang.reflect.Module;
31 import java.security.AccessController;
32 import java.security.PrivilegedAction;
33 import java.util.ArrayList;
34 import java.util.Iterator;
35 import java.util.Locale;
36 import java.util.MissingResourceException;
37 import java.util.Objects;
38 import java.util.ResourceBundle;
39 import java.util.concurrent.CopyOnWriteArrayList;
40 import java.util.function.Supplier;
41 import sun.reflect.CallerSensitive;
42 import sun.reflect.Reflection;
43
44 /**
45 * A Logger object is used to log messages for a specific
46 * system or application component. Loggers are normally named,
47 * using a hierarchical dot-separated namespace. Logger names
48 * can be arbitrary strings, but they should normally be based on
49 * the package name or class name of the logged component, such
50 * as java.net or javax.swing. In addition it is possible to create
51 * "anonymous" Loggers that are not stored in the Logger namespace.
52 * <p>
53 * Logger objects may be obtained by calls on one of the getLogger
54 * factory methods. These will either create a new Logger or
55 * return a suitable existing Logger. It is important to note that
56 * the Logger returned by one of the {@code getLogger} factory methods
57 * may be garbage collected at any time if a strong reference to the
58 * Logger is not kept.
59 * <p>
60 * Logging messages will be forwarded to registered Handler
61 * objects, which can forward the messages to a variety of
62 * destinations, including consoles, files, OS logs, etc.
362 * Protected method to construct a logger for a named subsystem.
363 * <p>
364 * The logger will be initially configured with a null Level
365 * and with useParentHandlers set to true.
366 *
367 * @param name A name for the logger. This should
368 * be a dot-separated name and should normally
369 * be based on the package name or class name
370 * of the subsystem, such as java.net
371 * or javax.swing. It may be null for anonymous Loggers.
372 * @param resourceBundleName name of ResourceBundle to be used for localizing
373 * messages for this logger. May be null if none
374 * of the messages require localization.
375 * @throws MissingResourceException if the resourceBundleName is non-null and
376 * no corresponding resource can be found.
377 */
378 protected Logger(String name, String resourceBundleName) {
379 this(name, resourceBundleName, null, LogManager.getLogManager(), false);
380 }
381
382 Logger(String name, String resourceBundleName, Class<?> caller, LogManager manager, boolean isSystemLogger) {
383 this.manager = manager;
384 this.isSystemLogger = isSystemLogger;
385 setupResourceInfo(resourceBundleName, caller);
386 this.name = name;
387 levelValue = Level.INFO.intValue();
388 }
389
390 private void setCallerModuleRef(Class<?> caller) {
391 Module callerModule = ((caller != null)
392 ? caller.getModule()
393 : null);
394 if (callerModule != null) {
395 this.callerModuleRef = new WeakReference<>(callerModule);
396 }
397 }
398
399 private Module getCallerModule() {
400 return (callerModuleRef != null)
401 ? callerModuleRef.get()
402 : null;
403 }
404
405 // This constructor is used only to create the global Logger.
406 // It is needed to break a cyclic dependence between the LogManager
407 // and Logger static initializers causing deadlocks.
408 private Logger(String name) {
409 // The manager field is not initialized here.
410 this.name = name;
411 this.isSystemLogger = true;
412 levelValue = Level.INFO.intValue();
413 }
601 // We have to set the callers ClassLoader here in case demandLogger
602 // above found a previously created Logger. This can happen, for
603 // example, if Logger.getLogger(name) is called and subsequently
604 // Logger.getLogger(name, resourceBundleName) is called. In this case
605 // we won't necessarily have the correct classloader saved away, so
606 // we need to set it here, too.
607
608 result.setupResourceInfo(resourceBundleName, callerClass);
609 return result;
610 }
611
612 // package-private
613 // Add a platform logger to the system context.
614 // i.e. caller of sun.util.logging.PlatformLogger.getLogger
615 static Logger getPlatformLogger(String name) {
616 LogManager manager = LogManager.getLogManager();
617
618 // all loggers in the system context will default to
619 // the system logger's resource bundle - therefore the caller won't
620 // be needed and can be null.
621 Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME, null);
622 return result;
623 }
624
625 /**
626 * Create an anonymous Logger. The newly created Logger is not
627 * registered in the LogManager namespace. There will be no
628 * access checks on updates to the logger.
629 * <p>
630 * This factory method is primarily intended for use from applets.
631 * Because the resulting Logger is anonymous it can be kept private
632 * by the creating class. This removes the need for normal security
633 * checks, which in turn allows untrusted applet code to update
634 * the control state of the Logger. For example an applet can do
635 * a setLevel or an addHandler on an anonymous Logger.
636 * <p>
637 * Even although the new logger is anonymous, it is configured
638 * to have the root logger ("") as its parent. This means that
639 * by default it inherits its effective level and handlers
640 * from the root logger. Changing its parent via the
641 * {@link #setParent(java.util.logging.Logger) setParent} method
664 * by default it inherits its effective level and handlers
665 * from the root logger. Changing its parent via the
666 * {@link #setParent(java.util.logging.Logger) setParent} method
667 * will still require the security permission specified by that method.
668 *
669 * @param resourceBundleName name of ResourceBundle to be used for localizing
670 * messages for this logger.
671 * May be null if none of the messages require localization.
672 * @return a newly created private Logger
673 * @throws MissingResourceException if the resourceBundleName is non-null and
674 * no corresponding resource can be found.
675 */
676
677 // Synchronization is not required here. All synchronization for
678 // adding a new anonymous Logger object is handled by doSetParent().
679 @CallerSensitive
680 public static Logger getAnonymousLogger(String resourceBundleName) {
681 LogManager manager = LogManager.getLogManager();
682 // cleanup some Loggers that have been GC'ed
683 manager.drainLoggerRefQueueBounded();
684 Logger result = new Logger(null, resourceBundleName,
685 Reflection.getCallerClass(), manager, false);
686 result.anonymous = true;
687 Logger root = manager.getLogger("");
688 result.doSetParent(root);
689 return result;
690 }
691
692 /**
693 * Retrieve the localization resource bundle for this
694 * logger.
695 * This method will return a {@code ResourceBundle} that was either
696 * set by the {@link
697 * #setResourceBundle(java.util.ResourceBundle) setResourceBundle} method or
698 * <a href="#ResourceBundleMapping">mapped from the
699 * the resource bundle name</a> set via the {@link
700 * Logger#getLogger(java.lang.String, java.lang.String) getLogger} factory
701 * method for the current default locale.
702 * <br>Note that if the result is {@code null}, then the Logger will use a resource
703 * bundle or resource bundle name inherited from its parent.
704 *
705 * @return localization bundle (may be {@code null})
2029 }
2030 }
2031 } else {
2032 // we should have:
2033 // useCallersModule && callerModule != null && callerModule.isNamed();
2034 // Try with the caller's module
2035 try {
2036 // Use the caller's module
2037 PrivilegedAction<ResourceBundle> pa = () ->
2038 ResourceBundle.getBundle(name, currentLocale, callerModule);
2039 catalog = AccessController.doPrivileged(pa, null, GET_CLASS_LOADER_PERMISSION);
2040 catalogName = name;
2041 catalogLocale = currentLocale;
2042 return catalog;
2043 } catch (MissingResourceException ex) {
2044 return null; // no luck
2045 }
2046 }
2047 }
2048
2049 // Private utility method to initialize our one entry
2050 // resource bundle name cache and the callers Module
2051 // Note: for consistency reasons, we are careful to check
2052 // that a suitable ResourceBundle exists before setting the
2053 // resourceBundleName field.
2054 // Synchronized to prevent races in setting the fields.
2055 private synchronized void setupResourceInfo(String name,
2056 Class<?> callerClass) {
2057 final LoggerBundle lb = loggerBundle;
2058 if (lb.resourceBundleName != null) {
2059 // this Logger already has a ResourceBundle
2060
2061 if (lb.resourceBundleName.equals(name)) {
2062 // the names match so there is nothing more to do
2063 return;
2064 }
2065
2066 // cannot change ResourceBundles once they are set
2067 throw new IllegalArgumentException(
2068 lb.resourceBundleName + " != " + name);
2069 }
2070
2071 if (name == null) {
2072 return;
2073 }
2074
2075 setCallerModuleRef(callerClass);
2076 if (isSystemLogger && (callerClass != null && callerClass.getClassLoader() != null)) {
2077 checkPermission();
2078 }
2079
2080 if (name.equals(SYSTEM_LOGGER_RB_NAME)) {
2081 loggerBundle = SYSTEM_BUNDLE;
2082 } else {
2083 ResourceBundle bundle = findResourceBundle(name, true);
2084 if (bundle == null) {
2085 // We've failed to find an expected ResourceBundle.
2086 // unset the caller's module since we were unable to find the
2087 // the bundle using it
2088 this.callerModuleRef = null;
2089 throw new MissingResourceException("Can't find " + name + " bundle from ",
2090 name, "");
2091 }
2092
2093 loggerBundle = LoggerBundle.get(name, null);
2094 }
2095 }
2096
|
23 * questions.
24 */
25
26
27 package java.util.logging;
28
29 import java.lang.ref.WeakReference;
30 import java.lang.reflect.Module;
31 import java.security.AccessController;
32 import java.security.PrivilegedAction;
33 import java.util.ArrayList;
34 import java.util.Iterator;
35 import java.util.Locale;
36 import java.util.MissingResourceException;
37 import java.util.Objects;
38 import java.util.ResourceBundle;
39 import java.util.concurrent.CopyOnWriteArrayList;
40 import java.util.function.Supplier;
41 import sun.reflect.CallerSensitive;
42 import sun.reflect.Reflection;
43 import static jdk.internal.logger.DefaultLoggerFinder.isSystem;
44
45 /**
46 * A Logger object is used to log messages for a specific
47 * system or application component. Loggers are normally named,
48 * using a hierarchical dot-separated namespace. Logger names
49 * can be arbitrary strings, but they should normally be based on
50 * the package name or class name of the logged component, such
51 * as java.net or javax.swing. In addition it is possible to create
52 * "anonymous" Loggers that are not stored in the Logger namespace.
53 * <p>
54 * Logger objects may be obtained by calls on one of the getLogger
55 * factory methods. These will either create a new Logger or
56 * return a suitable existing Logger. It is important to note that
57 * the Logger returned by one of the {@code getLogger} factory methods
58 * may be garbage collected at any time if a strong reference to the
59 * Logger is not kept.
60 * <p>
61 * Logging messages will be forwarded to registered Handler
62 * objects, which can forward the messages to a variety of
63 * destinations, including consoles, files, OS logs, etc.
363 * Protected method to construct a logger for a named subsystem.
364 * <p>
365 * The logger will be initially configured with a null Level
366 * and with useParentHandlers set to true.
367 *
368 * @param name A name for the logger. This should
369 * be a dot-separated name and should normally
370 * be based on the package name or class name
371 * of the subsystem, such as java.net
372 * or javax.swing. It may be null for anonymous Loggers.
373 * @param resourceBundleName name of ResourceBundle to be used for localizing
374 * messages for this logger. May be null if none
375 * of the messages require localization.
376 * @throws MissingResourceException if the resourceBundleName is non-null and
377 * no corresponding resource can be found.
378 */
379 protected Logger(String name, String resourceBundleName) {
380 this(name, resourceBundleName, null, LogManager.getLogManager(), false);
381 }
382
383 Logger(String name, String resourceBundleName, Module caller,
384 LogManager manager, boolean isSystemLogger) {
385 this.manager = manager;
386 this.isSystemLogger = isSystemLogger;
387 setupResourceInfo(resourceBundleName, caller);
388 this.name = name;
389 levelValue = Level.INFO.intValue();
390 }
391
392 private void setCallerModuleRef(Module callerModule) {
393 if (callerModule != null) {
394 this.callerModuleRef = new WeakReference<>(callerModule);
395 }
396 }
397
398 private Module getCallerModule() {
399 return (callerModuleRef != null)
400 ? callerModuleRef.get()
401 : null;
402 }
403
404 // This constructor is used only to create the global Logger.
405 // It is needed to break a cyclic dependence between the LogManager
406 // and Logger static initializers causing deadlocks.
407 private Logger(String name) {
408 // The manager field is not initialized here.
409 this.name = name;
410 this.isSystemLogger = true;
411 levelValue = Level.INFO.intValue();
412 }
600 // We have to set the callers ClassLoader here in case demandLogger
601 // above found a previously created Logger. This can happen, for
602 // example, if Logger.getLogger(name) is called and subsequently
603 // Logger.getLogger(name, resourceBundleName) is called. In this case
604 // we won't necessarily have the correct classloader saved away, so
605 // we need to set it here, too.
606
607 result.setupResourceInfo(resourceBundleName, callerClass);
608 return result;
609 }
610
611 // package-private
612 // Add a platform logger to the system context.
613 // i.e. caller of sun.util.logging.PlatformLogger.getLogger
614 static Logger getPlatformLogger(String name) {
615 LogManager manager = LogManager.getLogManager();
616
617 // all loggers in the system context will default to
618 // the system logger's resource bundle - therefore the caller won't
619 // be needed and can be null.
620 Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME, (Module)null);
621 return result;
622 }
623
624 /**
625 * Create an anonymous Logger. The newly created Logger is not
626 * registered in the LogManager namespace. There will be no
627 * access checks on updates to the logger.
628 * <p>
629 * This factory method is primarily intended for use from applets.
630 * Because the resulting Logger is anonymous it can be kept private
631 * by the creating class. This removes the need for normal security
632 * checks, which in turn allows untrusted applet code to update
633 * the control state of the Logger. For example an applet can do
634 * a setLevel or an addHandler on an anonymous Logger.
635 * <p>
636 * Even although the new logger is anonymous, it is configured
637 * to have the root logger ("") as its parent. This means that
638 * by default it inherits its effective level and handlers
639 * from the root logger. Changing its parent via the
640 * {@link #setParent(java.util.logging.Logger) setParent} method
663 * by default it inherits its effective level and handlers
664 * from the root logger. Changing its parent via the
665 * {@link #setParent(java.util.logging.Logger) setParent} method
666 * will still require the security permission specified by that method.
667 *
668 * @param resourceBundleName name of ResourceBundle to be used for localizing
669 * messages for this logger.
670 * May be null if none of the messages require localization.
671 * @return a newly created private Logger
672 * @throws MissingResourceException if the resourceBundleName is non-null and
673 * no corresponding resource can be found.
674 */
675
676 // Synchronization is not required here. All synchronization for
677 // adding a new anonymous Logger object is handled by doSetParent().
678 @CallerSensitive
679 public static Logger getAnonymousLogger(String resourceBundleName) {
680 LogManager manager = LogManager.getLogManager();
681 // cleanup some Loggers that have been GC'ed
682 manager.drainLoggerRefQueueBounded();
683 final Class<?> callerClass = Reflection.getCallerClass();
684 final Module module = callerClass.getModule();
685 Logger result = new Logger(null, resourceBundleName,
686 module, manager, false);
687 result.anonymous = true;
688 Logger root = manager.getLogger("");
689 result.doSetParent(root);
690 return result;
691 }
692
693 /**
694 * Retrieve the localization resource bundle for this
695 * logger.
696 * This method will return a {@code ResourceBundle} that was either
697 * set by the {@link
698 * #setResourceBundle(java.util.ResourceBundle) setResourceBundle} method or
699 * <a href="#ResourceBundleMapping">mapped from the
700 * the resource bundle name</a> set via the {@link
701 * Logger#getLogger(java.lang.String, java.lang.String) getLogger} factory
702 * method for the current default locale.
703 * <br>Note that if the result is {@code null}, then the Logger will use a resource
704 * bundle or resource bundle name inherited from its parent.
705 *
706 * @return localization bundle (may be {@code null})
2030 }
2031 }
2032 } else {
2033 // we should have:
2034 // useCallersModule && callerModule != null && callerModule.isNamed();
2035 // Try with the caller's module
2036 try {
2037 // Use the caller's module
2038 PrivilegedAction<ResourceBundle> pa = () ->
2039 ResourceBundle.getBundle(name, currentLocale, callerModule);
2040 catalog = AccessController.doPrivileged(pa, null, GET_CLASS_LOADER_PERMISSION);
2041 catalogName = name;
2042 catalogLocale = currentLocale;
2043 return catalog;
2044 } catch (MissingResourceException ex) {
2045 return null; // no luck
2046 }
2047 }
2048 }
2049
2050 private void setupResourceInfo(String name, Class<?> caller) {
2051 final Module module = caller == null ? null : caller.getModule();
2052 setupResourceInfo(name, module);
2053 }
2054
2055 // Private utility method to initialize our one entry
2056 // resource bundle name cache and the callers Module
2057 // Note: for consistency reasons, we are careful to check
2058 // that a suitable ResourceBundle exists before setting the
2059 // resourceBundleName field.
2060 // Synchronized to prevent races in setting the fields.
2061 private synchronized void setupResourceInfo(String name,
2062 Module callerModule) {
2063 final LoggerBundle lb = loggerBundle;
2064 if (lb.resourceBundleName != null) {
2065 // this Logger already has a ResourceBundle
2066
2067 if (lb.resourceBundleName.equals(name)) {
2068 // the names match so there is nothing more to do
2069 return;
2070 }
2071
2072 // cannot change ResourceBundles once they are set
2073 throw new IllegalArgumentException(
2074 lb.resourceBundleName + " != " + name);
2075 }
2076
2077 if (name == null) {
2078 return;
2079 }
2080
2081 setCallerModuleRef(callerModule);
2082
2083 if (isSystemLogger && (callerModule != null && !isSystem(callerModule))) {
2084 checkPermission();
2085 }
2086
2087 if (name.equals(SYSTEM_LOGGER_RB_NAME)) {
2088 loggerBundle = SYSTEM_BUNDLE;
2089 } else {
2090 ResourceBundle bundle = findResourceBundle(name, true);
2091 if (bundle == null) {
2092 // We've failed to find an expected ResourceBundle.
2093 // unset the caller's module since we were unable to find the
2094 // the bundle using it
2095 this.callerModuleRef = null;
2096 throw new MissingResourceException("Can't find " + name + " bundle from ",
2097 name, "");
2098 }
2099
2100 loggerBundle = LoggerBundle.get(name, null);
2101 }
2102 }
2103
|