Improve Javadocs and initialization routine
This commit is contained in:
@@ -66,62 +66,92 @@ import org.yaml.snakeyaml.Yaml;
|
|||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* A merger of SLF4J's {@code SimpleLogger} and {@code JDK14LoggerAdapter},
|
* A merger of SLF4J's {@code SimpleLogger} and {@code JDK14LoggerAdapter},
|
||||||
* wired to log all messages to the Bukkit plugin found in this class's
|
* wired to log all messages to the enclosing Bukkit plugin. The plugin is
|
||||||
* classloader (by way of reading plugin.yml).
|
* identified by reading the "name" attribute from {@code plugin.yml} in the
|
||||||
|
* current classloader.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* SLF4J messages at level {@code TRACE} or {@code DEBUG} are logged to Bukkit
|
* Plugins that include SLF4Bukkit can use the following values in
|
||||||
* at level {@link Level#INFO} because Bukkit does not enable any levels higher
|
* {@code config.yml} to configure the behavior of SLF4Bukkit. SLF4Bukkit uses
|
||||||
* than {@code INFO}. Therefore, only SLF4J messages at level {@code TRACE} or
|
* Bukkit's plugin configuration API to retrieve config values, so both on-disk
|
||||||
* {@code DEBUG} show their SLF4J level in the message that is logged to the
|
* and built-in {@code config.yml} behavior is supported.
|
||||||
* server console.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Plugins that shade SLF4Bukkit can use the following values in config.yml to
|
|
||||||
* configure the behavior of this logger:
|
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li><code>slf4j.defaultLogLevel</code> - Default log level for all instances
|
* <li><code>slf4j.defaultLogLevel</code> - Default log level for all SLF4Bukkit
|
||||||
* of SimpleLogger. Must be one of ("trace", "debug", "info", "warn", or
|
* loggers in this plugin. Must be one of "trace", "debug", "info", "warn", or
|
||||||
* "error"). If not specified, defaults to "info".</li>
|
* "error". Defaults to "info".</li>
|
||||||
*
|
*
|
||||||
* <li><code>slf4j.log.<em>a.b.c</em></code> - Logging detail level for a
|
* <li><code>slf4j.log.<em>a.b.c</em></code> - Logging detail level for an
|
||||||
* SimpleLogger instance named "a.b.c". Right-side value must be one of "trace",
|
* SLF4Bukkit logger instance in this plugin named "a.b.c". Right-side value
|
||||||
* "debug", "info", "warn", or "error". When a SimpleLogger named "a.b.c" is
|
* must be one of "trace", "debug", "info", "warn", or "error". When a logger
|
||||||
* initialized, its level is assigned from this property. If unspecified, the
|
* named "a.b.c" is initialized, its level is assigned from this property. If
|
||||||
* level of nearest parent logger will be used, and if none is set, then the
|
* unspecified, the level of the nearest parent logger will be used. If no
|
||||||
* value specified by <code>slf4j.defaultLogLevel</code> will be used.</li>
|
* parent logger level is set, then the value specified by
|
||||||
|
* <code>slf4j.defaultLogLevel</code> for this plugin will be used.</li>
|
||||||
*
|
*
|
||||||
* <li><code>slf4j.showHeader</code> -Set to <code>true</code> if you want to
|
* <li><code>slf4j.showHeader</code> -Set to <code>true</code> if you want to
|
||||||
* output the [SLF4J]. Defaults to <code>false</code>.</li>
|
* output the {@code [SLF4J]} header. Defaults to <code>false</code>.</li>
|
||||||
*
|
*
|
||||||
* <li><code>slf4j.showThreadName</code> -Set to <code>true</code> if you want
|
* <li><code>slf4j.showThreadName</code> -Set to <code>true</code> if you want
|
||||||
* to output the current thread name. Defaults to <code>false</code>.</li>
|
* to output the current thread name. Defaults to <code>false</code>.</li>
|
||||||
*
|
*
|
||||||
* <li><code>slf4j.showLogName</code> - Set to <code>true</code> if you want the
|
* <li><code>slf4j.showLogName</code> - Set to <code>true</code> if you want the
|
||||||
* Logger instance name to be included in output messages. Defaults to
|
* logger instance name to be included in output messages. Defaults to
|
||||||
* <code>false</code>.</li>
|
* <code>false</code>.</li>
|
||||||
*
|
*
|
||||||
* <li><code>slf4j.showShortLogName</code> - Set to <code>true</code> if you
|
* <li><code>slf4j.showShortLogName</code> - Set to <code>true</code> if you
|
||||||
* want the last component of the name to be included in output messages.
|
* want the logger instance's short name to be included in output messages. The
|
||||||
|
* short name is equal to the full name with every dot-separated portion of the
|
||||||
|
* full name (except the last portion) truncated to its first character.
|
||||||
* Defaults to <code>true</code>.</li>
|
* Defaults to <code>true</code>.</li>
|
||||||
*
|
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Because SLF4Bukkit's configuration comes from the plugin configuration,
|
* SLF4J messages at level {@code TRACE} or {@code DEBUG} are logged to Bukkit
|
||||||
* SLF4Bukkit supports configuration reloading (assuming the containing plugin
|
* at level {@code INFO} because Bukkit does not enable any levels higher than
|
||||||
* supports config reloading). To achieve this, call {@link #init()} after
|
* {@code INFO}. Therefore, only SLF4J messages at level {@code TRACE} or
|
||||||
* calling {@link Plugin#reloadConfig()}.
|
* {@code DEBUG} show their SLF4J level in the message that is logged to the
|
||||||
|
* server console.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* With no configuration, the default output includes the thread name, the SLF4J
|
* Because SLF4Bukkit's configuration comes from the plugin configuration,
|
||||||
* level (only if it differs from the Bukkit level; see above), logger name, and
|
* SLF4Bukkit supports configuration reloading. To achieve this, call
|
||||||
* the message followed by the line separator for the host.
|
* {@link #init()} with argument {@code true} after calling
|
||||||
|
* {@link Plugin#reloadConfig()}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* It is possible for SLF4J loggers to be used before the plugin is registered
|
||||||
|
* with Bukkit's plugin manager. SLF4Bukkit is considered to be
|
||||||
|
* <i>uninitialized</i> as long as the plugin cannot be retrieved from Bukkit's
|
||||||
|
* plugin manager. While in the uninitialized state, SLF4Bukkit:
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>uses {@link Bukkit#getLogger()} instead of {@link Plugin#getLogger()}.</li>
|
||||||
|
* <li>uses the default configuration values (see above).</li>
|
||||||
|
* <li>attempts to initialize itself upon every logging call until the plugin is
|
||||||
|
* retrievable from Bukkit's plugin manager, at which point SLF4Bukkit is
|
||||||
|
* considered to be <i>initialized</i>. Once initialized,
|
||||||
|
* {@link Plugin#getLogger()} and {@link Plugin#getConfig() the plugin YAML
|
||||||
|
* configuration values} are used.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* For this reason, it is strongly recommended that you not emit any log
|
||||||
|
* messages via SLF4Bukkit until your plugin's {@link Plugin#onLoad() onLoad()}
|
||||||
|
* method has begun execution. (You can safely log messages inside the
|
||||||
|
* {@code onLoad()} method, because your plugin is registered by that time.)
|
||||||
|
* Logging inside static initializers, the plugin class constructor and other
|
||||||
|
* pre-plugin-registration areas of your code is discouraged.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* With no configuration, the default output includes the logger short name and
|
||||||
|
* the message, followed by the line separator for the host.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Ceki Gülcü
|
* @author Ceki Gülcü
|
||||||
@@ -138,6 +168,7 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase
|
|||||||
|
|
||||||
// Plugin reference.
|
// Plugin reference.
|
||||||
private static transient Plugin BUKKIT_PLUGIN;
|
private static transient Plugin BUKKIT_PLUGIN;
|
||||||
|
private static transient String BUKKIT_PLUGIN_NAME;
|
||||||
// Constants for JUL record creation.
|
// Constants for JUL record creation.
|
||||||
private static final String CLASS_SELF = BukkitPluginLoggerAdapter.class.getName();
|
private static final String CLASS_SELF = BukkitPluginLoggerAdapter.class.getName();
|
||||||
private static final String CLASS_SUPER = MarkerIgnoringBase.class.getName();
|
private static final String CLASS_SUPER = MarkerIgnoringBase.class.getName();
|
||||||
@@ -158,8 +189,6 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase
|
|||||||
private static boolean CONFIG_SHOW_LOG_NAME;
|
private static boolean CONFIG_SHOW_LOG_NAME;
|
||||||
private static boolean CONFIG_SHOW_SHORT_LOG_NAME;
|
private static boolean CONFIG_SHOW_SHORT_LOG_NAME;
|
||||||
private static boolean CONFIG_SHOW_THREAD_NAME;
|
private static boolean CONFIG_SHOW_THREAD_NAME;
|
||||||
// Initialization status.
|
|
||||||
private static boolean INIT_FAILURE_WARNED = false;
|
|
||||||
// Initialization lock.
|
// Initialization lock.
|
||||||
private static final Object INITIALIZATION_LOCK = new Object();
|
private static final Object INITIALIZATION_LOCK = new Object();
|
||||||
// Logging level constants.
|
// Logging level constants.
|
||||||
@@ -189,7 +218,7 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* (Re)initializes all SLF4Bukkit loggers, relying on the YAML configuration
|
* (Re)initializes all SLF4Bukkit loggers, relying on the YAML configuration
|
||||||
* of the containing plugin.
|
* of the enclosing 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
|
||||||
@@ -200,10 +229,11 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase
|
|||||||
// Do not re-initialize unless requested.
|
// Do not re-initialize unless requested.
|
||||||
if (reinitialize) {
|
if (reinitialize) {
|
||||||
BukkitPluginLoggerAdapter.BUKKIT_PLUGIN = null;
|
BukkitPluginLoggerAdapter.BUKKIT_PLUGIN = null;
|
||||||
|
BUKKIT_PLUGIN_NAME = null;
|
||||||
} else if (BukkitPluginLoggerAdapter.BUKKIT_PLUGIN != null) { return; }
|
} else if (BukkitPluginLoggerAdapter.BUKKIT_PLUGIN != null) { return; }
|
||||||
// Get a reference to the plugin in this classloader.
|
// Get a reference to the plugin in this classloader.
|
||||||
|
if (BUKKIT_PLUGIN_NAME == null) {
|
||||||
InputStream pluginYmlFile = null;
|
InputStream pluginYmlFile = null;
|
||||||
String pluginName;
|
|
||||||
try {
|
try {
|
||||||
pluginYmlFile = BukkitPluginLoggerAdapter.class.getClassLoader()
|
pluginYmlFile = BukkitPluginLoggerAdapter.class.getClassLoader()
|
||||||
.getResource("plugin.yml")
|
.getResource("plugin.yml")
|
||||||
@@ -211,7 +241,7 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase
|
|||||||
final Yaml yaml = new Yaml();
|
final Yaml yaml = new Yaml();
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
final Map pluginYml = (Map) yaml.load(pluginYmlFile);
|
final Map pluginYml = (Map) yaml.load(pluginYmlFile);
|
||||||
pluginName = (String) pluginYml.get("name");
|
BUKKIT_PLUGIN_NAME = (String) pluginYml.get("name");
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -223,20 +253,13 @@ public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get the plugin.
|
}
|
||||||
|
// Try to get the plugin. The logging system will be considered
|
||||||
|
// uninitialized until this becomes non-null. While it is null, the Bukkit
|
||||||
|
// server logger will be used instead of the plugin logger, and all
|
||||||
|
// default configuration options will be used.
|
||||||
BukkitPluginLoggerAdapter.BUKKIT_PLUGIN = Bukkit.getPluginManager()
|
BukkitPluginLoggerAdapter.BUKKIT_PLUGIN = Bukkit.getPluginManager()
|
||||||
.getPlugin(pluginName);
|
.getPlugin(BUKKIT_PLUGIN_NAME);
|
||||||
if (BukkitPluginLoggerAdapter.BUKKIT_PLUGIN == null) {
|
|
||||||
// Initialization failed.
|
|
||||||
if (!BukkitPluginLoggerAdapter.INIT_FAILURE_WARNED) {
|
|
||||||
System.err.println("WARN: SLF4Bukkit could not be initialized for plugin "
|
|
||||||
+ pluginName + "; default configuration assumed!");
|
|
||||||
}
|
|
||||||
BukkitPluginLoggerAdapter.INIT_FAILURE_WARNED = true;
|
|
||||||
} else {
|
|
||||||
// Initialization successful.
|
|
||||||
BukkitPluginLoggerAdapter.INIT_FAILURE_WARNED = false;
|
|
||||||
}
|
|
||||||
// Get the configuration values.
|
// Get the configuration values.
|
||||||
// 1. Look in the plugin's on-disk config.
|
// 1. Look in the plugin's on-disk config.
|
||||||
// 2. If the value is absent, use the plugin's built-in config.
|
// 2. If the value is absent, use the plugin's built-in config.
|
||||||
|
|||||||
Reference in New Issue
Block a user