1 /* 2 * Copyright (c) 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 23 * questions. 24 */ 25 26 package sun.util.logger; 27 28 import java.lang.ref.Reference; 29 import java.lang.ref.WeakReference; 30 import java.util.HashMap; 31 import java.util.Map; 32 import java.util.function.Function; 33 import java.lang.System.LoggerFinder; 34 import java.lang.System.Logger; 35 import static java.lang.System.LoggerFinder.LOGGERFINDER_PERMISSION; 36 37 /** 38 * Internal Service Provider Interface (SPI) that makes it possible to use 39 * {@code java.util.logging} as backend when the {@link 40 * sun.util.logging.internal.JdkLoggingProvider 41 * sun.util.logging.internal.JdkLoggingProvider} is present. 42 * <p> 43 * The JDK default implementation of the {@link LoggerFinder} will 44 * attempt to locate and load an {@linkplain 45 * java.util.ServiceLoader#loadInstalled(java.lang.Class) installed} 46 * implementation of the {@code JdkLoggerProvider}. If {@code java.util.logging} 47 * is present, this will usually resolve to an instance of {@link 48 * sun.util.logging.internal.JdkLoggingProvider sun.util.logging.internal.JdkLoggingProvider}. 49 * Otherwise, if no concrete service provider is declared for 50 * {@code JdkLoggerProvider}, the default implementation provided by this class 51 * will be used. 52 * <p> 53 * When the {@link sun.util.logging.internal.JdkLoggingProvider 54 * sun.util.logging.internal.JdkLoggingProvider} is not present then the 55 * default implementation provided by this class is to use a simple logger 56 * that will log messages whose level is INFO and above to the console. 57 * These simple loggers are not configurable. 58 * <p> 59 * When configuration is needed, an application should either link with 60 * {@code java.util.logging} - and use the {@code java.util.logging} for 61 * configuration, or link with {@link LoggerFinder another implementation} 62 * of the {@link LoggerFinder} 63 * that provides the necessary configuration. 64 * 65 * @apiNote Programmers are not expected to call this class directly. 66 * Instead they should rely on the static methods defined by {@link 67 * java.lang.System java.lang.System} or {@link sun.util.logging.PlatformLogger 68 * sun.util.logging.PlatformLogger}. 69 * 70 * @see java.lang.System.LoggerFinder 71 * @see sun.util.logger 72 * @see sun.util.logging.internal 73 * 74 */ 75 public abstract class JdkLoggerProvider { 76 77 /** 78 * Creates a new instance of JdkLoggerProvider. 79 * @throws SecurityException if the calling code does not have the 80 * {@code RuntimePermission("loggerFinder")} 81 */ 82 protected JdkLoggerProvider() { 83 this(checkPermission()); 84 } 85 86 private JdkLoggerProvider(Void unused) { 87 // nothing to do. 88 } 89 90 private static Void checkPermission() { 91 final SecurityManager sm = System.getSecurityManager(); 92 if (sm != null) { 93 sm.checkPermission(LOGGERFINDER_PERMISSION); 94 } 95 return null; 96 } 97 98 // SharedLoggers is a default cache of loggers used when JUL is not 99 // present - in that case we use instances of SimpleConsoleLogger which 100 // cannot be directly configure through public APIs. 101 // 102 // We can therefore afford to simply maintain two domains - one for the 103 // system, and one for the application. 104 // 105 static final class SharedLoggers { 106 private final Map<String, Reference<Logger>> loggers = 107 new HashMap<>(); 108 109 synchronized Logger get(Function<String, Logger> loggerSupplier, final String name) { 110 Reference<Logger> ref = loggers.get(name); 111 Logger w = ref == null ? null : ref.get(); 112 if (w == null) { 113 // this could be optimized for when SecurityManager is null. 114 w = loggerSupplier.apply(name); 115 loggers.put(name, new WeakReference<>(w)); 116 } 117 return w; 118 } 119 120 121 final static SharedLoggers system = new SharedLoggers(); 122 final static SharedLoggers application = new SharedLoggers(); 123 } 124 125 /** 126 * Returns a {@link Logger logger} suitable for the caller's usage. 127 * 128 * @implSpec The default implementation for this method is to return a 129 * simple logger that will print all messages of INFO level and above 130 * to the console. That simple logger is not configurable. 131 * 132 * @param name The name of the logger. 133 * @param caller The class on behalf of which the logger is created. 134 * @return A {@link Logger logger} suitable for the caller's usage. 135 * @throws SecurityException if the calling code does not have the 136 * {@code RuntimePermission("loggerFinder")}. 137 */ 138 public final Logger getJdkLogger(String name, /* Module */ Class<?> caller) { 139 checkPermission(); 140 return demandLoggerFor(name, caller); 141 } 142 143 /** 144 * Returns a {@link Logger logger} suitable for the caller usage. 145 * 146 * @implSpec The default implementation for this method is to return a 147 * simple logger that will print all messages of INFO level and above 148 * to the console. That simple logger is not configurable. 149 * 150 * @param name The name of the logger. 151 * @param caller The class on behalf of which the logger is created. 152 * @return A {@link Logger logger} suitable for the application usage. 153 * @throws SecurityException if the calling code does not have the 154 * {@code RuntimePermission("loggerFinder")}. 155 */ 156 protected Logger demandLoggerFor(String name, /* Module */ Class<?> caller) { 157 checkPermission(); 158 if (caller.getClassLoader() == null) { 159 return SharedLoggers.system.get(SimpleConsoleLogger::makeSimpleLogger, name); 160 } else { 161 return SharedLoggers.application.get(SimpleConsoleLogger::makeSimpleLogger, name); 162 } 163 } 164 165 }