PlatformLogger.java revision 51b1b6997fd3f980076b8081f7f1165ccc2a4008
151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.util.logging;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.lang.ref.WeakReference;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.PrintStream;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.PrintWriter;
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.StringWriter;
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.AccessController;
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.PrivilegedAction;
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Arrays;
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Date;
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.HashMap;
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Map;
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.misc.JavaLangAccess;
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.misc.SharedSecrets;
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Platform logger provides an API for the JRE components to log
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * messages.  This enables the runtime components to eliminate the
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * static dependency of the logging facility and also defers the
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * java.util.logging initialization until it is enabled.
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * In addition, the PlatformLogger API can be used if the logging
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * module does not exist.
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If the logging facility is not enabled, the platform loggers
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * will output log messages per the default logging configuration
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (see below). In this implementation, it does not log the
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the stack frame information issuing the log message.
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * When the logging facility is enabled (at startup or runtime),
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the java.util.logging.Logger will be created for each platform
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * logger and all log messages will be forwarded to the Logger
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to handle.
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Logging facility is "enabled" when one of the following
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * conditions is met:
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1) a system property "java.util.logging.config.class" or
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *    "java.util.logging.config.file" is set
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2) java.util.logging.LogManager or java.util.logging.Logger
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *    is referenced that will trigger the logging initialization.
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Default logging configuration:
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   global logging level = INFO
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   handlers = java.util.logging.ConsoleHandler
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   java.util.logging.ConsoleHandler.level = INFO
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Limitation:
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <JAVA_HOME>/lib/logging.properties is the system-wide logging
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * configuration defined in the specification and read in the
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * default case to configure any java.util.logging.Logger instances.
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Platform loggers will not detect if <JAVA_HOME>/lib/logging.properties
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is modified. In other words, unless the java.util.logging API
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is used at runtime or the logging system properties is set,
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the platform loggers will use the default setting described above.
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The platform loggers are designed for JDK developers use and
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this limitation can be workaround with setting
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * -Djava.util.logging.config.file system property.
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.7
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class PlatformLogger {
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * These constants should be shortcuts to Level enum constants that
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the clients of sun.util.logging.PlatformLogger require no source
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * modification and avoid the conversion from int to Level enum.
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This can be done when JavaFX is converted to use the new PlatformLogger.Level API.
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int OFF     = Integer.MAX_VALUE;
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int SEVERE  = 1000;
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int WARNING = 900;
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int INFO    = 800;
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int CONFIG  = 700;
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int FINE    = 500;
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int FINER   = 400;
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int FINEST  = 300;
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int ALL     = Integer.MIN_VALUE;
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * PlatformLogger logging levels.
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static enum Level {
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // The name and value must match that of {@code java.util.logging.Level}s.
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Declare in ascending order of the given value for binary search.
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ALL,
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        FINEST,
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        FINER,
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        FINE,
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CONFIG,
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        INFO,
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        WARNING,
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        SEVERE,
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        OFF;
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Associated java.util.logging.Level lazily initialized in
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * JavaLoggerProxy's static initializer only once
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * when java.util.logging is available and enabled.
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Only accessed by JavaLoggerProxy.
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* java.util.logging.Level */ Object javaLevel;
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // ascending order for binary search matching the list of enum constants
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static final int[] levelValues = new int[] {
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            PlatformLogger.ALL, PlatformLogger.FINEST, PlatformLogger.FINER,
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            PlatformLogger.FINE, PlatformLogger.CONFIG, PlatformLogger.INFO,
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            PlatformLogger.WARNING, PlatformLogger.SEVERE, PlatformLogger.OFF
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        };
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int intValue() {
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return levelValues[this.ordinal()];
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        static Level valueOf(int level) {
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            switch (level) {
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // ordering per the highest occurences in the jdk source
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // finest, fine, finer, info first
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case PlatformLogger.FINEST  : return Level.FINEST;
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case PlatformLogger.FINE    : return Level.FINE;
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case PlatformLogger.FINER   : return Level.FINER;
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case PlatformLogger.INFO    : return Level.INFO;
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case PlatformLogger.WARNING : return Level.WARNING;
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case PlatformLogger.CONFIG  : return Level.CONFIG;
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case PlatformLogger.SEVERE  : return Level.SEVERE;
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case PlatformLogger.OFF     : return Level.OFF;
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case PlatformLogger.ALL     : return Level.ALL;
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // return the nearest Level value >= the given level,
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // for level > SEVERE, return SEVERE and exclude OFF
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int i = Arrays.binarySearch(levelValues, 0, levelValues.length-2, level);
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return values()[i >= 0 ? i : (-i-1)];
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final Level DEFAULT_LEVEL = Level.INFO;
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static boolean loggingEnabled;
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static {
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggingEnabled = AccessController.doPrivileged(
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            new PrivilegedAction<Boolean>() {
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                public Boolean run() {
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String cname = System.getProperty("java.util.logging.config.class");
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String fname = System.getProperty("java.util.logging.config.file");
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return (cname != null || fname != null);
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            });
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // force loading of all JavaLoggerProxy (sub)classes to make JIT de-optimizations
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // less probable.  Don't initialize JavaLoggerProxy class since
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // java.util.logging may not be enabled.
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Class.forName("sun.util.logging.PlatformLogger$DefaultLoggerProxy",
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          false,
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          PlatformLogger.class.getClassLoader());
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Class.forName("sun.util.logging.PlatformLogger$JavaLoggerProxy",
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          false,   // do not invoke class initializer
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          PlatformLogger.class.getClassLoader());
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (ClassNotFoundException ex) {
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InternalError(ex.getMessage());
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Table of known loggers.  Maps names to PlatformLoggers.
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static Map<String,WeakReference<PlatformLogger>> loggers =
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        new HashMap<>();
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a PlatformLogger of a given name.
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static synchronized PlatformLogger getLogger(String name) {
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        PlatformLogger log = null;
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        WeakReference<PlatformLogger> ref = loggers.get(name);
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (ref != null) {
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            log = ref.get();
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (log == null) {
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            log = new PlatformLogger(name);
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            loggers.put(name, new WeakReference<>(log));
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return log;
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Initialize java.util.logging.Logger objects for all platform loggers.
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method is called from LogManager.readPrimordialConfiguration().
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static synchronized void redirectPlatformLoggers() {
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (loggingEnabled || !LoggingSupport.isAvailable()) return;
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggingEnabled = true;
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (Map.Entry<String, WeakReference<PlatformLogger>> entry : loggers.entrySet()) {
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            WeakReference<PlatformLogger> ref = entry.getValue();
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            PlatformLogger plog = ref.get();
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (plog != null) {
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                plog.redirectToJavaLoggerProxy();
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a new JavaLoggerProxy and redirects the platform logger to it
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void redirectToJavaLoggerProxy() {
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DefaultLoggerProxy lp = DefaultLoggerProxy.class.cast(this.loggerProxy);
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JavaLoggerProxy jlp = new JavaLoggerProxy(lp.name, lp.level);
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // the order of assignments is important
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.javaLoggerProxy = jlp;   // isLoggable checks javaLoggerProxy if set
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.loggerProxy = jlp;
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // DefaultLoggerProxy may be replaced with a JavaLoggerProxy object
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // when the java.util.logging facility is enabled
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private volatile LoggerProxy loggerProxy;
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // javaLoggerProxy is only set when the java.util.logging facility is enabled
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private volatile JavaLoggerProxy javaLoggerProxy;
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private PlatformLogger(String name) {
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (loggingEnabled) {
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.loggerProxy = this.javaLoggerProxy = new JavaLoggerProxy(name);
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.loggerProxy = new DefaultLoggerProxy(name);
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * A convenience method to test if the logger is turned off.
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * (i.e. its level is OFF).
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean isEnabled() {
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return loggerProxy.isEnabled();
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the name for this platform logger.
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getName() {
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return loggerProxy.name;
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns true if a message of the given level would actually
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * be logged by this logger.
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @deprecated Use isLoggable(Level) instead.
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Deprecated
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean isLoggable(int levelValue) {
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return isLoggable(Level.valueOf(levelValue));
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the current log level. Returns 0 if the current effective level is
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * not set (equivalent to Logger.getLevel() returns null).
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @deprecated Use level() instead
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Deprecated
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int getLevel() {
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Level level = loggerProxy.getLevel();
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return level != null ? level.intValue() : 0;
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Sets the log level.
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @deprecated Use setLevel(Level) instead
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Deprecated
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void setLevel(int newLevel) {
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.setLevel(newLevel == 0 ? null : Level.valueOf(newLevel));
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns true if a message of the given level would actually
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * be logged by this logger.
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean isLoggable(Level level) {
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (level == null) {
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // performance-sensitive method: use two monomorphic call-sites
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JavaLoggerProxy jlp = javaLoggerProxy;
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return jlp != null ? jlp.isLoggable(level) : loggerProxy.isLoggable(level);
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get the log level that has been specified for this PlatformLogger.
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The result may be null, which means that this logger's
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * effective level will be inherited from its parent.
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  this PlatformLogger's level
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Level level() {
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return loggerProxy.getLevel();
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Set the log level specifying which message levels will be
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * logged by this logger.  Message levels lower than this
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * value will be discarded.  The level value {@link #OFF}
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * can be used to turn off logging.
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If the new level is null, it means that this node should
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * inherit its level from its nearest ancestor with a specific
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * (non-null) level value.
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param newLevel the new value for the log level (may be null)
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void setLevel(Level newLevel) {
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.setLevel(newLevel);
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Logs a SEVERE message.
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void severe(String msg) {
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.SEVERE, msg);
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void severe(String msg, Throwable t) {
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.SEVERE, msg, t);
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void severe(String msg, Object... params) {
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.SEVERE, msg, params);
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Logs a WARNING message.
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void warning(String msg) {
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.WARNING, msg);
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void warning(String msg, Throwable t) {
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.WARNING, msg, t);
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void warning(String msg, Object... params) {
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.WARNING, msg, params);
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Logs an INFO message.
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void info(String msg) {
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.INFO, msg);
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void info(String msg, Throwable t) {
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.INFO, msg, t);
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void info(String msg, Object... params) {
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.INFO, msg, params);
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Logs a CONFIG message.
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void config(String msg) {
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.CONFIG, msg);
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void config(String msg, Throwable t) {
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.CONFIG, msg, t);
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void config(String msg, Object... params) {
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.CONFIG, msg, params);
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Logs a FINE message.
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void fine(String msg) {
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.FINE, msg);
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void fine(String msg, Throwable t) {
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.FINE, msg, t);
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void fine(String msg, Object... params) {
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.FINE, msg, params);
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Logs a FINER message.
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void finer(String msg) {
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.FINER, msg);
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void finer(String msg, Throwable t) {
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.FINER, msg, t);
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void finer(String msg, Object... params) {
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.FINER, msg, params);
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Logs a FINEST message.
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void finest(String msg) {
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.FINEST, msg);
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void finest(String msg, Throwable t) {
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.FINEST, msg, t);
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void finest(String msg, Object... params) {
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loggerProxy.doLog(Level.FINEST, msg, params);
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Abstract base class for logging support, defining the API and common field.
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static abstract class LoggerProxy {
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final String name;
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        protected LoggerProxy(String name) {
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.name = name;
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        abstract boolean isEnabled();
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        abstract Level getLevel();
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        abstract void setLevel(Level newLevel);
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        abstract void doLog(Level level, String msg);
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        abstract void doLog(Level level, String msg, Throwable thrown);
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        abstract void doLog(Level level, String msg, Object... params);
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        abstract boolean isLoggable(Level level);
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final class DefaultLoggerProxy extends LoggerProxy {
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Default platform logging support - output messages to System.err -
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * equivalent to ConsoleHandler with SimpleFormatter.
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static PrintStream outputStream() {
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return System.err;
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        volatile Level effectiveLevel; // effective level (never null)
47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        volatile Level level;          // current level set for this node (may be null)
47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DefaultLoggerProxy(String name) {
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            super(name);
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.effectiveLevel = deriveEffectiveLevel(null);
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.level = null;
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean isEnabled() {
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return effectiveLevel != Level.OFF;
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Level getLevel() {
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return level;
48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void setLevel(Level newLevel) {
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Level oldLevel = level;
49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (oldLevel != newLevel) {
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                level = newLevel;
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                effectiveLevel = deriveEffectiveLevel(newLevel);
49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void doLog(Level level, String msg) {
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (isLoggable(level)) {
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                outputStream().print(format(level, msg, null));
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void doLog(Level level, String msg, Throwable thrown) {
50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (isLoggable(level)) {
50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                outputStream().print(format(level, msg, thrown));
50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void doLog(Level level, String msg, Object... params) {
51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (isLoggable(level)) {
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String newMsg = formatMessage(msg, params);
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                outputStream().print(format(level, newMsg, null));
51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean isLoggable(Level level) {
51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Level effectiveLevel = this.effectiveLevel;
52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return level.intValue() >= effectiveLevel.intValue() && effectiveLevel != Level.OFF;
52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // derive effective level (could do inheritance search like j.u.l.Logger)
52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private Level deriveEffectiveLevel(Level level) {
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return level == null ? DEFAULT_LEVEL : level;
52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Copied from java.util.logging.Formatter.formatMessage
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private String formatMessage(String format, Object... parameters) {
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Do the formatting.
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (parameters == null || parameters.length == 0) {
53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // No parameters.  Just return format string.
53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return format;
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Is it a java.text style format?
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Ideally we could match with
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Pattern.compile("\\{\\d").matcher(format).find())
53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // However the cost is 14% higher, so we cheaply check for
54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // 1 of the first 4 parameters
54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (format.indexOf("{0") >= 0 || format.indexOf("{1") >=0 ||
54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            format.indexOf("{2") >=0|| format.indexOf("{3") >=0) {
54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return java.text.MessageFormat.format(format, parameters);
54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return format;
54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (Exception ex) {
54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Formatting failed: use format string.
54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return format;
54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static final String formatString =
55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            LoggingSupport.getSimpleFormat(false); // don't check logging.properties
55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // minimize memory allocation
55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private Date date = new Date();
55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private synchronized String format(Level level, String msg, Throwable thrown) {
55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            date.setTime(System.currentTimeMillis());
55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String throwable = "";
56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (thrown != null) {
56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                StringWriter sw = new StringWriter();
56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                PrintWriter pw = new PrintWriter(sw);
56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pw.println();
56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                thrown.printStackTrace(pw);
56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pw.close();
56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throwable = sw.toString();
56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return String.format(formatString,
57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                 date,
57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                 getCallerInfo(),
57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                 name,
57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                 level.name(),
57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                 msg,
57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                 throwable);
57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Returns the caller's class and method's name; best effort
57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // if cannot infer, return the logger's name.
58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private String getCallerInfo() {
58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String sourceClassName = null;
58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String sourceMethodName = null;
58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            JavaLangAccess access = SharedSecrets.getJavaLangAccess();
58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Throwable throwable = new Throwable();
58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int depth = access.getStackTraceDepth(throwable);
58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String logClassName = "sun.util.logging.PlatformLogger";
58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            boolean lookingForLogger = true;
59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int ix = 0; ix < depth; ix++) {
59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Calling getStackTraceElement directly prevents the VM
59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // from paying the cost of building the entire stack frame.
59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                StackTraceElement frame =
59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    access.getStackTraceElement(throwable, ix);
59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String cname = frame.getClassName();
59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (lookingForLogger) {
59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // Skip all frames until we have found the first logger frame.
59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (cname.equals(logClassName)) {
59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        lookingForLogger = false;
60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (!cname.equals(logClassName)) {
60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // We've found the relevant frame.
60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        sourceClassName = cname;
60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        sourceMethodName = frame.getMethodName();
60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break;
60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (sourceClassName != null) {
61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return sourceClassName + " " + sourceMethodName;
61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return name;
61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * JavaLoggerProxy forwards all the calls to its corresponding
62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * java.util.logging.Logger object.
62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final class JavaLoggerProxy extends LoggerProxy {
62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // initialize javaLevel fields for mapping from Level enum -> j.u.l.Level object
62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        static {
62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (Level level : Level.values()) {
62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                level.javaLevel = LoggingSupport.parseLevel(level.name());
62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private final /* java.util.logging.Logger */ Object javaLogger;
63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JavaLoggerProxy(String name) {
63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this(name, null);
63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JavaLoggerProxy(String name, Level level) {
63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            super(name);
63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.javaLogger = LoggingSupport.getLogger(name);
64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (level != null) {
64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // level has been updated and so set the Logger's level
64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                LoggingSupport.setLevel(javaLogger, level.javaLevel);
64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void doLog(Level level, String msg) {
64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            LoggingSupport.log(javaLogger, level.javaLevel, msg);
64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void doLog(Level level, String msg, Throwable t) {
65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            LoggingSupport.log(javaLogger, level.javaLevel, msg, t);
65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void doLog(Level level, String msg, Object... params) {
65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!isLoggable(level)) {
65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return;
65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // only pass String objects to the j.u.l.Logger which may
65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // be created by untrusted code
66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int len = (params != null) ? params.length : 0;
66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Object[] sparams = new String[len];
66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = 0; i < len; i++) {
66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                sparams [i] = String.valueOf(params[i]);
66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            LoggingSupport.log(javaLogger, level.javaLevel, msg, sparams);
66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean isEnabled() {
66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return LoggingSupport.isLoggable(javaLogger, Level.OFF.javaLevel);
67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Returns the PlatformLogger.Level mapped from j.u.l.Level
67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * set in the logger.  If the j.u.l.Logger is set to a custom Level,
67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * this method will return the nearest Level.
67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Level getLevel() {
67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Object javaLevel = LoggingSupport.getLevel(javaLogger);
67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (javaLevel == null) return null;
68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return Level.valueOf(LoggingSupport.getLevelName(javaLevel));
68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (IllegalArgumentException e) {
68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return Level.valueOf(LoggingSupport.getLevelValue(javaLevel));
68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void setLevel(Level level) {
68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            LoggingSupport.setLevel(javaLogger, level == null ? null : level.javaLevel);
69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean isLoggable(Level level) {
69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return LoggingSupport.isLoggable(javaLogger, level.javaLevel);
69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
697