< prev index next >

src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java

Print this page


   1 /*
   2  * Copyright (c) 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 package jdk.internal.logger;
  27 
  28 import java.io.PrintStream;
  29 import java.io.PrintWriter;
  30 import java.io.StringWriter;
  31 import java.lang.StackWalker.StackFrame;
  32 import java.security.AccessController;
  33 import java.security.PrivilegedAction;
  34 import java.time.ZonedDateTime;
  35 import java.util.Optional;
  36 import java.util.ResourceBundle;
  37 import java.util.function.Function;
  38 import java.lang.System.Logger;

  39 import java.util.function.Predicate;
  40 import java.util.function.Supplier;

  41 import sun.util.logging.PlatformLogger;
  42 import sun.util.logging.PlatformLogger.ConfigurableBridge.LoggerConfiguration;
  43 
  44 /**
  45  * A simple console logger to emulate the behavior of JUL loggers when
  46  * in the default configuration. SimpleConsoleLoggers are also used when
  47  * JUL is not present and no DefaultLoggerFinder is installed.
  48  */
  49 public class SimpleConsoleLogger extends LoggerConfiguration
  50     implements Logger, PlatformLogger.Bridge, PlatformLogger.ConfigurableBridge {
  51 
  52     static final PlatformLogger.Level DEFAULT_LEVEL = PlatformLogger.Level.INFO;












  53 
  54     final String name;
  55     volatile PlatformLogger.Level  level;
  56     final boolean usePlatformLevel;
  57     SimpleConsoleLogger(String name, boolean usePlatformLevel) {
  58         this.name = name;
  59         this.usePlatformLevel = usePlatformLevel;
  60     }
  61 








  62     @Override
  63     public String getName() {
  64         return name;
  65     }
  66 
  67     private Enum<?> logLevel(PlatformLogger.Level level) {
  68         return usePlatformLevel ? level : level.systemLevel();
  69     }
  70 
  71     private Enum<?> logLevel(Level level) {
  72         return usePlatformLevel ? PlatformLogger.toPlatformLevel(level) : level;
  73     }
  74 
  75     // ---------------------------------------------------
  76     //                 From Logger
  77     // ---------------------------------------------------
  78 
  79     @Override
  80     public boolean isLoggable(Level level) {
  81         return isLoggable(PlatformLogger.toPlatformLevel(level));
  82     }
  83 
  84     @Override
  85     public void log(Level level, ResourceBundle bundle, String key, Throwable thrown) {
  86         if (isLoggable(level)) {
  87             if (bundle != null) {
  88                 key = bundle.getString(key);
  89             }
  90             publish(getCallerInfo(), logLevel(level), key, thrown);
  91         }
  92     }
  93 
  94     @Override
  95     public void log(Level level, ResourceBundle bundle, String format, Object... params) {
  96         if (isLoggable(level)) {
  97             if (bundle != null) {
  98                 format = bundle.getString(format);
  99             }
 100             publish(getCallerInfo(), logLevel(level), format, params);
 101         }
 102     }
 103 
 104     // ---------------------------------------------------
 105     //             From PlatformLogger.Bridge
 106     // ---------------------------------------------------
 107 
 108     @Override
 109     public boolean isLoggable(PlatformLogger.Level level) {
 110         final PlatformLogger.Level effectiveLevel =  effectiveLevel();
 111         return level != PlatformLogger.Level.OFF
 112                 && level.ordinal() >= effectiveLevel.ordinal();
 113     }
 114 
 115     @Override
 116     public boolean isEnabled() {
 117         return level != PlatformLogger.Level.OFF;
 118     }
 119 
 120     @Override
 121     public void log(PlatformLogger.Level level, String msg) {
 122         if (isLoggable(level)) {
 123             publish(getCallerInfo(), logLevel(level), msg);
 124         }
 125     }
 126 
 127     @Override
 128     public void log(PlatformLogger.Level level, String msg, Throwable thrown) {
 129         if (isLoggable(level)) {
 130             publish(getCallerInfo(), logLevel(level), msg, thrown);
 131         }
 132     }
 133 
 134     @Override
 135     public void log(PlatformLogger.Level level, String msg, Object... params) {
 136         if (isLoggable(level)) {
 137             publish(getCallerInfo(), logLevel(level), msg, params);
 138         }
 139     }
 140 
 141     private PlatformLogger.Level effectiveLevel() {
 142         if (level == null) return DEFAULT_LEVEL;
 143         return level;
 144     }
 145 
 146     @Override
 147     public PlatformLogger.Level getPlatformLevel() {
 148         return level;
 149     }
 150 
 151     @Override
 152     public void setPlatformLevel(PlatformLogger.Level newLevel) {
 153         level = newLevel;
 154     }
 155 
 156     @Override
 157     public LoggerConfiguration getLoggerConfiguration() {
 158         return this;
 159     }
 160 
 161     /**
 162      * Default platform logging support - output messages to System.err -
 163      * equivalent to ConsoleHandler with SimpleFormatter.
 164      */
 165     static PrintStream outputStream() {
 166         return System.err;
 167     }
 168 
 169     // Returns the caller's class and method's name; best effort
 170     // if cannot infer, return the logger's name.
 171     private String getCallerInfo() {
 172         Optional<StackWalker.StackFrame> frame = new CallerFinder().get();
 173         if (frame.isPresent()) {
 174             return frame.get().getClassName() + " " + frame.get().getMethodName();
 175         } else {
 176             return name;
 177         }


 205          * Returns true if we have found the caller's frame, false if the frame
 206          * must be skipped.
 207          *
 208          * @param t The frame info.
 209          * @return true if we have found the caller's frame, false if the frame
 210          * must be skipped.
 211          */
 212         @Override
 213         public boolean test(StackWalker.StackFrame t) {
 214             final String cname = t.getClassName();
 215             // We should skip all frames until we have found the logger,
 216             // because these frames could be frames introduced by e.g. custom
 217             // sub classes of Handler.
 218             if (lookingForLogger) {
 219                 // Skip all frames until we have found the first logger frame.
 220                 lookingForLogger = !isLoggerImplFrame(cname);
 221                 return false;
 222             }
 223             // Continue walking until we've found the relevant calling frame.
 224             // Skips logging/logger infrastructure.
 225             return !isFilteredFrame(t);
 226         }
 227 
 228         private boolean isLoggerImplFrame(String cname) {
 229             return (cname.equals("sun.util.logging.PlatformLogger") ||
 230                     cname.equals("jdk.internal.logger.SimpleConsoleLogger"));
 231         }
 232     }
 233 
 234     private String getCallerInfo(String sourceClassName, String sourceMethodName) {
 235         if (sourceClassName == null) return name;
 236         if (sourceMethodName == null) return sourceClassName;
 237         return sourceClassName + " " + sourceMethodName;
 238     }
 239 
 240     private String toString(Throwable thrown) {
 241         String throwable = "";
 242         if (thrown != null) {
 243             StringWriter sw = new StringWriter();
 244             PrintWriter pw = new PrintWriter(sw);
 245             pw.println();
 246             thrown.printStackTrace(pw);
 247             pw.close();
 248             throwable = sw.toString();
 249         }
 250         return throwable;
 251     }
 252 
 253     private synchronized String format(Enum<?> level,
 254             String msg, Throwable thrown, String callerInfo) {
 255 
 256         ZonedDateTime zdt = ZonedDateTime.now();
 257         String throwable = toString(thrown);
 258 
 259         return String.format(Formatting.formatString,
 260                          zdt,
 261                          callerInfo,
 262                          name,
 263                          level.name(),
 264                          msg,
 265                          throwable);
 266     }
 267 
 268     // publish accepts both PlatformLogger Levels and LoggerFinder Levels.
 269     private void publish(String callerInfo, Enum<?> level, String msg) {
 270         outputStream().print(format(level, msg, null, callerInfo));
 271     }
 272     // publish accepts both PlatformLogger Levels and LoggerFinder Levels.
 273     private void publish(String callerInfo, Enum<?> level, String msg, Throwable thrown) {
 274         outputStream().print(format(level, msg, thrown, callerInfo));
 275     }
 276     // publish accepts both PlatformLogger Levels and LoggerFinder Levels.
 277     private void publish(String callerInfo, Enum<?> level, String msg, Object... params) {
 278         msg = params == null || params.length == 0 ? msg
 279                 : Formatting.formatMessage(msg, params);
 280         outputStream().print(format(level, msg, null, callerInfo));
 281     }
 282 
 283     public static SimpleConsoleLogger makeSimpleLogger(String name, boolean usePlatformLevel) {
 284         return new SimpleConsoleLogger(name, usePlatformLevel);
 285     }
 286 
 287     public static SimpleConsoleLogger makeSimpleLogger(String name) {
 288         return new SimpleConsoleLogger(name, false);
 289     }
 290 
 291     public static String getSimpleFormat(Function<String, String> defaultPropertyGetter) {
 292         return Formatting.getSimpleFormat(defaultPropertyGetter);
 293     }
 294 
 295     public static boolean isFilteredFrame(StackFrame st) {
 296         return Formatting.isFilteredFrame(st);
 297     }
 298 
 299     @Override
 300     public void log(PlatformLogger.Level level, Supplier<String> msgSupplier) {
 301         if (isLoggable(level)) {
 302             publish(getCallerInfo(), logLevel(level), msgSupplier.get());
 303         }
 304     }
 305 
 306     @Override
 307     public void log(PlatformLogger.Level level, Throwable thrown,
 308             Supplier<String> msgSupplier) {
 309         if (isLoggable(level)) {
 310             publish(getCallerInfo(), logLevel(level), msgSupplier.get(), thrown);
 311         }
 312     }
 313 
 314     @Override
 315     public void logp(PlatformLogger.Level level, String sourceClass,
 316             String sourceMethod, String msg) {
 317         if (isLoggable(level)) {
 318             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg);
 319         }
 320     }
 321 
 322     @Override
 323     public void logp(PlatformLogger.Level level, String sourceClass,
 324             String sourceMethod, Supplier<String> msgSupplier) {
 325         if (isLoggable(level)) {
 326             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msgSupplier.get());
 327         }
 328     }
 329 
 330     @Override
 331     public void logp(PlatformLogger.Level level, String sourceClass, String sourceMethod,
 332             String msg, Object... params) {
 333         if (isLoggable(level)) {
 334             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg, params);
 335         }
 336     }
 337 
 338     @Override
 339     public void logp(PlatformLogger.Level level, String sourceClass,
 340             String sourceMethod, String msg, Throwable thrown) {
 341         if (isLoggable(level)) {
 342             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg, thrown);
 343         }
 344     }
 345 
 346     @Override
 347     public void logp(PlatformLogger.Level level, String sourceClass,
 348             String sourceMethod, Throwable thrown, Supplier<String> msgSupplier) {
 349         if (isLoggable(level)) {
 350             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msgSupplier.get(), thrown);
 351         }
 352     }
 353 
 354     @Override
 355     public void logrb(PlatformLogger.Level level, String sourceClass,
 356             String sourceMethod, ResourceBundle bundle, String key, Object... params) {
 357         if (isLoggable(level)) {
 358             String msg = bundle == null ? key : bundle.getString(key);
 359             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg, params);
 360         }
 361     }
 362 
 363     @Override
 364     public void logrb(PlatformLogger.Level level, String sourceClass,
 365             String sourceMethod, ResourceBundle bundle, String key, Throwable thrown) {
 366         if (isLoggable(level)) {
 367             String msg = bundle == null ? key : bundle.getString(key);
 368             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg, thrown);
 369         }
 370     }
 371 
 372     @Override
 373     public void logrb(PlatformLogger.Level level, ResourceBundle bundle,
 374             String key, Object... params) {
 375         if (isLoggable(level)) {
 376             String msg = bundle == null ? key : bundle.getString(key);
 377             publish(getCallerInfo(), logLevel(level), msg, params);
 378         }
 379     }
 380 
 381     @Override
 382     public void logrb(PlatformLogger.Level level, ResourceBundle bundle,
 383             String key, Throwable thrown) {
 384         if (isLoggable(level)) {
 385             String msg = bundle == null ? key : bundle.getString(key);
 386             publish(getCallerInfo(), logLevel(level), msg, thrown);
 387         }
 388     }
 389 
 390     private static final class Formatting {
 391         static final String DEFAULT_FORMAT =
 392             "%1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS %1$Tp %2$s%n%4$s: %5$s%6$s%n";
 393         static final String FORMAT_PROP_KEY =


 394             "java.util.logging.SimpleFormatter.format";
 395         static final String formatString = getSimpleFormat(null);
 396 
 397         // Make it easier to wrap Logger...
 398         static private final String[] skips;
 399         static {
 400             String additionalPkgs = AccessController.doPrivileged(
 401                 (PrivilegedAction<String>)
 402                 () -> System.getProperty("jdk.logger.packages"));
 403             skips = additionalPkgs == null ? new String[0] : additionalPkgs.split(",");
 404 
 405         }
 406 
 407         static boolean isFilteredFrame(StackFrame st) {
 408             // skip logging/logger infrastructure
 409             if (System.Logger.class.isAssignableFrom(st.getDeclaringClass())) {
 410                 return true;
 411             }
 412 
 413             // fast escape path: all the prefixes below start with 's' or 'j' and
 414             // have more than 12 characters.
 415             final String cname = st.getClassName();
 416             char c = cname.length() < 12 ? 0 : cname.charAt(0);
 417             if (c == 's') {
 418                 // skip internal machinery classes
 419                 if (cname.startsWith("sun.util.logging."))   return true;
 420                 if (cname.startsWith("sun.rmi.runtime.Log")) return true;
 421             } else if (c == 'j') {
 422                 // Message delayed at Bootstrap: no need to go further up.
 423                 if (cname.startsWith("jdk.internal.logger.BootstrapLogger$LogEvent")) return false;
 424                 // skip public machinery classes
 425                 if (cname.startsWith("jdk.internal.logger."))          return true;
 426                 if (cname.startsWith("java.util.logging."))            return true;
 427                 if (cname.startsWith("java.lang.invoke.MethodHandle")) return true;
 428                 if (cname.startsWith("java.security.AccessController")) return true;
 429             }
 430 
 431             // check additional prefixes if any are specified.
 432             if (skips.length > 0) {
 433                 for (int i=0; i<skips.length; i++) {
 434                     if (!skips[i].isEmpty() && cname.startsWith(skips[i])) {
 435                         return true;
 436                     }
 437                 }
 438             }
 439 
 440             return false;
 441         }
 442 
 443         static String getSimpleFormat(Function<String, String> defaultPropertyGetter) {
 444             // Using a lambda here causes
 445             //    jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java
 446             // to fail - because that test has a testcase which somehow references
 447             // PlatformLogger and counts the number of generated lambda classes
 448             // So we explicitely use new PrivilegedAction<String> here.
 449             String format =
 450                 AccessController.doPrivileged(new PrivilegedAction<String>() {
 451                 @Override
 452                 public String run() {
 453                     return System.getProperty(FORMAT_PROP_KEY);
 454                 }
 455             });
 456             if (format == null && defaultPropertyGetter != null) {
 457                 format = defaultPropertyGetter.apply(FORMAT_PROP_KEY);
 458             }
 459             if (format != null) {
 460                 try {
 461                     // validate the user-defined format string
 462                     String.format(format, ZonedDateTime.now(), "", "", "", "", "");
 463                 } catch (IllegalArgumentException e) {
 464                     // illegal syntax; fall back to the default format
 465                     format = DEFAULT_FORMAT;
 466                 }
 467             } else {
 468                 format = DEFAULT_FORMAT;
 469             }
 470             return format;
 471         }
 472 
 473 
 474         // Copied from java.util.logging.Formatter.formatMessage
 475         static String formatMessage(String format, Object... parameters) {
 476             // Do the formatting.
 477             try {


   1 /*
   2  * Copyright (c) 2015, 2016, 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 jdk.internal.logger;
  27 
  28 import java.io.PrintStream;
  29 import java.io.PrintWriter;
  30 import java.io.StringWriter;
  31 import java.lang.StackWalker.StackFrame;
  32 import java.security.AccessController;
  33 import java.security.PrivilegedAction;
  34 import java.time.ZonedDateTime;
  35 import java.util.Optional;
  36 import java.util.ResourceBundle;
  37 import java.util.function.Function;
  38 import java.lang.System.Logger;
  39 import java.util.PropertyPermission;
  40 import java.util.function.Predicate;
  41 import java.util.function.Supplier;
  42 import sun.security.action.GetPropertyAction;
  43 import sun.util.logging.PlatformLogger;
  44 import sun.util.logging.PlatformLogger.ConfigurableBridge.LoggerConfiguration;
  45 
  46 /**
  47  * A simple console logger to emulate the behavior of JUL loggers when
  48  * in the default configuration. SimpleConsoleLoggers are also used when
  49  * JUL is not present and no DefaultLoggerFinder is installed.
  50  */
  51 public class SimpleConsoleLogger extends LoggerConfiguration
  52     implements Logger, PlatformLogger.Bridge, PlatformLogger.ConfigurableBridge {
  53 
  54     static final Level DEFAULT_LEVEL = getDefaultLevel();
  55     static final PlatformLogger.Level DEFAULT_PLATFORM_LEVEL =
  56             PlatformLogger.toPlatformLevel(DEFAULT_LEVEL);
  57 
  58     static Level getDefaultLevel() {
  59         String levelName = AccessController.doPrivileged(
  60                 new GetPropertyAction("jdk.system.logger.level", "INFO"));
  61         try {
  62             return Level.valueOf(levelName);
  63         } catch (IllegalArgumentException iae) {
  64             return Level.INFO;
  65         }
  66     }
  67 
  68     final String name;
  69     volatile PlatformLogger.Level  level;
  70     final boolean usePlatformLevel;
  71     SimpleConsoleLogger(String name, boolean usePlatformLevel) {
  72         this.name = name;
  73         this.usePlatformLevel = usePlatformLevel;
  74     }
  75 
  76     String defaultFormatString() {
  77         return Formatting.defaultFormatString;
  78     }
  79 
  80     PlatformLogger.Level defaultLevel() {
  81         return DEFAULT_PLATFORM_LEVEL;
  82     }
  83 
  84     @Override
  85     public final String getName() {
  86         return name;
  87     }
  88 
  89     private Enum<?> logLevel(PlatformLogger.Level level) {
  90         return usePlatformLevel ? level : level.systemLevel();
  91     }
  92 
  93     private Enum<?> logLevel(Level level) {
  94         return usePlatformLevel ? PlatformLogger.toPlatformLevel(level) : level;
  95     }
  96 
  97     // ---------------------------------------------------
  98     //                 From Logger
  99     // ---------------------------------------------------
 100 
 101     @Override
 102     public final boolean isLoggable(Level level) {
 103         return isLoggable(PlatformLogger.toPlatformLevel(level));
 104     }
 105 
 106     @Override
 107     public final void log(Level level, ResourceBundle bundle, String key, Throwable thrown) {
 108         if (isLoggable(level)) {
 109             if (bundle != null) {
 110                 key = bundle.getString(key);
 111             }
 112             publish(getCallerInfo(), logLevel(level), key, thrown);
 113         }
 114     }
 115 
 116     @Override
 117     public final void log(Level level, ResourceBundle bundle, String format, Object... params) {
 118         if (isLoggable(level)) {
 119             if (bundle != null) {
 120                 format = bundle.getString(format);
 121             }
 122             publish(getCallerInfo(), logLevel(level), format, params);
 123         }
 124     }
 125 
 126     // ---------------------------------------------------
 127     //             From PlatformLogger.Bridge
 128     // ---------------------------------------------------
 129 
 130     @Override
 131     public final boolean isLoggable(PlatformLogger.Level level) {
 132         final PlatformLogger.Level effectiveLevel =  effectiveLevel();
 133         return level != PlatformLogger.Level.OFF
 134                 && level.ordinal() >= effectiveLevel.ordinal();
 135     }
 136 
 137     @Override
 138     public final boolean isEnabled() {
 139         return level != PlatformLogger.Level.OFF;
 140     }
 141 
 142     @Override
 143     public final void log(PlatformLogger.Level level, String msg) {
 144         if (isLoggable(level)) {
 145             publish(getCallerInfo(), logLevel(level), msg);
 146         }
 147     }
 148 
 149     @Override
 150     public final void log(PlatformLogger.Level level, String msg, Throwable thrown) {
 151         if (isLoggable(level)) {
 152             publish(getCallerInfo(), logLevel(level), msg, thrown);
 153         }
 154     }
 155 
 156     @Override
 157     public final void log(PlatformLogger.Level level, String msg, Object... params) {
 158         if (isLoggable(level)) {
 159             publish(getCallerInfo(), logLevel(level), msg, params);
 160         }
 161     }
 162 
 163     private PlatformLogger.Level effectiveLevel() {
 164         if (level == null) return defaultLevel();
 165         return level;
 166     }
 167 
 168     @Override
 169     public final PlatformLogger.Level getPlatformLevel() {
 170         return level;
 171     }
 172 
 173     @Override
 174     public final void setPlatformLevel(PlatformLogger.Level newLevel) {
 175         level = newLevel;
 176     }
 177 
 178     @Override
 179     public final LoggerConfiguration getLoggerConfiguration() {
 180         return this;
 181     }
 182 
 183     /**
 184      * Default platform logging support - output messages to System.err -
 185      * equivalent to ConsoleHandler with SimpleFormatter.
 186      */
 187     static PrintStream outputStream() {
 188         return System.err;
 189     }
 190 
 191     // Returns the caller's class and method's name; best effort
 192     // if cannot infer, return the logger's name.
 193     private String getCallerInfo() {
 194         Optional<StackWalker.StackFrame> frame = new CallerFinder().get();
 195         if (frame.isPresent()) {
 196             return frame.get().getClassName() + " " + frame.get().getMethodName();
 197         } else {
 198             return name;
 199         }


 227          * Returns true if we have found the caller's frame, false if the frame
 228          * must be skipped.
 229          *
 230          * @param t The frame info.
 231          * @return true if we have found the caller's frame, false if the frame
 232          * must be skipped.
 233          */
 234         @Override
 235         public boolean test(StackWalker.StackFrame t) {
 236             final String cname = t.getClassName();
 237             // We should skip all frames until we have found the logger,
 238             // because these frames could be frames introduced by e.g. custom
 239             // sub classes of Handler.
 240             if (lookingForLogger) {
 241                 // Skip all frames until we have found the first logger frame.
 242                 lookingForLogger = !isLoggerImplFrame(cname);
 243                 return false;
 244             }
 245             // Continue walking until we've found the relevant calling frame.
 246             // Skips logging/logger infrastructure.
 247             return !Formatting.isFilteredFrame(t);
 248         }
 249 
 250         private boolean isLoggerImplFrame(String cname) {
 251             return (cname.equals("sun.util.logging.PlatformLogger") ||
 252                     cname.equals("jdk.internal.logger.SimpleConsoleLogger"));
 253         }
 254     }
 255 
 256     private String getCallerInfo(String sourceClassName, String sourceMethodName) {
 257         if (sourceClassName == null) return name;
 258         if (sourceMethodName == null) return sourceClassName;
 259         return sourceClassName + " " + sourceMethodName;
 260     }
 261 
 262     private String toString(Throwable thrown) {
 263         String throwable = "";
 264         if (thrown != null) {
 265             StringWriter sw = new StringWriter();
 266             PrintWriter pw = new PrintWriter(sw);
 267             pw.println();
 268             thrown.printStackTrace(pw);
 269             pw.close();
 270             throwable = sw.toString();
 271         }
 272         return throwable;
 273     }
 274 
 275     private synchronized String format(Enum<?> level,
 276             String msg, Throwable thrown, String callerInfo) {
 277 
 278         ZonedDateTime zdt = ZonedDateTime.now();
 279         String throwable = toString(thrown);
 280 
 281         return String.format(defaultFormatString(),
 282                          zdt,
 283                          callerInfo,
 284                          name,
 285                          level.name(),
 286                          msg,
 287                          throwable);
 288     }
 289 
 290     // publish accepts both PlatformLogger Levels and LoggerFinder Levels.
 291     private void publish(String callerInfo, Enum<?> level, String msg) {
 292         outputStream().print(format(level, msg, null, callerInfo));
 293     }
 294     // publish accepts both PlatformLogger Levels and LoggerFinder Levels.
 295     private void publish(String callerInfo, Enum<?> level, String msg, Throwable thrown) {
 296         outputStream().print(format(level, msg, thrown, callerInfo));
 297     }
 298     // publish accepts both PlatformLogger Levels and LoggerFinder Levels.
 299     private void publish(String callerInfo, Enum<?> level, String msg, Object... params) {
 300         msg = params == null || params.length == 0 ? msg
 301                 : Formatting.formatMessage(msg, params);
 302         outputStream().print(format(level, msg, null, callerInfo));
 303     }
 304 




 305     public static SimpleConsoleLogger makeSimpleLogger(String name) {
 306         return new SimpleConsoleLogger(name, false);
 307     }
 308 








 309     @Override
 310     public final void log(PlatformLogger.Level level, Supplier<String> msgSupplier) {
 311         if (isLoggable(level)) {
 312             publish(getCallerInfo(), logLevel(level), msgSupplier.get());
 313         }
 314     }
 315 
 316     @Override
 317     public final void log(PlatformLogger.Level level, Throwable thrown,
 318             Supplier<String> msgSupplier) {
 319         if (isLoggable(level)) {
 320             publish(getCallerInfo(), logLevel(level), msgSupplier.get(), thrown);
 321         }
 322     }
 323 
 324     @Override
 325     public final void logp(PlatformLogger.Level level, String sourceClass,
 326             String sourceMethod, String msg) {
 327         if (isLoggable(level)) {
 328             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg);
 329         }
 330     }
 331 
 332     @Override
 333     public final void logp(PlatformLogger.Level level, String sourceClass,
 334             String sourceMethod, Supplier<String> msgSupplier) {
 335         if (isLoggable(level)) {
 336             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msgSupplier.get());
 337         }
 338     }
 339 
 340     @Override
 341     public final void logp(PlatformLogger.Level level, String sourceClass, String sourceMethod,
 342             String msg, Object... params) {
 343         if (isLoggable(level)) {
 344             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg, params);
 345         }
 346     }
 347 
 348     @Override
 349     public final void logp(PlatformLogger.Level level, String sourceClass,
 350             String sourceMethod, String msg, Throwable thrown) {
 351         if (isLoggable(level)) {
 352             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg, thrown);
 353         }
 354     }
 355 
 356     @Override
 357     public final void logp(PlatformLogger.Level level, String sourceClass,
 358             String sourceMethod, Throwable thrown, Supplier<String> msgSupplier) {
 359         if (isLoggable(level)) {
 360             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msgSupplier.get(), thrown);
 361         }
 362     }
 363 
 364     @Override
 365     public final void logrb(PlatformLogger.Level level, String sourceClass,
 366             String sourceMethod, ResourceBundle bundle, String key, Object... params) {
 367         if (isLoggable(level)) {
 368             String msg = bundle == null ? key : bundle.getString(key);
 369             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg, params);
 370         }
 371     }
 372 
 373     @Override
 374     public final void logrb(PlatformLogger.Level level, String sourceClass,
 375             String sourceMethod, ResourceBundle bundle, String key, Throwable thrown) {
 376         if (isLoggable(level)) {
 377             String msg = bundle == null ? key : bundle.getString(key);
 378             publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg, thrown);
 379         }
 380     }
 381 
 382     @Override
 383     public final void logrb(PlatformLogger.Level level, ResourceBundle bundle,
 384             String key, Object... params) {
 385         if (isLoggable(level)) {
 386             String msg = bundle == null ? key : bundle.getString(key);
 387             publish(getCallerInfo(), logLevel(level), msg, params);
 388         }
 389     }
 390 
 391     @Override
 392     public final void logrb(PlatformLogger.Level level, ResourceBundle bundle,
 393             String key, Throwable thrown) {
 394         if (isLoggable(level)) {
 395             String msg = bundle == null ? key : bundle.getString(key);
 396             publish(getCallerInfo(), logLevel(level), msg, thrown);
 397         }
 398     }
 399 
 400     static final class Formatting {
 401         static final String DEFAULT_FORMAT =
 402             "%1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS %1$Tp %2$s%n%4$s: %5$s%6$s%n";
 403         static final String DEFAULT_FORMAT_PROP_KEY =
 404             "jdk.system.logger.format";
 405         static final String JUL_FORMAT_PROP_KEY =
 406             "java.util.logging.SimpleFormatter.format";
 407         static final String defaultFormatString = getSimpleFormat(DEFAULT_FORMAT_PROP_KEY, null);
 408 
 409         // Make it easier to wrap Logger...
 410         static private final String[] skips;
 411         static {
 412             String additionalPkgs = AccessController.doPrivileged(
 413                 new GetPropertyAction("jdk.logger.packages"));

 414             skips = additionalPkgs == null ? new String[0] : additionalPkgs.split(",");
 415 
 416         }
 417 
 418         static boolean isFilteredFrame(StackFrame st) {
 419             // skip logging/logger infrastructure
 420             if (System.Logger.class.isAssignableFrom(st.getDeclaringClass())) {
 421                 return true;
 422             }
 423 
 424             // fast escape path: all the prefixes below start with 's' or 'j' and
 425             // have more than 12 characters.
 426             final String cname = st.getClassName();
 427             char c = cname.length() < 12 ? 0 : cname.charAt(0);
 428             if (c == 's') {
 429                 // skip internal machinery classes
 430                 if (cname.startsWith("sun.util.logging."))   return true;
 431                 if (cname.startsWith("sun.rmi.runtime.Log")) return true;
 432             } else if (c == 'j') {
 433                 // Message delayed at Bootstrap: no need to go further up.
 434                 if (cname.startsWith("jdk.internal.logger.BootstrapLogger$LogEvent")) return false;
 435                 // skip public machinery classes
 436                 if (cname.startsWith("jdk.internal.logger."))          return true;
 437                 if (cname.startsWith("java.util.logging."))            return true;
 438                 if (cname.startsWith("java.lang.invoke.MethodHandle")) return true;
 439                 if (cname.startsWith("java.security.AccessController")) return true;
 440             }
 441 
 442             // check additional prefixes if any are specified.
 443             if (skips.length > 0) {
 444                 for (int i=0; i<skips.length; i++) {
 445                     if (!skips[i].isEmpty() && cname.startsWith(skips[i])) {
 446                         return true;
 447                     }
 448                 }
 449             }
 450 
 451             return false;
 452         }
 453 
 454         static String getSimpleFormat(String key, Function<String, String> defaultPropertyGetter) {
 455             // Using a lambda here causes
 456             //    jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java
 457             // to fail - because that test has a testcase which somehow references
 458             // PlatformLogger and counts the number of generated lambda classes
 459             // So we explicitely use new PrivilegedAction<String> here.
 460             String format = AccessController.doPrivileged(
 461                     new GetPropertyAction(key), null,
 462                     new PropertyPermission(DEFAULT_FORMAT_PROP_KEY, "read"),
 463                     new PropertyPermission(JUL_FORMAT_PROP_KEY, "read"));



 464             if (format == null && defaultPropertyGetter != null) {
 465                 format = defaultPropertyGetter.apply(key);
 466             }
 467             if (format != null) {
 468                 try {
 469                     // validate the user-defined format string
 470                     String.format(format, ZonedDateTime.now(), "", "", "", "", "");
 471                 } catch (IllegalArgumentException e) {
 472                     // illegal syntax; fall back to the default format
 473                     format = DEFAULT_FORMAT;
 474                 }
 475             } else {
 476                 format = DEFAULT_FORMAT;
 477             }
 478             return format;
 479         }
 480 
 481 
 482         // Copied from java.util.logging.Formatter.formatMessage
 483         static String formatMessage(String format, Object... parameters) {
 484             // Do the formatting.
 485             try {


< prev index next >