0

Improve Javadocs and initialization routine

This commit is contained in:
rjenkinsjr
2016-03-28 19:58:32 -04:00
parent f2a64e44eb
commit ac1ff26365

View File

@@ -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&uuml;lc&uuml; * @author Ceki G&uuml;lc&uuml;
@@ -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.