1 /* 2 * Copyright (c) 2009, 2015, 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 27 package sun.util.logging; 28 29 import java.lang.ref.WeakReference; 30 import java.util.Arrays; 31 import java.util.HashMap; 32 import java.util.Map; 33 import java.util.ResourceBundle; 34 import java.util.function.Supplier; 35 import jdk.internal.logger.LazyLoggers; 36 import jdk.internal.logger.LoggerWrapper; 37 38 /** 39 * Platform logger provides an API for the JRE components to log 40 * messages. This enables the runtime components to eliminate the 41 * static dependency of the logging facility and also defers the 42 * java.util.logging initialization until it is enabled. 43 * In addition, the PlatformLogger API can be used if the logging 44 * module does not exist. 45 * 46 * If the logging facility is not enabled, the platform loggers 47 * will output log messages per the default logging configuration 48 * (see below). In this implementation, it does not log the 49 * the stack frame information issuing the log message. 50 * 51 * When the logging facility is enabled (at startup or runtime), 52 * the backend logger will be created for each platform 53 * logger and all log messages will be forwarded to the Logger 54 * to handle. 55 * 56 * The PlatformLogger uses an underlying PlatformLogger.Bridge instance 57 * obtained by calling {@link PlatformLogger.Bridge#convert PlatformLogger.Bridge.convert(} 58 * {@link jdk.internal.logger.LazyLoggers#getLazyLogger(java.lang.String, java.lang.Class) 59 * jdk.internal.logger.LazyLoggers#getLazyLogger(name, PlatformLogger.class))}. 60 * 61 * Logging facility is "enabled" when one of the following 62 * conditions is met: 63 * 1) ServiceLoader.load({@link java.lang.System.LoggerFinder LoggerFinder.class}, 64 * ClassLoader.getSystemClassLoader()).iterator().hasNext(). 65 * 2) ServiceLoader.loadInstalled({@link jdk.internal.logger.DefaultLoggerFinder}).iterator().hasNext(), 66 * and 2.1) a system property "java.util.logging.config.class" or 67 * "java.util.logging.config.file" is set 68 * or 2.2) java.util.logging.LogManager or java.util.logging.Logger 69 * is referenced that will trigger the logging initialization. 70 * 71 * Default logging configuration: 72 * 73 * No LoggerFinder service implementation declared 74 * global logging level = INFO 75 * handlers = java.util.logging.ConsoleHandler 76 * java.util.logging.ConsoleHandler.level = INFO 77 * java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter 78 * 79 * Limitation: 80 * {@code <JAVA_HOME>/conf/logging.properties} is the system-wide logging 81 * configuration defined in the specification and read in the 82 * default case to configure any java.util.logging.Logger instances. 83 * Platform loggers will not detect if {@code <JAVA_HOME>/conf/logging.properties} 84 * is modified. In other words, unless the java.util.logging API 85 * is used at runtime or the logging system properties is set, 86 * the platform loggers will use the default setting described above. 87 * The platform loggers are designed for JDK developers use and 88 * this limitation can be workaround with setting 89 * -Djava.util.logging.config.file system property. 90 * <br> 91 * Calling PlatformLogger.setLevel will not work when there is a custom 92 * LoggerFinder installed - and as a consequence {@link #setLevel setLevel} 93 * is now deprecated. 94 * 95 * @since 1.7 96 */ 97 public class PlatformLogger { 98 99 /** 100 * PlatformLogger logging levels. 101 */ 102 public static enum Level { 103 // The name and value must match that of {@code java.util.logging.Level}s. 104 // Declare in ascending order of the given value for binary search. 105 ALL(System.Logger.Level.ALL), 106 FINEST(System.Logger.Level.TRACE), 107 FINER(System.Logger.Level.TRACE), 108 FINE(System.Logger.Level.DEBUG), 109 CONFIG(System.Logger.Level.DEBUG), 110 INFO(System.Logger.Level.INFO), 111 WARNING(System.Logger.Level.WARNING), 112 SEVERE(System.Logger.Level.ERROR), 113 OFF(System.Logger.Level.OFF); 114 115 final System.Logger.Level systemLevel; 116 Level(System.Logger.Level systemLevel) { 117 this.systemLevel = systemLevel; 118 } 119 120 // The integer values must match that of {@code java.util.logging.Level} 121 // objects. 122 private static final int SEVERITY_OFF = Integer.MAX_VALUE; 123 private static final int SEVERITY_SEVERE = 1000; 124 private static final int SEVERITY_WARNING = 900; 125 private static final int SEVERITY_INFO = 800; 126 private static final int SEVERITY_CONFIG = 700; 127 private static final int SEVERITY_FINE = 500; 128 private static final int SEVERITY_FINER = 400; 129 private static final int SEVERITY_FINEST = 300; 130 private static final int SEVERITY_ALL = Integer.MIN_VALUE; 131 132 // ascending order for binary search matching the list of enum constants 133 private static final int[] LEVEL_VALUES = new int[] { 134 SEVERITY_ALL, SEVERITY_FINEST, SEVERITY_FINER, 135 SEVERITY_FINE, SEVERITY_CONFIG, SEVERITY_INFO, 136 SEVERITY_WARNING, SEVERITY_SEVERE, SEVERITY_OFF 137 }; 138 139 public System.Logger.Level systemLevel() { 140 return systemLevel; 141 } 142 143 public int intValue() { 144 return LEVEL_VALUES[this.ordinal()]; 145 } 146 147 /** 148 * Maps a severity value to an effective logger level. 149 * @param level The severity of the messages that should be 150 * logged with a logger set to the returned level. 151 * @return The effective logger level, which is the nearest Level value 152 * whose severity is greater or equal to the given level. 153 * For level > SEVERE (OFF excluded), return SEVERE. 154 */ 155 public static Level valueOf(int level) { 156 switch (level) { 157 // ordering per the highest occurrences in the jdk source 158 // finest, fine, finer, info first 159 case SEVERITY_FINEST : return Level.FINEST; 160 case SEVERITY_FINE : return Level.FINE; 161 case SEVERITY_FINER : return Level.FINER; 162 case SEVERITY_INFO : return Level.INFO; 163 case SEVERITY_WARNING : return Level.WARNING; 164 case SEVERITY_CONFIG : return Level.CONFIG; 165 case SEVERITY_SEVERE : return Level.SEVERE; 166 case SEVERITY_OFF : return Level.OFF; 167 case SEVERITY_ALL : return Level.ALL; 168 } 169 // return the nearest Level value >= the given level, 170 // for level > SEVERE, return SEVERE and exclude OFF 171 int i = Arrays.binarySearch(LEVEL_VALUES, 0, LEVEL_VALUES.length-2, level); 172 return values()[i >= 0 ? i : (-i-1)]; 173 } 174 } 175 176 /** 177 * 178 * The PlatformLogger.Bridge interface is implemented by the System.Logger 179 * objects returned by our default JUL provider - so that JRE classes using 180 * PlatformLogger see no difference when JUL is the actual backend. 181 * 182 * PlatformLogger is now only a thin adaptation layer over the same 183 * loggers than returned by java.lang.System.getLogger(String name). 184 * 185 * The recommendation for JRE classes going forward is to use 186 * java.lang.System.getLogger(String name), which will 187 * use Lazy Loggers when possible and necessary. 188 * 189 */ 190 public static interface Bridge { 191 192 /** 193 * Gets the name for this platform logger. 194 * @return the name of the platform logger. 195 */ 196 public String getName(); 197 198 /** 199 * Returns true if a message of the given level would actually 200 * be logged by this logger. 201 * @param level the level 202 * @return whether a message of that level would be logged 203 */ 204 public boolean isLoggable(Level level); 205 public boolean isEnabled(); 206 207 public void log(Level level, String msg); 208 public void log(Level level, String msg, Throwable thrown); 209 public void log(Level level, String msg, Object... params); 210 public void log(Level level, Supplier<String> msgSupplier); 211 public void log(Level level, Throwable thrown, Supplier<String> msgSupplier); 212 public void logp(Level level, String sourceClass, String sourceMethod, String msg); 213 public void logp(Level level, String sourceClass, String sourceMethod, 214 Supplier<String> msgSupplier); 215 public void logp(Level level, String sourceClass, String sourceMethod, 216 String msg, Object... params); 217 public void logp(Level level, String sourceClass, String sourceMethod, 218 String msg, Throwable thrown); 219 public void logp(Level level, String sourceClass, String sourceMethod, 220 Throwable thrown, Supplier<String> msgSupplier); 221 public void logrb(Level level, String sourceClass, String sourceMethod, 222 ResourceBundle bundle, String msg, Object... params); 223 public void logrb(Level level, String sourceClass, String sourceMethod, 224 ResourceBundle bundle, String msg, Throwable thrown); 225 public void logrb(Level level, ResourceBundle bundle, String msg, 226 Object... params); 227 public void logrb(Level level, ResourceBundle bundle, String msg, 228 Throwable thrown); 229 230 231 public static Bridge convert(System.Logger logger) { 232 if (logger instanceof PlatformLogger.Bridge) { 233 return (Bridge) logger; 234 } else { 235 return new LoggerWrapper<>(logger); 236 } 237 } 238 } 239 240 /** 241 * The {@code PlatformLogger.ConfigurableBridge} interface is used to 242 * implement the deprecated {@link PlatformLogger#setLevel} method. 243 * 244 * PlatformLogger is now only a thin adaptation layer over the same 245 * loggers than returned by java.lang.System.getLogger(String name). 246 * 247 * The recommendation for JRE classes going forward is to use 248 * java.lang.System.getLogger(String name), which will 249 * use Lazy Loggers when possible and necessary. 250 * 251 */ 252 public static interface ConfigurableBridge { 253 254 public abstract class LoggerConfiguration { 255 public abstract Level getPlatformLevel(); 256 public abstract void setPlatformLevel(Level level); 257 } 258 259 public default LoggerConfiguration getLoggerConfiguration() { 260 return null; 261 } 262 263 public static LoggerConfiguration getLoggerConfiguration(PlatformLogger.Bridge logger) { 264 if (logger instanceof PlatformLogger.ConfigurableBridge) { 265 return ((ConfigurableBridge) logger).getLoggerConfiguration(); 266 } else { 267 return null; 268 } 269 } 270 } 271 272 // Table of known loggers. Maps names to PlatformLoggers. 273 private static final Map<String,WeakReference<PlatformLogger>> loggers = 274 new HashMap<>(); 275 276 /** 277 * Returns a PlatformLogger of a given name. 278 * @param name the name of the logger 279 * @return a PlatformLogger 280 */ 281 public static synchronized PlatformLogger getLogger(String name) { 282 PlatformLogger log = null; 283 WeakReference<PlatformLogger> ref = loggers.get(name); 284 if (ref != null) { 285 log = ref.get(); 286 } 287 if (log == null) { 288 log = new PlatformLogger(PlatformLogger.Bridge.convert( 289 // We pass PlatformLogger.class rather than the actual caller 290 // because we want PlatformLoggers to be system loggers: we 291 // won't need to resolve any resource bundles anyway. 292 // Note: Many unit tests depend on the fact that 293 // PlatformLogger.getLoggerFromFinder is not caller sensitive. 294 LazyLoggers.getLazyLogger(name, PlatformLogger.class))); 295 loggers.put(name, new WeakReference<>(log)); 296 } 297 return log; 298 } 299 300 // The system loggerProxy returned by LazyLoggers 301 // This may be a lazy logger - see jdk.internal.logger.LazyLoggers, 302 // or may be a Logger instance (or a wrapper thereof). 303 // 304 private final PlatformLogger.Bridge loggerProxy; 305 private PlatformLogger(PlatformLogger.Bridge loggerProxy) { 306 this.loggerProxy = loggerProxy; 307 } 308 309 /** 310 * A convenience method to test if the logger is turned off. 311 * (i.e. its level is OFF). 312 * @return whether the logger is turned off. 313 */ 314 public boolean isEnabled() { 315 return loggerProxy.isEnabled(); 316 } 317 318 /** 319 * Gets the name for this platform logger. 320 * @return the name of the platform logger. 321 */ 322 public String getName() { 323 return loggerProxy.getName(); 324 } 325 326 /** 327 * Returns true if a message of the given level would actually 328 * be logged by this logger. 329 * @param level the level 330 * @return whether a message of that level would be logged 331 */ 332 public boolean isLoggable(Level level) { 333 if (level == null) { 334 throw new NullPointerException(); 335 } 336 337 return loggerProxy.isLoggable(level); 338 } 339 340 /** 341 * Get the log level that has been specified for this PlatformLogger. 342 * The result may be null, which means that this logger's 343 * effective level will be inherited from its parent. 344 * 345 * @return this PlatformLogger's level 346 */ 347 public Level level() { 348 final ConfigurableBridge.LoggerConfiguration spi = 349 PlatformLogger.ConfigurableBridge.getLoggerConfiguration(loggerProxy); 350 return spi == null ? null : spi.getPlatformLevel(); 351 } 352 353 /** 354 * Set the log level specifying which message levels will be 355 * logged by this logger. Message levels lower than this 356 * value will be discarded. The level value {@link Level#OFF} 357 * can be used to turn off logging. 358 * <p> 359 * If the new level is null, it means that this node should 360 * inherit its level from its nearest ancestor with a specific 361 * (non-null) level value. 362 * 363 * @param newLevel the new value for the log level (may be null) 364 * @deprecated Platform Loggers should not be configured programmatically. 365 * This method will not work if a custom {@link 366 * java.lang.System.LoggerFinder} is installed. 367 */ 368 @Deprecated 369 public void setLevel(Level newLevel) { 370 final ConfigurableBridge.LoggerConfiguration spi = 371 PlatformLogger.ConfigurableBridge.getLoggerConfiguration(loggerProxy);; 372 if (spi != null) { 373 spi.setPlatformLevel(newLevel); 374 } 375 } 376 377 /** 378 * Logs a SEVERE message. 379 * @param msg the message 380 */ 381 public void severe(String msg) { 382 loggerProxy.log(Level.SEVERE, msg, (Object[])null); 383 } 384 385 public void severe(String msg, Throwable t) { 386 loggerProxy.log(Level.SEVERE, msg, t); 387 } 388 389 public void severe(String msg, Object... params) { 390 loggerProxy.log(Level.SEVERE, msg, params); 391 } 392 393 /** 394 * Logs a WARNING message. 395 * @param msg the message 396 */ 397 public void warning(String msg) { 398 loggerProxy.log(Level.WARNING, msg, (Object[])null); 399 } 400 401 public void warning(String msg, Throwable t) { 402 loggerProxy.log(Level.WARNING, msg, t); 403 } 404 405 public void warning(String msg, Object... params) { 406 loggerProxy.log(Level.WARNING, msg, params); 407 } 408 409 /** 410 * Logs an INFO message. 411 * @param msg the message 412 */ 413 public void info(String msg) { 414 loggerProxy.log(Level.INFO, msg, (Object[])null); 415 } 416 417 public void info(String msg, Throwable t) { 418 loggerProxy.log(Level.INFO, msg, t); 419 } 420 421 public void info(String msg, Object... params) { 422 loggerProxy.log(Level.INFO, msg, params); 423 } 424 425 /** 426 * Logs a CONFIG message. 427 * @param msg the message 428 */ 429 public void config(String msg) { 430 loggerProxy.log(Level.CONFIG, msg, (Object[])null); 431 } 432 433 public void config(String msg, Throwable t) { 434 loggerProxy.log(Level.CONFIG, msg, t); 435 } 436 437 public void config(String msg, Object... params) { 438 loggerProxy.log(Level.CONFIG, msg, params); 439 } 440 441 /** 442 * Logs a FINE message. 443 * @param msg the message 444 */ 445 public void fine(String msg) { 446 loggerProxy.log(Level.FINE, msg, (Object[])null); 447 } 448 449 public void fine(String msg, Throwable t) { 450 loggerProxy.log(Level.FINE, msg, t); 451 } 452 453 public void fine(String msg, Object... params) { 454 loggerProxy.log(Level.FINE, msg, params); 455 } 456 457 /** 458 * Logs a FINER message. 459 * @param msg the message 460 */ 461 public void finer(String msg) { 462 loggerProxy.log(Level.FINER, msg, (Object[])null); 463 } 464 465 public void finer(String msg, Throwable t) { 466 loggerProxy.log(Level.FINER, msg, t); 467 } 468 469 public void finer(String msg, Object... params) { 470 loggerProxy.log(Level.FINER, msg, params); 471 } 472 473 /** 474 * Logs a FINEST message. 475 * @param msg the message 476 */ 477 public void finest(String msg) { 478 loggerProxy.log(Level.FINEST, msg, (Object[])null); 479 } 480 481 public void finest(String msg, Throwable t) { 482 loggerProxy.log(Level.FINEST, msg, t); 483 } 484 485 public void finest(String msg, Object... params) { 486 loggerProxy.log(Level.FINEST, msg, params); 487 } 488 489 // ------------------------------------ 490 // Maps used for Level conversion 491 // ------------------------------------ 492 493 // This map is indexed by java.util.spi.Logger.Level.ordinal() and returns 494 // a PlatformLogger.Level 495 // 496 // ALL, TRACE, DEBUG, INFO, WARNING, ERROR, OFF 497 private static final Level[] spi2platformLevelMapping = { 498 Level.ALL, // mapped from ALL 499 Level.FINER, // mapped from TRACE 500 Level.FINE, // mapped from DEBUG 501 Level.INFO, // mapped from INFO 502 Level.WARNING, // mapped from WARNING 503 Level.SEVERE, // mapped from ERROR 504 Level.OFF // mapped from OFF 505 }; 506 507 public static Level toPlatformLevel(java.lang.System.Logger.Level level) { 508 if (level == null) return null; 509 assert level.ordinal() < spi2platformLevelMapping.length; 510 return spi2platformLevelMapping[level.ordinal()]; 511 } 512 513 }