/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.nashorn.internal.runtime.logging;

import java.io.PrintWriter;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.LoggingPermission;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.events.RuntimeEvent;

Wrapper class for Logging system. This is how you are supposed to register a logger and use it
/** * Wrapper class for Logging system. This is how you are supposed to register a logger and use it */
public final class DebugLogger {
Disabled logger used for all loggers that need an instance, but shouldn't output anything
/** Disabled logger used for all loggers that need an instance, but shouldn't output anything */
public static final DebugLogger DISABLED_LOGGER = new DebugLogger("disabled", Level.OFF, false); private final Logger logger; private final boolean isEnabled; private int indent; private static final int INDENT_SPACE = 4;
A quiet logger only logs RuntimeEvents and does't output any text, regardless of level
/** A quiet logger only logs {@link RuntimeEvent}s and does't output any text, regardless of level */
private final boolean isQuiet;
Constructor A logger can be paired with a property, e.g. --log:codegen:info is equivalent to -Dnashorn.codegen.log
Params:
  • loggerName – name of logger - this is the unique key with which it can be identified
  • loggerLevel – level of the logger
  • isQuiet – is this a quiet logger, i.e. enabled for things like e.g. RuntimeEvent:s, but quiet otherwise
/** * Constructor * * A logger can be paired with a property, e.g. {@code --log:codegen:info} is equivalent to {@code -Dnashorn.codegen.log} * * @param loggerName name of logger - this is the unique key with which it can be identified * @param loggerLevel level of the logger * @param isQuiet is this a quiet logger, i.e. enabled for things like e.g. RuntimeEvent:s, but quiet otherwise */
public DebugLogger(final String loggerName, final Level loggerLevel, final boolean isQuiet) { this.logger = instantiateLogger(loggerName, loggerLevel); this.isQuiet = isQuiet; assert logger != null; this.isEnabled = getLevel() != Level.OFF; } private static Logger instantiateLogger(final String name, final Level level) { final Logger logger = java.util.logging.Logger.getLogger(name); AccessController.doPrivileged(new PrivilegedAction<Void>() { @Override public Void run() { for (final Handler h : logger.getHandlers()) { logger.removeHandler(h); } logger.setLevel(level); logger.setUseParentHandlers(false); final Handler c = new ConsoleHandler(); c.setFormatter(new Formatter() { @Override public String format(final LogRecord record) { final StringBuilder sb = new StringBuilder(); sb.append('[') .append(record.getLoggerName()) .append("] ") .append(record.getMessage()) .append('\n'); return sb.toString(); } }); logger.addHandler(c); c.setLevel(level); return null; } }, createLoggerControlAccCtxt()); return logger; }
Do not currently support chaining this with parent logger. Logger level null means disabled
Returns:level
/** * Do not currently support chaining this with parent logger. Logger level null * means disabled * @return level */
public Level getLevel() { return logger.getLevel() == null ? Level.OFF : logger.getLevel(); }
Get the output writer for the logger. Loggers always default to stderr for output as they are used mainly to output debug info Can be inherited so this should not be static.
Returns:print writer for log output.
/** * Get the output writer for the logger. Loggers always default to * stderr for output as they are used mainly to output debug info * * Can be inherited so this should not be static. * * @return print writer for log output. */
@SuppressWarnings("static-method") public PrintWriter getOutputStream() { return Context.getCurrentErr(); }
Add quotes around a string
Params:
  • str – string
Returns:quoted string
/** * Add quotes around a string * @param str string * @return quoted string */
public static String quote(final String str) { if (str.isEmpty()) { return "''"; } char startQuote = '\0'; char endQuote = '\0'; char quote = '\0'; if (str.startsWith("\\") || str.startsWith("\"")) { startQuote = str.charAt(0); } if (str.endsWith("\\") || str.endsWith("\"")) { endQuote = str.charAt(str.length() - 1); } if (startQuote == '\0' || endQuote == '\0') { quote = startQuote == '\0' ? endQuote : startQuote; } if (quote == '\0') { quote = '\''; } return (startQuote == '\0' ? quote : startQuote) + str + (endQuote == '\0' ? quote : endQuote); }
Check if the logger is enabled
Returns:true if enabled
/** * Check if the logger is enabled * @return true if enabled */
public boolean isEnabled() { return isEnabled; }
Check if the logger is enabled
Params:
  • logger – logger to check, null will return false
Returns:true if enabled
/** * Check if the logger is enabled * @param logger logger to check, null will return false * @return true if enabled */
public static boolean isEnabled(final DebugLogger logger) { return logger != null && logger.isEnabled(); }
If you want to change the indent level of your logger, call indent with a new position. Positions start at 0 and are increased by one for a new "tab"
Params:
  • pos – indent position
/** * If you want to change the indent level of your logger, call indent with a new position. * Positions start at 0 and are increased by one for a new "tab" * * @param pos indent position */
public void indent(final int pos) { if (isEnabled) { indent += pos * INDENT_SPACE; } }
Add an indent position
/** * Add an indent position */
public void indent() { indent += INDENT_SPACE; }
Unindent a position
/** * Unindent a position */
public void unindent() { indent -= INDENT_SPACE; if (indent < 0) { indent = 0; } } private static void logEvent(final RuntimeEvent<?> event) { if (event != null) { final Global global = Context.getGlobal(); if (global.has("Debug")) { final ScriptObject debug = (ScriptObject)global.get("Debug"); final ScriptFunction addRuntimeEvent = (ScriptFunction)debug.get("addRuntimeEvent"); ScriptRuntime.apply(addRuntimeEvent, debug, event); } } }
Check if the event of given level will be logged.
Params:
  • level – logging level
See Also:
  • Level
Returns:true if event of given level will be logged.
/** * Check if the event of given level will be logged. * @see java.util.logging.Level * * @param level logging level * @return true if event of given level will be logged. */
public boolean isLoggable(final Level level) { return logger.isLoggable(level); }
Shorthand for outputting a log string as log level Level.FINEST on this logger
Params:
  • str – the string to log
/** * Shorthand for outputting a log string as log level {@link java.util.logging.Level#FINEST} on this logger * @param str the string to log */
public void finest(final String str) { log(Level.FINEST, str); }
Shorthand for outputting a log string as log level Level.FINEST on this logger
Params:
  • event – optional runtime event to log
  • str – the string to log
/** * Shorthand for outputting a log string as log level {@link java.util.logging.Level#FINEST} on this logger * @param event optional runtime event to log * @param str the string to log */
public void finest(final RuntimeEvent<?> event, final String str) { finest(str); logEvent(event); }
Shorthand for outputting a log string as log level Level.FINEST on this logger
Params:
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINEST} on this logger * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void finest(final Object... objs) { log(Level.FINEST, objs); }
Shorthand for outputting a log string as log level Level.FINEST on this logger
Params:
  • event – optional runtime event to log
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINEST} on this logger * @param event optional runtime event to log * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void finest(final RuntimeEvent<?> event, final Object... objs) { finest(objs); logEvent(event); }
Shorthand for outputting a log string as log level Level.FINER on this logger
Params:
  • str – the string to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINER} on this logger * @param str the string to log */
public void finer(final String str) { log(Level.FINER, str); }
Shorthand for outputting a log string as log level Level.FINER on this logger
Params:
  • event – optional runtime event to log
  • str – the string to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINER} on this logger * @param event optional runtime event to log * @param str the string to log */
public void finer(final RuntimeEvent<?> event, final String str) { finer(str); logEvent(event); }
Shorthand for outputting a log string as log level Level.FINER on this logger
Params:
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINER} on this logger * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void finer(final Object... objs) { log(Level.FINER, objs); }
Shorthand for outputting a log string as log level Level.FINER on this logger
Params:
  • event – optional runtime event to log
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINER} on this logger * @param event optional runtime event to log * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void finer(final RuntimeEvent<?> event, final Object... objs) { finer(objs); logEvent(event); }
Shorthand for outputting a log string as log level Level.FINE on this logger
Params:
  • str – the string to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINE} on this logger * @param str the string to log */
public void fine(final String str) { log(Level.FINE, str); }
Shorthand for outputting a log string as log level Level.FINE on this logger
Params:
  • event – optional runtime event to log
  • str – the string to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINE} on this logger * @param event optional runtime event to log * @param str the string to log */
public void fine(final RuntimeEvent<?> event, final String str) { fine(str); logEvent(event); }
Shorthand for outputting a log string as log level Level.FINE on this logger
Params:
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINE} on this logger * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void fine(final Object... objs) { log(Level.FINE, objs); }
Shorthand for outputting a log string as log level Level.FINE on this logger
Params:
  • event – optional runtime event to log
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINE} on this logger * @param event optional runtime event to log * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void fine(final RuntimeEvent<?> event, final Object... objs) { fine(objs); logEvent(event); }
Shorthand for outputting a log string as log level Level.CONFIG on this logger
Params:
  • str – the string to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#CONFIG} on this logger * @param str the string to log */
public void config(final String str) { log(Level.CONFIG, str); }
Shorthand for outputting a log string as log level Level.CONFIG on this logger
Params:
  • event – optional runtime event to log
  • str – the string to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#CONFIG} on this logger * @param event optional runtime event to log * @param str the string to log */
public void config(final RuntimeEvent<?> event, final String str) { config(str); logEvent(event); }
Shorthand for outputting a log string as log level Level.CONFIG on this logger
Params:
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#CONFIG} on this logger * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void config(final Object... objs) { log(Level.CONFIG, objs); }
Shorthand for outputting a log string as log level Level.CONFIG on this logger
Params:
  • event – optional runtime event to log
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#CONFIG} on this logger * @param event optional runtime event to log * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void config(final RuntimeEvent<?> event, final Object... objs) { config(objs); logEvent(event); }
Shorthand for outputting a log string as log level Level.INFO on this logger
Params:
  • str – the string to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#INFO} on this logger * @param str the string to log */
public void info(final String str) { log(Level.INFO, str); }
Shorthand for outputting a log string as log level Level.INFO on this logger
Params:
  • event – optional runtime event to log
  • str – the string to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#INFO} on this logger * @param event optional runtime event to log * @param str the string to log */
public void info(final RuntimeEvent<?> event, final String str) { info(str); logEvent(event); }
Shorthand for outputting a log string as log level Level.FINE on this logger
Params:
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINE} on this logger * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void info(final Object... objs) { log(Level.INFO, objs); }
Shorthand for outputting a log string as log level Level.FINE on this logger
Params:
  • event – optional runtime event to log
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINE} on this logger * @param event optional runtime event to log * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void info(final RuntimeEvent<?> event, final Object... objs) { info(objs); logEvent(event); }
Shorthand for outputting a log string as log level Level.WARNING on this logger
Params:
  • str – the string to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#WARNING} on this logger * @param str the string to log */
public void warning(final String str) { log(Level.WARNING, str); }
Shorthand for outputting a log string as log level Level.WARNING on this logger
Params:
  • event – optional runtime event to log
  • str – the string to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#WARNING} on this logger * @param event optional runtime event to log * @param str the string to log */
public void warning(final RuntimeEvent<?> event, final String str) { warning(str); logEvent(event); }
Shorthand for outputting a log string as log level Level.FINE on this logger
Params:
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINE} on this logger * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void warning(final Object... objs) { log(Level.WARNING, objs); }
Shorthand for outputting a log string as log level Level.FINE on this logger
Params:
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
  • event – optional runtime event to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINE} on this logger * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead * @param event optional runtime event to log */
public void warning(final RuntimeEvent<?> event, final Object... objs) { warning(objs); logEvent(event); }
Shorthand for outputting a log string as log level Level.SEVERE on this logger
Params:
  • str – the string to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#SEVERE} on this logger * @param str the string to log */
public void severe(final String str) { log(Level.SEVERE, str); }
Shorthand for outputting a log string as log level Level.SEVERE on this logger
Params:
  • str – the string to log
  • event – optional runtime event to log
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#SEVERE} on this logger * @param str the string to log * @param event optional runtime event to log */
public void severe(final RuntimeEvent<?> event, final String str) { severe(str); logEvent(event); }
Shorthand for outputting a log string as log level Level.SEVERE on this logger
Params:
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#SEVERE} on this logger * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void severe(final Object... objs) { log(Level.SEVERE, objs); }
Shorthand for outputting a log string as log level Level.FINE on this logger
Params:
  • event – optional runtime event to log
  • objs – object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
/** * Shorthand for outputting a log string as log level * {@link java.util.logging.Level#FINE} on this logger * @param event optional runtime event to log * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead */
public void severe(final RuntimeEvent<?> event, final Object... objs) { severe(objs); logEvent(event); }
Output log line on this logger at a given level of verbosity
Params:
  • level – minimum log level required for logging to take place
  • str – string to log
See Also:
  • Level
/** * Output log line on this logger at a given level of verbosity * @see java.util.logging.Level * * @param level minimum log level required for logging to take place * @param str string to log */
public void log(final Level level, final String str) { if (isEnabled && !isQuiet && logger.isLoggable(level)) { final StringBuilder sb = new StringBuilder(); for (int i = 0 ; i < indent ; i++) { sb.append(' '); } sb.append(str); logger.log(level, sb.toString()); } }
Output log line on this logger at a given level of verbosity
Params:
  • level – minimum log level required for logging to take place
  • objs – objects for which to invoke toString and concatenate to log
See Also:
  • Level
/** * Output log line on this logger at a given level of verbosity * @see java.util.logging.Level * * @param level minimum log level required for logging to take place * @param objs objects for which to invoke toString and concatenate to log */
public void log(final Level level, final Object... objs) { if (isEnabled && !isQuiet && logger.isLoggable(level)) { final StringBuilder sb = new StringBuilder(); for (final Object obj : objs) { sb.append(obj); } log(level, sb.toString()); } }
Access control context for logger level and instantiation permissions
Returns:access control context
/** * Access control context for logger level and instantiation permissions * @return access control context */
private static AccessControlContext createLoggerControlAccCtxt() { final Permissions perms = new Permissions(); perms.add(new LoggingPermission("control", null)); return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) }); } }