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.io.PrintStream; 31 import java.io.PrintWriter; 32 import java.io.StringWriter; 33 import java.security.AccessController; 34 import java.security.PrivilegedAction; 35 import java.time.Clock; 36 import java.time.Instant; 37 import java.time.ZoneId; 38 import java.time.ZonedDateTime; 39 import java.util.Arrays; 40 import java.util.HashMap; 41 import java.util.Map; 42 import jdk.internal.misc.JavaLangAccess; 43 import jdk.internal.misc.SharedSecrets; 44 45 /** 46 * Platform logger provides an API for the JRE components to log 47 * messages. This enables the runtime components to eliminate the 48 * static dependency of the logging facility and also defers the 49 * java.util.logging initialization until it is enabled. 50 * In addition, the PlatformLogger API can be used if the logging 51 * module does not exist. 52 * 53 * If the logging facility is not enabled, the platform loggers 54 * will output log messages per the default logging configuration 55 * (see below). In this implementation, it does not log the 56 * the stack frame information issuing the log message. 57 * 58 * When the logging facility is enabled (at startup or runtime), 59 * the java.util.logging.Logger will be created for each platform 60 * logger and all log messages will be forwarded to the Logger 61 * to handle. 62 * 63 * Logging facility is "enabled" when one of the following 522 ZonedDateTime zdt = ZonedDateTime.now(zoneId); 523 String throwable = ""; 524 if (thrown != null) { 525 StringWriter sw = new StringWriter(); 526 PrintWriter pw = new PrintWriter(sw); 527 pw.println(); 528 thrown.printStackTrace(pw); 529 pw.close(); 530 throwable = sw.toString(); 531 } 532 533 return String.format(formatString, 534 zdt, 535 getCallerInfo(), 536 name, 537 level.name(), 538 msg, 539 throwable); 540 } 541 542 // Returns the caller's class and method's name; best effort 543 // if cannot infer, return the logger's name. 544 private String getCallerInfo() { 545 String sourceClassName = null; 546 String sourceMethodName = null; 547 548 JavaLangAccess access = SharedSecrets.getJavaLangAccess(); 549 Throwable throwable = new Throwable(); 550 int depth = access.getStackTraceDepth(throwable); 551 552 String logClassName = "sun.util.logging.PlatformLogger"; 553 boolean lookingForLogger = true; 554 for (int ix = 0; ix < depth; ix++) { 555 // Calling getStackTraceElement directly prevents the VM 556 // from paying the cost of building the entire stack frame. 557 StackTraceElement frame = 558 access.getStackTraceElement(throwable, ix); 559 String cname = frame.getClassName(); 560 if (lookingForLogger) { 561 // Skip all frames until we have found the first logger frame. 562 if (cname.equals(logClassName)) { 563 lookingForLogger = false; 564 } 565 } else { 566 if (!cname.equals(logClassName)) { 567 // We've found the relevant frame. 568 sourceClassName = cname; 569 sourceMethodName = frame.getMethodName(); 570 break; 571 } 572 } 573 } 574 575 if (sourceClassName != null) { 576 return sourceClassName + " " + sourceMethodName; 577 } else { 578 return name; 579 } 580 } 581 } 582 583 /** 584 * JavaLoggerProxy forwards all the calls to its corresponding 585 * java.util.logging.Logger object. 586 */ 587 private static final class JavaLoggerProxy extends LoggerProxy { 588 // initialize javaLevel fields for mapping from Level enum -> j.u.l.Level object 589 static { 590 for (Level level : Level.values()) { 591 level.javaLevel = LoggingSupport.parseLevel(level.name()); 592 } 593 } 594 595 private final /* java.util.logging.Logger */ Object javaLogger; 596 597 JavaLoggerProxy(String name) { 598 this(name, null); 599 } | 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.io.PrintStream; 31 import java.io.PrintWriter; 32 import java.io.StringWriter; 33 import java.security.AccessController; 34 import java.security.PrivilegedAction; 35 import java.time.ZoneId; 36 import java.time.ZonedDateTime; 37 import java.util.Arrays; 38 import java.util.HashMap; 39 import java.util.Map; 40 import java.util.Optional; 41 import java.util.function.Predicate; 42 43 /** 44 * Platform logger provides an API for the JRE components to log 45 * messages. This enables the runtime components to eliminate the 46 * static dependency of the logging facility and also defers the 47 * java.util.logging initialization until it is enabled. 48 * In addition, the PlatformLogger API can be used if the logging 49 * module does not exist. 50 * 51 * If the logging facility is not enabled, the platform loggers 52 * will output log messages per the default logging configuration 53 * (see below). In this implementation, it does not log the 54 * the stack frame information issuing the log message. 55 * 56 * When the logging facility is enabled (at startup or runtime), 57 * the java.util.logging.Logger will be created for each platform 58 * logger and all log messages will be forwarded to the Logger 59 * to handle. 60 * 61 * Logging facility is "enabled" when one of the following 520 ZonedDateTime zdt = ZonedDateTime.now(zoneId); 521 String throwable = ""; 522 if (thrown != null) { 523 StringWriter sw = new StringWriter(); 524 PrintWriter pw = new PrintWriter(sw); 525 pw.println(); 526 thrown.printStackTrace(pw); 527 pw.close(); 528 throwable = sw.toString(); 529 } 530 531 return String.format(formatString, 532 zdt, 533 getCallerInfo(), 534 name, 535 level.name(), 536 msg, 537 throwable); 538 } 539 540 /* 541 * CallerFinder is a stateful predicate. 542 */ 543 static final class CallerFinder implements Predicate<StackWalker.StackFrame> { 544 static final StackWalker WALKER = StackWalker.getInstance(); 545 546 /** 547 * Returns StackFrame of the caller's frame. 548 * @return StackFrame of the caller's frame. 549 */ 550 Optional<StackWalker.StackFrame> get() { 551 return WALKER.walk(s -> s.filter(this).findFirst()); 552 } 553 554 private boolean lookingForLogger = true; 555 556 /** 557 * Returns true if we have found the caller's frame, false if the frame 558 * must be skipped. 559 * 560 * @param t The frame info. 561 * @return true if we have found the caller's frame, false if the frame 562 * must be skipped. 563 */ 564 @Override 565 public boolean test(StackWalker.StackFrame t) { 566 final String cname = t.getClassName(); 567 // We should skip all frames until we have found the logger, 568 // because these frames could be frames introduced by e.g. custom 569 // sub classes of Handler. 570 if (lookingForLogger) { 571 lookingForLogger = !cname.equals("sun.util.logging.PlatformLogger"); 572 return false; 573 } 574 // Once the logger is found - we should skip all frames that 575 // point to packages which contain artifacts that could be 576 // inserted between the logger and its caller. These could be 577 // logger wrappers from j.u.l or sun.util.logging (e.g. the 578 // PlatformLogger or artifacts between the PlatformLogger and 579 // the actual logger) or frames inserted by use of reflection 580 // and/or doPrivileged calls. 581 return !cname.startsWith("java.util.logging.") 582 && !cname.startsWith("sun.util.logging.") 583 && !cname.startsWith("java.security.AccessController"); 584 } 585 } 586 587 private String getCallerInfo() { 588 Optional<StackWalker.StackFrame> frame = new CallerFinder().get(); 589 return frame.map(f -> f.getClassName() + " " + f.getMethodName()).orElse(name); 590 } 591 } 592 593 /** 594 * JavaLoggerProxy forwards all the calls to its corresponding 595 * java.util.logging.Logger object. 596 */ 597 private static final class JavaLoggerProxy extends LoggerProxy { 598 // initialize javaLevel fields for mapping from Level enum -> j.u.l.Level object 599 static { 600 for (Level level : Level.values()) { 601 level.javaLevel = LoggingSupport.parseLevel(level.name()); 602 } 603 } 604 605 private final /* java.util.logging.Logger */ Object javaLogger; 606 607 JavaLoggerProxy(String name) { 608 this(name, null); 609 } |