0

Add support for Bukkit formatting markers

This commit is contained in:
rjenkinsjr
2016-03-31 23:16:47 -04:00
parent 2a24764d65
commit 11996d92fd
3 changed files with 447 additions and 247 deletions

View File

@@ -67,9 +67,9 @@ public final class BukkitColorMapper {
* @return never null. * @return never null.
*/ */
public static String map(final String input) { public static String map(final String input) {
if (input == null) return ""; if (input == null) { return ""; }
String output = input; String output = input;
for (final Map.Entry<ChatColor, String> mapping : MAP.entrySet()) { for (final Map.Entry<ChatColor, String> mapping : BukkitColorMapper.MAP.entrySet()) {
output = output.replace(mapping.getKey().toString(), mapping.getValue()); output = output.replace(mapping.getKey().toString(), mapping.getValue());
} }
return output; return output;

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2016 Ronald Jack Jenkins Jr.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package info.ronjenkins.slf4bukkit;
import java.util.Collections;
import java.util.Iterator;
import org.bukkit.ChatColor;
import org.slf4j.Marker;
/**
* SLF4J markers that map to {@link ChatColor}s. These markers never contain any
* references (other markers).
*
* @author Ronald Jack Jenkins Jr.
*/
public enum BukkitColorMarker implements Marker {
AQUA(ChatColor.AQUA), BLACK(ChatColor.BLACK), BLUE(ChatColor.BLUE),
BOLD(ChatColor.BOLD), DARK_AQUA(ChatColor.DARK_AQUA),
DARK_BLUE(ChatColor.DARK_BLUE), DARK_GRAY(ChatColor.DARK_GRAY),
DARK_GREEN(ChatColor.DARK_GREEN), DARK_PURPLE(ChatColor.DARK_PURPLE),
DARK_RED(ChatColor.DARK_RED), GOLD(ChatColor.GOLD), GRAY(ChatColor.GRAY),
GREEN(ChatColor.GREEN), ITALIC(ChatColor.ITALIC),
LIGHT_PURPLE(ChatColor.LIGHT_PURPLE), MAGIC(ChatColor.MAGIC),
RED(ChatColor.RED), RESET(ChatColor.RESET),
STRIKETHROUGH(ChatColor.STRIKETHROUGH), UNDERLINE(ChatColor.UNDERLINE),
WHITE(ChatColor.WHITE), YELLOW(ChatColor.YELLOW);
private final ChatColor value;
private BukkitColorMarker(final ChatColor value) {
this.value = value;
}
/**
* Not supported.
*
* @param reference
* unused.
* @throws UnsupportedOperationException
* always.
*/
@Override
public void add(final Marker reference) {
throw new UnsupportedOperationException();
}
/*
* Marker API
*/
/**
* These markers never have references.
*
* @return false.
*/
@Override
public boolean contains(final Marker other) {
// TODO Auto-generated method stub
return false;
}
/**
* These markers never have references.
*
* @return false.
*/
@Override
public boolean contains(final String name) {
return false;
}
/**
* Returns the enum name of this marker.
*
* @return never null.
*/
@Override
public String getName() {
return this.name();
}
/**
* Returns the Bukkit color object associated with this marker.
*
* @return never null.
*/
public ChatColor getValue() {
return this.value;
}
/**
* These markers never have references.
*
* @return false.
*/
@Override
@SuppressWarnings({ "all", "deprecation" })
public boolean hasChildren() {
return false;
}
/**
* These markers never have references.
*
* @return false.
*/
@Override
public boolean hasReferences() {
// TODO Auto-generated method stub
return false;
}
/**
* These markers never have references.
*
* @return false.
*/
@Override
public Iterator<Marker> iterator() {
return Collections.emptyIterator();
}
/**
* Not supported.
*
* @param reference
* unused.
* @throws UnsupportedOperationException
* always.
*/
@Override
public boolean remove(final Marker reference) {
throw new UnsupportedOperationException();
}
}

View File

@@ -45,6 +45,7 @@
package org.slf4j.impl; package org.slf4j.impl;
import info.ronjenkins.slf4bukkit.BukkitColorMapper; import info.ronjenkins.slf4bukkit.BukkitColorMapper;
import info.ronjenkins.slf4bukkit.BukkitColorMarker;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -52,15 +53,15 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.event.Level; import org.slf4j.event.Level;
import org.slf4j.helpers.FormattingTuple; import org.slf4j.helpers.FormattingTuple;
import org.slf4j.helpers.MarkerIgnoringBase;
import org.slf4j.helpers.MessageFormatter; import org.slf4j.helpers.MessageFormatter;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
@@ -160,6 +161,13 @@ import org.yaml.snakeyaml.Yaml;
* the message, followed by the line separator for the host. * the message, followed by the line separator for the host.
* </p> * </p>
* *
* <p>
* This logger supports only {@link BukkitColorMarker}s, which are used to
* format the logged message and throwable. All other marker types are ignored.
* The usage of markers does not affect whether or not a given logging level is
* enabled.
* </p>
*
* @author Ceki G&uuml;lc&uuml; * @author Ceki G&uuml;lc&uuml;
* @author <a href="mailto:sanders@apache.org">Scott Sanders</a> * @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
* @author Rod Waldhoff * @author Rod Waldhoff
@@ -168,14 +176,11 @@ import org.yaml.snakeyaml.Yaml;
* @author Peter Royal * @author Peter Royal
* @author Ronald Jack Jenkins Jr. * @author Ronald Jack Jenkins Jr.
*/ */
public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase { public final class BukkitPluginLoggerAdapter implements Logger {
// Plugin reference. // Plugin reference.
private static transient Plugin BUKKIT_PLUGIN; private static transient Plugin BUKKIT_PLUGIN;
private static transient String BUKKIT_PLUGIN_NAME; private static transient String BUKKIT_PLUGIN_NAME;
// Constants for JUL record creation.
private static final String CLASS_SELF = BukkitPluginLoggerAdapter.class.getName();
private static final String CLASS_SUPER = MarkerIgnoringBase.class.getName();
// Configuration parameters. // Configuration parameters.
private static final String CONFIG_FALLBACK_DEFAULT_LOG_LEVEL = "info"; private static final String CONFIG_FALLBACK_DEFAULT_LOG_LEVEL = "info";
private static final boolean CONFIG_FALLBACK_SHOW_HEADER = false; private static final boolean CONFIG_FALLBACK_SHOW_HEADER = false;
@@ -195,8 +200,8 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
private static boolean CONFIG_VALUE_SHOW_THREAD_NAME; private static boolean CONFIG_VALUE_SHOW_THREAD_NAME;
// Initialization lock. // Initialization lock.
private static final Object INITIALIZATION_LOCK = new Object(); private static final Object INITIALIZATION_LOCK = new Object();
// serialVersionUID // The logger name.
private static final long serialVersionUID = -2270127287235697381L; private final String name;
// The short name of this simple log instance // The short name of this simple log instance
private transient String shortLogName = null; private transient String shortLogName = null;
@@ -207,8 +212,8 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
} }
/** /**
* (Re)initializes all SLF4Bukkit loggers, relying on the YAML configuration * (Re)initializes all SLF4Bukkit loggers in this plugin, relying on the YAML
* of the enclosing plugin. * configuration of the plugin.
* *
* @param reinitialize * @param reinitialize
* set to {@code true} to reinitialize all loggers, e.g. after * set to {@code true} to reinitialize all loggers, e.g. after
@@ -257,7 +262,9 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
// (1 and 2 are handled by using the Bukkit API.) // (1 and 2 are handled by using the Bukkit API.)
BukkitPluginLoggerAdapter.CONFIG_VALUE_DEFAULT_LOG_LEVEL = BukkitPluginLoggerAdapter.stringToLevel(BukkitPluginLoggerAdapter.getStringProperty(BukkitPluginLoggerAdapter.CONFIG_KEY_DEFAULT_LOG_LEVEL, BukkitPluginLoggerAdapter.CONFIG_VALUE_DEFAULT_LOG_LEVEL = BukkitPluginLoggerAdapter.stringToLevel(BukkitPluginLoggerAdapter.getStringProperty(BukkitPluginLoggerAdapter.CONFIG_KEY_DEFAULT_LOG_LEVEL,
BukkitPluginLoggerAdapter.CONFIG_FALLBACK_DEFAULT_LOG_LEVEL)); BukkitPluginLoggerAdapter.CONFIG_FALLBACK_DEFAULT_LOG_LEVEL));
if (BukkitPluginLoggerAdapter.CONFIG_VALUE_DEFAULT_LOG_LEVEL == null) BukkitPluginLoggerAdapter.CONFIG_VALUE_DEFAULT_LOG_LEVEL = BukkitPluginLoggerAdapter.stringToLevel(BukkitPluginLoggerAdapter.CONFIG_FALLBACK_DEFAULT_LOG_LEVEL); if (BukkitPluginLoggerAdapter.CONFIG_VALUE_DEFAULT_LOG_LEVEL == null) {
BukkitPluginLoggerAdapter.CONFIG_VALUE_DEFAULT_LOG_LEVEL = BukkitPluginLoggerAdapter.stringToLevel(BukkitPluginLoggerAdapter.CONFIG_FALLBACK_DEFAULT_LOG_LEVEL);
}
BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_HEADER = BukkitPluginLoggerAdapter.getBooleanProperty(BukkitPluginLoggerAdapter.CONFIG_KEY_SHOW_HEADER, BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_HEADER = BukkitPluginLoggerAdapter.getBooleanProperty(BukkitPluginLoggerAdapter.CONFIG_KEY_SHOW_HEADER,
BukkitPluginLoggerAdapter.CONFIG_FALLBACK_SHOW_HEADER); BukkitPluginLoggerAdapter.CONFIG_FALLBACK_SHOW_HEADER);
BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_LOG_NAME = BukkitPluginLoggerAdapter.getBooleanProperty(BukkitPluginLoggerAdapter.CONFIG_KEY_SHOW_LOG_NAME, BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_LOG_NAME = BukkitPluginLoggerAdapter.getBooleanProperty(BukkitPluginLoggerAdapter.CONFIG_KEY_SHOW_LOG_NAME,
@@ -287,8 +294,8 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
if (BukkitPluginLoggerAdapter.BUKKIT_PLUGIN == null) { return defaultValue; } if (BukkitPluginLoggerAdapter.BUKKIT_PLUGIN == null) { return defaultValue; }
final String prop = BukkitPluginLoggerAdapter.BUKKIT_PLUGIN.getConfig() final String prop = BukkitPluginLoggerAdapter.BUKKIT_PLUGIN.getConfig()
.getString(name); .getString(name);
if ("true".equalsIgnoreCase(prop)) return true; if ("true".equalsIgnoreCase(prop)) { return true; }
if ("false".equalsIgnoreCase(prop)) return false; if ("false".equalsIgnoreCase(prop)) { return false; }
return defaultValue; return defaultValue;
} }
} }
@@ -299,7 +306,7 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
* @return the logger for the plugin if available; otherwise the server * @return the logger for the plugin if available; otherwise the server
* logger. Never null. * logger. Never null.
*/ */
private static Logger getBukkitLogger() { private static java.util.logging.Logger getBukkitLogger() {
synchronized (BukkitPluginLoggerAdapter.INITIALIZATION_LOCK) { synchronized (BukkitPluginLoggerAdapter.INITIALIZATION_LOCK) {
return BukkitPluginLoggerAdapter.BUKKIT_PLUGIN == null ? Bukkit.getLogger() return BukkitPluginLoggerAdapter.BUKKIT_PLUGIN == null ? Bukkit.getLogger()
: BukkitPluginLoggerAdapter.BUKKIT_PLUGIN.getLogger(); : BukkitPluginLoggerAdapter.BUKKIT_PLUGIN.getLogger();
@@ -360,10 +367,6 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
return julLevel; return julLevel;
} }
/*
* Logger API implementations
*/
/** /**
* Convert YAML logging level properties to SLF4J level objects. * Convert YAML logging level properties to SLF4J level objects.
* *
@@ -388,275 +391,369 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
} }
} }
/** @Override
* A simple implementation which logs messages of level DEBUG according public void debug(final Marker marker, final String msg) {
* to the format outlined above. if (!this.isDebugEnabled()) { return; }
*/ this.log(Level.DEBUG, marker, msg, null);
}
@Override
public void debug(final Marker marker, final String format, final Object arg) {
if (!this.isDebugEnabled()) { return; }
this.formatAndLog(Level.DEBUG, marker, format, arg, null);
}
@Override
public void debug(final Marker marker, final String format,
final Object... arguments) {
if (!this.isDebugEnabled()) { return; }
this.formatAndLog(Level.DEBUG, marker, format, arguments);
}
@Override
public void debug(final Marker marker, final String format,
final Object arg1, final Object arg2) {
if (!this.isDebugEnabled()) { return; }
this.formatAndLog(Level.DEBUG, marker, format, arg1, arg2);
}
@Override
public void debug(final Marker marker, final String msg, final Throwable t) {
if (!this.isDebugEnabled()) { return; }
this.log(Level.DEBUG, marker, msg, t);
}
@Override @Override
public void debug(final String msg) { public void debug(final String msg) {
if (!this.isDebugEnabled()) { return; } if (!this.isDebugEnabled()) { return; }
this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.DEBUG, msg, null); this.log(Level.DEBUG, null, msg, null);
} }
/**
* Perform single parameter substitution before logging the message of level
* DEBUG according to the format outlined above.
*/
@Override @Override
public void debug(final String format, final Object param1) { public void debug(final String format, final Object arg) {
if (!this.isDebugEnabled()) { return; } if (!this.isDebugEnabled()) { return; }
this.formatAndLog(Level.DEBUG, format, param1, null); this.formatAndLog(Level.DEBUG, null, format, arg, null);
} }
/**
* Perform double parameter substitution before logging the message of level
* DEBUG according to the format outlined above.
*/
@Override @Override
public void debug(final String format, final Object... argArray) { public void debug(final String format, final Object... arguments) {
if (!this.isDebugEnabled()) { return; } if (!this.isDebugEnabled()) { return; }
this.formatAndLog(Level.DEBUG, format, argArray); this.formatAndLog(Level.DEBUG, null, format, arguments);
} }
/**
* Perform double parameter substitution before logging the message of level
* DEBUG according to the format outlined above.
*/
@Override @Override
public void debug(final String format, final Object param1, public void debug(final String format, final Object arg1, final Object arg2) {
final Object param2) {
if (!this.isDebugEnabled()) { return; } if (!this.isDebugEnabled()) { return; }
this.formatAndLog(Level.DEBUG, format, param1, param2); this.formatAndLog(Level.DEBUG, null, format, arg1, arg2);
} }
/** Log a message of level DEBUG, including an exception. */
@Override @Override
public void debug(final String msg, final Throwable t) { public void debug(final String msg, final Throwable t) {
if (!this.isDebugEnabled()) { return; } if (!this.isDebugEnabled()) { return; }
this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.DEBUG, msg, t); this.log(Level.DEBUG, null, msg, t);
}
@Override
public void error(final Marker marker, final String msg) {
if (!this.isErrorEnabled()) { return; }
this.log(Level.ERROR, marker, msg, null);
}
@Override
public void error(final Marker marker, final String format, final Object arg) {
if (!this.isErrorEnabled()) { return; }
this.formatAndLog(Level.ERROR, marker, format, arg, null);
}
@Override
public void error(final Marker marker, final String format,
final Object... arguments) {
if (!this.isErrorEnabled()) { return; }
this.formatAndLog(Level.ERROR, marker, format, arguments);
}
@Override
public void error(final Marker marker, final String format,
final Object arg1, final Object arg2) {
if (!this.isErrorEnabled()) { return; }
this.formatAndLog(Level.ERROR, marker, format, arg1, arg2);
}
@Override
public void error(final Marker marker, final String msg, final Throwable t) {
if (!this.isErrorEnabled()) { return; }
this.log(Level.ERROR, marker, msg, t);
} }
/**
* A simple implementation which always logs messages of level ERROR according
* to the format outlined above.
*/
@Override @Override
public void error(final String msg) { public void error(final String msg) {
if (!this.isErrorEnabled()) { return; } if (!this.isErrorEnabled()) { return; }
this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.ERROR, msg, null); this.log(Level.ERROR, null, msg, null);
} }
/**
* Perform single parameter substitution before logging the message of level
* ERROR according to the format outlined above.
*/
@Override @Override
public void error(final String format, final Object arg) { public void error(final String format, final Object arg) {
if (!this.isErrorEnabled()) { return; } if (!this.isErrorEnabled()) { return; }
this.formatAndLog(Level.ERROR, format, arg, null); this.formatAndLog(Level.ERROR, null, format, arg, null);
} }
/**
* Perform double parameter substitution before logging the message of level
* ERROR according to the format outlined above.
*/
@Override @Override
public void error(final String format, final Object... argArray) { public void error(final String format, final Object... arguments) {
if (!this.isErrorEnabled()) { return; } if (!this.isErrorEnabled()) { return; }
this.formatAndLog(Level.ERROR, format, argArray); this.formatAndLog(Level.ERROR, null, format, arguments);
} }
/**
* Perform double parameter substitution before logging the message of level
* ERROR according to the format outlined above.
*/
@Override @Override
public void error(final String format, final Object arg1, final Object arg2) { public void error(final String format, final Object arg1, final Object arg2) {
if (!this.isErrorEnabled()) { return; } if (!this.isErrorEnabled()) { return; }
this.formatAndLog(Level.ERROR, format, arg1, arg2); this.formatAndLog(Level.ERROR, null, format, arg1, arg2);
} }
/** Log a message of level ERROR, including an exception. */
@Override @Override
public void error(final String msg, final Throwable t) { public void error(final String msg, final Throwable t) {
if (!this.isErrorEnabled()) { return; } if (!this.isErrorEnabled()) { return; }
this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.ERROR, msg, t); this.log(Level.ERROR, null, msg, t);
}
@Override
public String getName() {
return this.name;
}
@Override
public void info(final Marker marker, final String msg) {
if (!this.isInfoEnabled()) { return; }
this.log(Level.INFO, marker, msg, null);
}
@Override
public void info(final Marker marker, final String format, final Object arg) {
if (!this.isInfoEnabled()) { return; }
this.formatAndLog(Level.INFO, marker, format, arg, null);
}
@Override
public void info(final Marker marker, final String format,
final Object... arguments) {
if (!this.isInfoEnabled()) { return; }
this.formatAndLog(Level.INFO, marker, format, arguments);
}
@Override
public void info(final Marker marker, final String format, final Object arg1,
final Object arg2) {
if (!this.isInfoEnabled()) { return; }
this.formatAndLog(Level.INFO, marker, format, arg1, arg2);
}
@Override
public void info(final Marker marker, final String msg, final Throwable t) {
if (!this.isInfoEnabled()) { return; }
this.log(Level.INFO, marker, msg, t);
} }
/**
* A simple implementation which logs messages of level INFO according
* to the format outlined above.
*/
@Override @Override
public void info(final String msg) { public void info(final String msg) {
if (!this.isInfoEnabled()) { return; } if (!this.isInfoEnabled()) { return; }
this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.INFO, msg, null); this.log(Level.INFO, null, msg, null);
} }
/**
* Perform single parameter substitution before logging the message of level
* INFO according to the format outlined above.
*/
@Override @Override
public void info(final String format, final Object arg) { public void info(final String format, final Object arg) {
if (!this.isInfoEnabled()) { return; } if (!this.isInfoEnabled()) { return; }
this.formatAndLog(Level.INFO, format, arg, null); this.formatAndLog(Level.INFO, null, format, arg, null);
} }
/**
* Perform double parameter substitution before logging the message of level
* INFO according to the format outlined above.
*/
@Override @Override
public void info(final String format, final Object... argArray) { public void info(final String format, final Object... arguments) {
if (!this.isInfoEnabled()) { return; } if (!this.isInfoEnabled()) { return; }
this.formatAndLog(Level.INFO, format, argArray); this.formatAndLog(Level.INFO, null, format, arguments);
} }
/**
* Perform double parameter substitution before logging the message of level
* INFO according to the format outlined above.
*/
@Override @Override
public void info(final String format, final Object arg1, final Object arg2) { public void info(final String format, final Object arg1, final Object arg2) {
if (!this.isInfoEnabled()) { return; } if (!this.isInfoEnabled()) { return; }
this.formatAndLog(Level.INFO, format, arg1, arg2); this.formatAndLog(Level.INFO, null, format, arg1, arg2);
} }
/** Log a message of level INFO, including an exception. */
@Override @Override
public void info(final String msg, final Throwable t) { public void info(final String msg, final Throwable t) {
if (!this.isInfoEnabled()) { return; } if (!this.isInfoEnabled()) { return; }
this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.INFO, msg, t); this.log(Level.INFO, null, msg, t);
} }
/** Are {@code debug} messages currently enabled? */
@Override @Override
public boolean isDebugEnabled() { public boolean isDebugEnabled() {
return this.isLevelEnabled(Level.DEBUG); return this.isLevelEnabled(Level.DEBUG);
} }
/** Are {@code error} messages currently enabled? */ @Override
public boolean isDebugEnabled(final Marker marker) {
return this.isLevelEnabled(Level.DEBUG);
}
@Override @Override
public boolean isErrorEnabled() { public boolean isErrorEnabled() {
return this.isLevelEnabled(Level.ERROR); return this.isLevelEnabled(Level.ERROR);
} }
/** Are {@code info} messages currently enabled? */ @Override
public boolean isErrorEnabled(final Marker marker) {
return this.isLevelEnabled(Level.ERROR);
}
@Override @Override
public boolean isInfoEnabled() { public boolean isInfoEnabled() {
return this.isLevelEnabled(Level.INFO); return this.isLevelEnabled(Level.INFO);
} }
/** Are {@code trace} messages currently enabled? */ @Override
public boolean isInfoEnabled(final Marker marker) {
return this.isLevelEnabled(Level.INFO);
}
@Override @Override
public boolean isTraceEnabled() { public boolean isTraceEnabled() {
return this.isLevelEnabled(Level.TRACE); return this.isLevelEnabled(Level.TRACE);
} }
/** Are {@code warn} messages currently enabled? */ @Override
public boolean isTraceEnabled(final Marker marker) {
return this.isLevelEnabled(Level.TRACE);
}
@Override @Override
public boolean isWarnEnabled() { public boolean isWarnEnabled() {
return this.isLevelEnabled(Level.WARN); return this.isLevelEnabled(Level.WARN);
} }
/** @Override
* A simple implementation which logs messages of level TRACE according public boolean isWarnEnabled(final Marker marker) {
* to the format outlined above. return this.isLevelEnabled(Level.WARN);
*/ }
@Override
public void trace(final Marker marker, final String msg) {
if (!this.isTraceEnabled()) { return; }
this.log(Level.TRACE, marker, msg, null);
}
@Override
public void trace(final Marker marker, final String format, final Object arg) {
if (!this.isTraceEnabled()) { return; }
this.formatAndLog(Level.TRACE, marker, format, arg, null);
}
@Override
public void trace(final Marker marker, final String format,
final Object... arguments) {
if (!this.isTraceEnabled()) { return; }
this.formatAndLog(Level.TRACE, marker, format, arguments);
}
@Override
public void trace(final Marker marker, final String format,
final Object arg1, final Object arg2) {
if (!this.isTraceEnabled()) { return; }
this.formatAndLog(Level.TRACE, marker, format, arg1, arg2);
}
@Override
public void trace(final Marker marker, final String msg, final Throwable t) {
if (!this.isTraceEnabled()) { return; }
this.log(Level.TRACE, marker, msg, t);
}
@Override @Override
public void trace(final String msg) { public void trace(final String msg) {
if (!this.isTraceEnabled()) { return; } if (!this.isTraceEnabled()) { return; }
this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.TRACE, msg, null); this.log(Level.TRACE, null, msg, null);
} }
/**
* Perform single parameter substitution before logging the message of level
* TRACE according to the format outlined above.
*/
@Override @Override
public void trace(final String format, final Object param1) { public void trace(final String format, final Object arg) {
if (!this.isTraceEnabled()) { return; } if (!this.isTraceEnabled()) { return; }
this.formatAndLog(Level.TRACE, format, param1, null); this.formatAndLog(Level.TRACE, null, format, arg, null);
} }
/**
* Perform double parameter substitution before logging the message of level
* TRACE according to the format outlined above.
*/
@Override @Override
public void trace(final String format, final Object... argArray) { public void trace(final String format, final Object... arguments) {
if (!this.isTraceEnabled()) { return; } if (!this.isTraceEnabled()) { return; }
this.formatAndLog(Level.TRACE, format, argArray); this.formatAndLog(Level.TRACE, null, format, arguments);
} }
/**
* Perform double parameter substitution before logging the message of level
* TRACE according to the format outlined above.
*/
@Override @Override
public void trace(final String format, final Object param1, public void trace(final String format, final Object arg1, final Object arg2) {
final Object param2) {
if (!this.isTraceEnabled()) { return; } if (!this.isTraceEnabled()) { return; }
this.formatAndLog(Level.TRACE, format, param1, param2); this.formatAndLog(Level.TRACE, null, format, arg1, arg2);
} }
/** Log a message of level TRACE, including an exception. */
@Override @Override
public void trace(final String msg, final Throwable t) { public void trace(final String msg, final Throwable t) {
if (!this.isTraceEnabled()) { return; } if (!this.isTraceEnabled()) { return; }
this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.TRACE, msg, t); this.log(Level.TRACE, null, msg, t);
}
@Override
public void warn(final Marker marker, final String msg) {
if (!this.isWarnEnabled()) { return; }
this.log(Level.WARN, marker, msg, null);
}
@Override
public void warn(final Marker marker, final String format, final Object arg) {
if (!this.isWarnEnabled()) { return; }
this.formatAndLog(Level.WARN, marker, format, arg, null);
}
@Override
public void warn(final Marker marker, final String format,
final Object... arguments) {
if (!this.isWarnEnabled()) { return; }
this.formatAndLog(Level.WARN, marker, format, arguments);
}
@Override
public void warn(final Marker marker, final String format, final Object arg1,
final Object arg2) {
if (!this.isWarnEnabled()) { return; }
this.formatAndLog(Level.WARN, marker, format, arg1, arg2);
}
@Override
public void warn(final Marker marker, final String msg, final Throwable t) {
if (!this.isWarnEnabled()) { return; }
this.log(Level.WARN, marker, msg, t);
} }
/**
* A simple implementation which always logs messages of level WARN according
* to the format outlined above.
*/
@Override @Override
public void warn(final String msg) { public void warn(final String msg) {
if (!this.isWarnEnabled()) { return; } if (!this.isWarnEnabled()) { return; }
this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.WARN, msg, null); this.log(Level.WARN, null, msg, null);
} }
/**
* Perform single parameter substitution before logging the message of level
* WARN according to the format outlined above.
*/
@Override @Override
public void warn(final String format, final Object arg) { public void warn(final String format, final Object arg) {
if (!this.isWarnEnabled()) { return; } if (!this.isWarnEnabled()) { return; }
this.formatAndLog(Level.WARN, format, arg, null); this.formatAndLog(Level.WARN, null, format, arg, null);
} }
/**
* Perform double parameter substitution before logging the message of level
* WARN according to the format outlined above.
*/
@Override @Override
public void warn(final String format, final Object... argArray) { public void warn(final String format, final Object... arguments) {
if (!this.isWarnEnabled()) { return; } if (!this.isWarnEnabled()) { return; }
this.formatAndLog(Level.WARN, format, argArray); this.formatAndLog(Level.WARN, null, format, arguments);
} }
/**
* Perform double parameter substitution before logging the message of level
* WARN according to the format outlined above.
*/
@Override @Override
public void warn(final String format, final Object arg1, final Object arg2) { public void warn(final String format, final Object arg1, final Object arg2) {
if (!this.isWarnEnabled()) { return; } if (!this.isWarnEnabled()) { return; }
this.formatAndLog(Level.WARN, format, arg1, arg2); this.formatAndLog(Level.WARN, null, format, arg1, arg2);
} }
/*
* Logic from SimpleLogger/JDK14LoggerAdapter
*/
/** Log a message of level WARN, including an exception. */
@Override @Override
public void warn(final String msg, final Throwable t) { public void warn(final String msg, final Throwable t) {
if (!this.isWarnEnabled()) { return; } if (!this.isWarnEnabled()) { return; }
this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.WARN, msg, t); this.log(Level.WARN, null, msg, t);
} }
/** /**
@@ -709,17 +806,18 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
* *
* @param level * @param level
* the level of this message. * the level of this message.
* @param marker
* the marker to use for this message, may be null.
* @param format * @param format
* the message format string. * the message format string.
* @param arguments * @param arguments
* 3 or more arguments. * 3 or more arguments.
*/ */
private void formatAndLog(final Level level, final String format, private void formatAndLog(final Level level, final Marker marker,
final Object... arguments) { final String format, final Object... arguments) {
if (!this.isLevelEnabled(level)) { return; } if (!this.isLevelEnabled(level)) { return; }
final FormattingTuple tp = MessageFormatter.arrayFormat(format, arguments); final FormattingTuple tp = MessageFormatter.arrayFormat(format, arguments);
this.log(BukkitPluginLoggerAdapter.CLASS_SELF, level, tp.getMessage(), this.log(level, marker, tp.getMessage(), tp.getThrowable());
tp.getThrowable());
} }
/** /**
@@ -727,6 +825,8 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
* *
* @param level * @param level
* the level of this message. * the level of this message.
* @param marker
* the marker to use for this message, may be null.
* @param format * @param format
* the message format string. * the message format string.
* @param arg1 * @param arg1
@@ -734,12 +834,12 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
* @param arg2 * @param arg2
* format argument #2. * format argument #2.
*/ */
private void formatAndLog(final Level level, final String format, private void formatAndLog(final Level level, final Marker marker,
final Object arg1, final Object arg2) { final String format, final Object arg1,
final Object arg2) {
if (!this.isLevelEnabled(level)) { return; } if (!this.isLevelEnabled(level)) { return; }
final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2);
this.log(BukkitPluginLoggerAdapter.CLASS_SELF, level, tp.getMessage(), this.log(level, marker, tp.getMessage(), tp.getThrowable());
tp.getThrowable());
} }
/** /**
@@ -765,91 +865,22 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
&& (BukkitPluginLoggerAdapter.getBukkitLogger().isLoggable(BukkitPluginLoggerAdapter.slf4jLevelIntToBukkitJULLevel(logLevel))); && (BukkitPluginLoggerAdapter.getBukkitLogger().isLoggable(BukkitPluginLoggerAdapter.slf4jLevelIntToBukkitJULLevel(logLevel)));
} }
/**
* Fill in JUL caller data if possible.
*
* @param record
* the record to update.
*/
private void
julFillCallerData(final String callerFQCN, final LogRecord record) {
final StackTraceElement[] steArray = new Throwable().getStackTrace();
int selfIndex = -1;
for (int i = 0; i < steArray.length; i++) {
final String className = steArray[i].getClassName();
if (className.equals(callerFQCN)
|| className.equals(BukkitPluginLoggerAdapter.CLASS_SUPER)) {
selfIndex = i;
break;
}
}
int found = -1;
for (int i = selfIndex + 1; i < steArray.length; i++) {
final String className = steArray[i].getClassName();
if (!(className.equals(callerFQCN) || className.equals(BukkitPluginLoggerAdapter.CLASS_SUPER))) {
found = i;
break;
}
}
if (found != -1) {
final StackTraceElement ste = steArray[found];
// setting the class name has the side effect of setting
// the needToInferCaller variable to false.
record.setSourceClassName(ste.getClassName());
record.setSourceMethodName(ste.getMethodName());
}
}
/**
* Log the message at the specified level with the specified throwable if any.
* This method creates a LogRecord and fills in caller information before
* calling the passed Bukkit plugin/server logger.
*
* See SLF4J bug report #13 for more details.
*
* @param logger
* the logger to which the message will be logged.
* @param callerFQCN
* the FQCN of the class that is calling the logger.
* @param level
* the desired log level of the message.
* @param message
* the msg to be logged.
* @param throwable
* the exception to be logged, may be null.
*/
private void julLog(final Logger logger, final String callerFQCN,
final java.util.logging.Level level,
final String message, final Throwable throwable) {
// millis and thread are filled by the constructor
final LogRecord record = new LogRecord(level, message);
record.setLoggerName(this.getName());
record.setThrown(throwable);
// Note: parameters in record are not set because SLF4J only
// supports a single formatting style
this.julFillCallerData(callerFQCN, record);
logger.log(record);
}
/** /**
* Assembles the final log message and sends it to the appropriate Bukkit * Assembles the final log message and sends it to the appropriate Bukkit
* logger. * logger.
* *
* @param callerFQCN
* the FQCN of the class that is calling the logger.
* @param level * @param level
* the desired log level of the message. * the desired log level of the message.
* @param marker
* the marker to use for this message, may be null.
* @param message * @param message
* the message to be logged. * the message to be logged.
* @param throwable * @param throwable
* the exception to be logged, may be null. * the exception to be logged, may be null.
*/ */
private void log(final String callerFQCN, final Level level, private void log(final Level level, final Marker marker,
final String message, final Throwable throwable) { final String message, final Throwable throwable) {
final Logger logger; final java.util.logging.Logger logger;
synchronized (BukkitPluginLoggerAdapter.INITIALIZATION_LOCK) { synchronized (BukkitPluginLoggerAdapter.INITIALIZATION_LOCK) {
// Ensure that the logger will accept this request. // Ensure that the logger will accept this request.
if (!this.isLevelEnabled(level)) { return; } if (!this.isLevelEnabled(level)) { return; }
@@ -859,9 +890,16 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
// Start building the log message. // Start building the log message.
final StringBuilder buf = new StringBuilder(32); final StringBuilder buf = new StringBuilder(32);
boolean hasHeader = false;
// Use the marker, if applicable.
if (marker instanceof BukkitColorMarker) {
buf.append(((BukkitColorMarker) marker).getValue());
}
// Indicate that this message comes from SLF4J, if desired. // Indicate that this message comes from SLF4J, if desired.
if (BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_HEADER) { if (BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_HEADER) {
hasHeader = true;
buf.append("[SLF4J]"); buf.append("[SLF4J]");
} }
@@ -869,9 +907,11 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
// that Bukkit would otherwise eat. // that Bukkit would otherwise eat.
switch (level) { switch (level) {
case TRACE: case TRACE:
hasHeader = true;
buf.append("[TRACE]"); buf.append("[TRACE]");
break; break;
case DEBUG: case DEBUG:
hasHeader = true;
buf.append("[DEBUG]"); buf.append("[DEBUG]");
break; break;
default: default:
@@ -880,13 +920,14 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
// Append the current thread name, if desired. // Append the current thread name, if desired.
if (BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_THREAD_NAME) { if (BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_THREAD_NAME) {
hasHeader = true;
buf.append('['); buf.append('[');
buf.append(Thread.currentThread().getName()); buf.append(Thread.currentThread().getName());
buf.append("]"); buf.append("]");
} }
// Buffer the current output with a space, unless there is no output. // Buffer the current output with a space, unless there is no output.
if (buf.length() > 0) { if (hasHeader) {
buf.append(' '); buf.append(' ');
} }
@@ -901,12 +942,19 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
} }
// Append the message. // Append the message.
buf.append(message).append(ChatColor.RESET); buf.append(message);
// Append the throwable, if applicable.
if (throwable != null) {
buf.append('\n').append(ExceptionUtils.getFullStackTrace(throwable)
.trim());
}
// Append a reset directive.
buf.append(ChatColor.RESET);
// Log the message. // Log the message.
this.julLog(logger, BukkitPluginLoggerAdapter.CLASS_SELF, logger.log(BukkitPluginLoggerAdapter.slf4jLevelIntToBukkitJULLevel(level),
BukkitPluginLoggerAdapter.slf4jLevelIntToBukkitJULLevel(level), BukkitColorMapper.map(buf.toString()));
BukkitColorMapper.map(buf.toString()), throwable);
} }
} }