From 5fa596fee9c40adc1d6c56bb42a9f785f04dab9b Mon Sep 17 00:00:00 2001 From: md_5 Date: Fri, 14 May 2021 08:39:17 +1000 Subject: [PATCH] #3084: (Regrettably) add a full SLF4J wrapper --- pom.xml | 1 + proxy/pom.xml | 12 +- .../main/java/net/md_5/bungee/BungeeCord.java | 2 + slf4j/nb-configuration.xml | 31 + slf4j/pom.xml | 35 + .../org/slf4j/impl/JDK14LoggerAdapter.java | 694 ++++++++++++++++++ .../org/slf4j/impl/JDK14LoggerFactory.java | 73 ++ .../org/slf4j/impl/StaticLoggerBinder.java | 80 ++ .../java/org/slf4j/impl/StaticMDCBinder.java | 68 ++ .../org/slf4j/impl/StaticMarkerBinder.java | 77 ++ 10 files changed, 1067 insertions(+), 6 deletions(-) create mode 100644 slf4j/nb-configuration.xml create mode 100644 slf4j/pom.xml create mode 100644 slf4j/src/main/java/org/slf4j/impl/JDK14LoggerAdapter.java create mode 100644 slf4j/src/main/java/org/slf4j/impl/JDK14LoggerFactory.java create mode 100644 slf4j/src/main/java/org/slf4j/impl/StaticLoggerBinder.java create mode 100644 slf4j/src/main/java/org/slf4j/impl/StaticMDCBinder.java create mode 100644 slf4j/src/main/java/org/slf4j/impl/StaticMarkerBinder.java diff --git a/pom.xml b/pom.xml index 4305537d..8b5feae5 100644 --- a/pom.xml +++ b/pom.xml @@ -41,6 +41,7 @@ protocol proxy query + slf4j native diff --git a/proxy/pom.xml b/proxy/pom.xml index 61fb794d..086b9e79 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -79,6 +79,12 @@ ${project.version} compile + + net.md-5 + bungeecord-slf4j + ${project.version} + compile + net.sf.jopt-simple jopt-simple @@ -110,12 +116,6 @@ 1.6.2 compile - - org.slf4j - slf4j-jdk14 - 1.7.30 - compile - diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java index c04c3e8e..f80c0486 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -95,6 +95,7 @@ import net.md_5.bungee.query.RemoteQuery; import net.md_5.bungee.scheduler.BungeeScheduler; import net.md_5.bungee.util.CaseInsensitiveMap; import org.fusesource.jansi.AnsiConsole; +import org.slf4j.impl.JDK14LoggerFactory; /** * Main BungeeCord proxy class. @@ -215,6 +216,7 @@ public class BungeeCord extends ProxyServer consoleReader.addCompleter( new ConsoleCommandCompleter( this ) ); logger = new BungeeLogger( "BungeeCord", "proxy.log", consoleReader ); + JDK14LoggerFactory.LOGGER = logger; System.setErr( new PrintStream( new LoggingOutputStream( logger, Level.SEVERE ), true ) ); System.setOut( new PrintStream( new LoggingOutputStream( logger, Level.INFO ), true ) ); diff --git a/slf4j/nb-configuration.xml b/slf4j/nb-configuration.xml new file mode 100644 index 00000000..7e465924 --- /dev/null +++ b/slf4j/nb-configuration.xml @@ -0,0 +1,31 @@ + + + + + + project + NEW_LINE + NEW_LINE + NEW_LINE + true + true + true + true + true + true + true + true + true + true + + diff --git a/slf4j/pom.xml b/slf4j/pom.xml new file mode 100644 index 00000000..e7f19178 --- /dev/null +++ b/slf4j/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + + net.md-5 + bungeecord-parent + 1.16-R0.5-SNAPSHOT + ../pom.xml + + + net.md-5 + bungeecord-slf4j + 1.16-R0.5-SNAPSHOT + jar + + BungeeCord-SLF4J + Wrapper over SLF4J for BungeeCord purposes. + + + true + true + true + + + + + org.slf4j + slf4j-api + 1.7.30 + compile + + + diff --git a/slf4j/src/main/java/org/slf4j/impl/JDK14LoggerAdapter.java b/slf4j/src/main/java/org/slf4j/impl/JDK14LoggerAdapter.java new file mode 100644 index 00000000..7cfafc88 --- /dev/null +++ b/slf4j/src/main/java/org/slf4j/impl/JDK14LoggerAdapter.java @@ -0,0 +1,694 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import java.util.logging.Level; +import java.util.logging.LogRecord; + +import org.slf4j.Logger; +import org.slf4j.Marker; +import org.slf4j.event.EventConstants; +import org.slf4j.event.LoggingEvent; +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MarkerIgnoringBase; +import org.slf4j.helpers.MessageFormatter; +import org.slf4j.spi.LocationAwareLogger; + +/** + * A wrapper over {@link java.util.logging.Logger java.util.logging.Logger} in + * conformity with the {@link Logger} interface. Note that the logging levels + * mentioned in this class refer to those defined in the java.util.logging + * package. + * + * @author Ceki Gülcü + * @author Peter Royal + */ +public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements LocationAwareLogger { + + private static final long serialVersionUID = -8053026990503422791L; + + transient final java.util.logging.Logger logger; + + // WARN: JDK14LoggerAdapter constructor should have only package access so + // that only JDK14LoggerFactory be able to create one. + JDK14LoggerAdapter(java.util.logging.Logger logger) { + this.logger = logger; + this.name = logger.getName(); + } + + /** + * Is this logger instance enabled for the FINEST level? + * + * @return True if this Logger is enabled for level FINEST, false otherwise. + */ + public boolean isTraceEnabled() { + return logger.isLoggable(Level.FINEST); + } + + /** + * Log a message object at level FINEST. + * + * @param msg + * - the message object to be logged + */ + public void trace(String msg) { + if (logger.isLoggable(Level.FINEST)) { + log(SELF, Level.FINEST, msg, null); + } + } + + /** + * Log a message at level FINEST according to the specified format and + * argument. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for level FINEST. + *

+ * + * @param format + * the format string + * @param arg + * the argument + */ + public void trace(String format, Object arg) { + if (logger.isLoggable(Level.FINEST)) { + FormattingTuple ft = MessageFormatter.format(format, arg); + log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level FINEST according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the FINEST level. + *

+ * + * @param format + * the format string + * @param arg1 + * the first argument + * @param arg2 + * the second argument + */ + public void trace(String format, Object arg1, Object arg2) { + if (logger.isLoggable(Level.FINEST)) { + FormattingTuple ft = MessageFormatter.format(format, arg1, arg2); + log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level FINEST according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the FINEST level. + *

+ * + * @param format + * the format string + * @param argArray + * an array of arguments + */ + public void trace(String format, Object... argArray) { + if (logger.isLoggable(Level.FINEST)) { + FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); + log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log an exception (throwable) at level FINEST with an accompanying message. + * + * @param msg + * the message accompanying the exception + * @param t + * the exception (throwable) to log + */ + public void trace(String msg, Throwable t) { + if (logger.isLoggable(Level.FINEST)) { + log(SELF, Level.FINEST, msg, t); + } + } + + /** + * Is this logger instance enabled for the FINE level? + * + * @return True if this Logger is enabled for level FINE, false otherwise. + */ + public boolean isDebugEnabled() { + return logger.isLoggable(Level.FINE); + } + + /** + * Log a message object at level FINE. + * + * @param msg + * - the message object to be logged + */ + public void debug(String msg) { + if (logger.isLoggable(Level.FINE)) { + log(SELF, Level.FINE, msg, null); + } + } + + /** + * Log a message at level FINE according to the specified format and argument. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for level FINE. + *

+ * + * @param format + * the format string + * @param arg + * the argument + */ + public void debug(String format, Object arg) { + if (logger.isLoggable(Level.FINE)) { + FormattingTuple ft = MessageFormatter.format(format, arg); + log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level FINE according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the FINE level. + *

+ * + * @param format + * the format string + * @param arg1 + * the first argument + * @param arg2 + * the second argument + */ + public void debug(String format, Object arg1, Object arg2) { + if (logger.isLoggable(Level.FINE)) { + FormattingTuple ft = MessageFormatter.format(format, arg1, arg2); + log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level FINE according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the FINE level. + *

+ * + * @param format + * the format string + * @param argArray + * an array of arguments + */ + public void debug(String format, Object... argArray) { + if (logger.isLoggable(Level.FINE)) { + FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); + log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log an exception (throwable) at level FINE with an accompanying message. + * + * @param msg + * the message accompanying the exception + * @param t + * the exception (throwable) to log + */ + public void debug(String msg, Throwable t) { + if (logger.isLoggable(Level.FINE)) { + log(SELF, Level.FINE, msg, t); + } + } + + /** + * Is this logger instance enabled for the INFO level? + * + * @return True if this Logger is enabled for the INFO level, false otherwise. + */ + public boolean isInfoEnabled() { + return logger.isLoggable(Level.INFO); + } + + /** + * Log a message object at the INFO level. + * + * @param msg + * - the message object to be logged + */ + public void info(String msg) { + if (logger.isLoggable(Level.INFO)) { + log(SELF, Level.INFO, msg, null); + } + } + + /** + * Log a message at level INFO according to the specified format and argument. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the INFO level. + *

+ * + * @param format + * the format string + * @param arg + * the argument + */ + public void info(String format, Object arg) { + if (logger.isLoggable(Level.INFO)) { + FormattingTuple ft = MessageFormatter.format(format, arg); + log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at the INFO level according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the INFO level. + *

+ * + * @param format + * the format string + * @param arg1 + * the first argument + * @param arg2 + * the second argument + */ + public void info(String format, Object arg1, Object arg2) { + if (logger.isLoggable(Level.INFO)) { + FormattingTuple ft = MessageFormatter.format(format, arg1, arg2); + log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level INFO according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the INFO level. + *

+ * + * @param format + * the format string + * @param argArray + * an array of arguments + */ + public void info(String format, Object... argArray) { + if (logger.isLoggable(Level.INFO)) { + FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); + log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log an exception (throwable) at the INFO level with an accompanying + * message. + * + * @param msg + * the message accompanying the exception + * @param t + * the exception (throwable) to log + */ + public void info(String msg, Throwable t) { + if (logger.isLoggable(Level.INFO)) { + log(SELF, Level.INFO, msg, t); + } + } + + /** + * Is this logger instance enabled for the WARNING level? + * + * @return True if this Logger is enabled for the WARNING level, false + * otherwise. + */ + public boolean isWarnEnabled() { + return logger.isLoggable(Level.WARNING); + } + + /** + * Log a message object at the WARNING level. + * + * @param msg + * - the message object to be logged + */ + public void warn(String msg) { + if (logger.isLoggable(Level.WARNING)) { + log(SELF, Level.WARNING, msg, null); + } + } + + /** + * Log a message at the WARNING level according to the specified format and + * argument. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the WARNING level. + *

+ * + * @param format + * the format string + * @param arg + * the argument + */ + public void warn(String format, Object arg) { + if (logger.isLoggable(Level.WARNING)) { + FormattingTuple ft = MessageFormatter.format(format, arg); + log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at the WARNING level according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the WARNING level. + *

+ * + * @param format + * the format string + * @param arg1 + * the first argument + * @param arg2 + * the second argument + */ + public void warn(String format, Object arg1, Object arg2) { + if (logger.isLoggable(Level.WARNING)) { + FormattingTuple ft = MessageFormatter.format(format, arg1, arg2); + log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level WARNING according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the WARNING level. + *

+ * + * @param format + * the format string + * @param argArray + * an array of arguments + */ + public void warn(String format, Object... argArray) { + if (logger.isLoggable(Level.WARNING)) { + FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); + log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log an exception (throwable) at the WARNING level with an accompanying + * message. + * + * @param msg + * the message accompanying the exception + * @param t + * the exception (throwable) to log + */ + public void warn(String msg, Throwable t) { + if (logger.isLoggable(Level.WARNING)) { + log(SELF, Level.WARNING, msg, t); + } + } + + /** + * Is this logger instance enabled for level SEVERE? + * + * @return True if this Logger is enabled for level SEVERE, false otherwise. + */ + public boolean isErrorEnabled() { + return logger.isLoggable(Level.SEVERE); + } + + /** + * Log a message object at the SEVERE level. + * + * @param msg + * - the message object to be logged + */ + public void error(String msg) { + if (logger.isLoggable(Level.SEVERE)) { + log(SELF, Level.SEVERE, msg, null); + } + } + + /** + * Log a message at the SEVERE level according to the specified format and + * argument. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the SEVERE level. + *

+ * + * @param format + * the format string + * @param arg + * the argument + */ + public void error(String format, Object arg) { + if (logger.isLoggable(Level.SEVERE)) { + FormattingTuple ft = MessageFormatter.format(format, arg); + log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at the SEVERE level according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the SEVERE level. + *

+ * + * @param format + * the format string + * @param arg1 + * the first argument + * @param arg2 + * the second argument + */ + public void error(String format, Object arg1, Object arg2) { + if (logger.isLoggable(Level.SEVERE)) { + FormattingTuple ft = MessageFormatter.format(format, arg1, arg2); + log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level SEVERE according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the SEVERE level. + *

+ * + * @param format + * the format string + * @param arguments + * an array of arguments + */ + public void error(String format, Object... arguments) { + if (logger.isLoggable(Level.SEVERE)) { + FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); + log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log an exception (throwable) at the SEVERE level with an accompanying + * message. + * + * @param msg + * the message accompanying the exception + * @param t + * the exception (throwable) to log + */ + public void error(String msg, Throwable t) { + if (logger.isLoggable(Level.SEVERE)) { + log(SELF, Level.SEVERE, msg, t); + } + } + + /** + * Log the message at the specified level with the specified throwable if any. + * This method creates a LogRecord and fills in caller date before calling + * this instance's JDK14 logger. + * + * See bug report #13 for more details. + * + * @param level + * @param msg + * @param t + */ + private void log(String callerFQCN, Level level, String msg, Throwable t) { + // millis and thread are filled by the constructor + LogRecord record = new LogRecord(level, msg); + record.setLoggerName(getName()); + record.setThrown(t); + // Note: parameters in record are not set because SLF4J only + // supports a single formatting style + fillCallerData(callerFQCN, record); + logger.log(record); + } + + static String SELF = JDK14LoggerAdapter.class.getName(); + static String SUPER = MarkerIgnoringBase.class.getName(); + + /** + * Fill in caller data if possible. + * + * @param record + * The record to update + */ + final private void fillCallerData(String callerFQCN, LogRecord record) { + 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(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(SUPER))) { + found = i; + break; + } + } + + if (found != -1) { + 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()); + } + } + + public void log(Marker marker, String callerFQCN, int level, String message, Object[] argArray, Throwable t) { + Level julLevel = slf4jLevelIntToJULLevel(level); + // the logger.isLoggable check avoids the unconditional + // construction of location data for disabled log + // statements. As of 2008-07-31, callers of this method + // do not perform this check. See also + // http://jira.qos.ch/browse/SLF4J-81 + if (logger.isLoggable(julLevel)) { + log(callerFQCN, julLevel, message, t); + } + } + + private Level slf4jLevelIntToJULLevel(int slf4jLevelInt) { + Level julLevel; + switch (slf4jLevelInt) { + case LocationAwareLogger.TRACE_INT: + julLevel = Level.FINEST; + break; + case LocationAwareLogger.DEBUG_INT: + julLevel = Level.FINE; + break; + case LocationAwareLogger.INFO_INT: + julLevel = Level.INFO; + break; + case LocationAwareLogger.WARN_INT: + julLevel = Level.WARNING; + break; + case LocationAwareLogger.ERROR_INT: + julLevel = Level.SEVERE; + break; + default: + throw new IllegalStateException("Level number " + slf4jLevelInt + " is not recognized."); + } + return julLevel; + } + + /** + * @since 1.7.15 + */ + public void log(LoggingEvent event) { + Level julLevel = slf4jLevelIntToJULLevel(event.getLevel().toInt()); + if (logger.isLoggable(julLevel)) { + LogRecord record = eventToRecord(event, julLevel); + logger.log(record); + } + } + + private LogRecord eventToRecord(LoggingEvent event, Level julLevel) { + String format = event.getMessage(); + Object[] arguments = event.getArgumentArray(); + FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); + if (ft.getThrowable() != null && event.getThrowable() != null) { + throw new IllegalArgumentException("both last element in argument array and last argument are of type Throwable"); + } + + Throwable t = event.getThrowable(); + if (ft.getThrowable() != null) { + t = ft.getThrowable(); + throw new IllegalStateException("fix above code"); + } + + LogRecord record = new LogRecord(julLevel, ft.getMessage()); + record.setLoggerName(event.getLoggerName()); + record.setMillis(event.getTimeStamp()); + record.setSourceClassName(EventConstants.NA_SUBST); + record.setSourceMethodName(EventConstants.NA_SUBST); + + record.setThrown(t); + return record; + } +} diff --git a/slf4j/src/main/java/org/slf4j/impl/JDK14LoggerFactory.java b/slf4j/src/main/java/org/slf4j/impl/JDK14LoggerFactory.java new file mode 100644 index 00000000..2d6eaaf8 --- /dev/null +++ b/slf4j/src/main/java/org/slf4j/impl/JDK14LoggerFactory.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import org.slf4j.Logger; +import org.slf4j.ILoggerFactory; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * JDK14LoggerFactory is an implementation of {@link ILoggerFactory} returning + * the appropriately named {@link JDK14LoggerAdapter} instance. + * + * @author Ceki Gülcü + */ +public class JDK14LoggerFactory implements ILoggerFactory { + + // key: name (String), value: a JDK14LoggerAdapter; + ConcurrentMap loggerMap; + public static java.util.logging.Logger LOGGER; // BungeeCord + + public JDK14LoggerFactory() { + loggerMap = new ConcurrentHashMap(); + // ensure jul initialization. see SLF4J-359 + // note that call to java.util.logging.LogManager.getLogManager() fails on the Google App Engine platform. See SLF4J-363 + java.util.logging.Logger.getLogger(""); + } + + /* + * (non-Javadoc) + * + * @see org.slf4j.ILoggerFactory#getLogger(java.lang.String) + */ + public Logger getLogger(String name) { + // the root logger is called "" in JUL + if (name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME)) { + name = ""; + } + + Logger slf4jLogger = loggerMap.get(name); + if (slf4jLogger != null) + return slf4jLogger; + else { + java.util.logging.Logger julLogger = LOGGER; // BungeeCord - TODO: per-plugin loggers + Logger newInstance = new JDK14LoggerAdapter(julLogger); + Logger oldInstance = loggerMap.putIfAbsent(name, newInstance); + return oldInstance == null ? newInstance : oldInstance; + } + } +} diff --git a/slf4j/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/slf4j/src/main/java/org/slf4j/impl/StaticLoggerBinder.java new file mode 100644 index 00000000..ebf8ae11 --- /dev/null +++ b/slf4j/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import org.slf4j.ILoggerFactory; +import org.slf4j.LoggerFactory; +import org.slf4j.spi.LoggerFactoryBinder; + +/** + * The binding of {@link LoggerFactory} class with an actual instance of + * {@link ILoggerFactory} is performed using information returned by this class. + * + * @author Ceki Gülcü + */ +public class StaticLoggerBinder implements LoggerFactoryBinder { + + /** + * The unique instance of this class. + * + */ + private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder(); + + /** + * Return the singleton of this class. + * + * @return the StaticLoggerBinder singleton + */ + public static final StaticLoggerBinder getSingleton() { + return SINGLETON; + } + + /** + * Declare the version of the SLF4J API this implementation is compiled against. + * The value of this field is modified with each major release. + */ + // to avoid constant folding by the compiler, this field must *not* be final + public static String REQUESTED_API_VERSION = "1.6.99"; // !final + + private static final String loggerFactoryClassStr = org.slf4j.impl.JDK14LoggerFactory.class.getName(); + + /** The ILoggerFactory instance returned by the {@link #getLoggerFactory} method + * should always be the same object + */ + private final ILoggerFactory loggerFactory; + + private StaticLoggerBinder() { + // Note: JCL gets substituted at build time by an appropriate Ant task + loggerFactory = new org.slf4j.impl.JDK14LoggerFactory(); + } + + public ILoggerFactory getLoggerFactory() { + return loggerFactory; + } + + public String getLoggerFactoryClassStr() { + return loggerFactoryClassStr; + } +} diff --git a/slf4j/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/slf4j/src/main/java/org/slf4j/impl/StaticMDCBinder.java new file mode 100644 index 00000000..0a1dcb4c --- /dev/null +++ b/slf4j/src/main/java/org/slf4j/impl/StaticMDCBinder.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import org.slf4j.helpers.BasicMDCAdapter; +import org.slf4j.spi.MDCAdapter; + +/** + * This implementation is bound to {@link BasicMDCAdapter}. + * + * @author Ceki Gülcü + */ +public class StaticMDCBinder { + + /** + * The unique instance of this class. + */ + public static final StaticMDCBinder SINGLETON = new StaticMDCBinder(); + + private StaticMDCBinder() { + } + + /** + * Return the singleton of this class. + * + * @return the StaticMDCBinder singleton + * @since 1.7.14 + */ + public static final StaticMDCBinder getSingleton() { + return SINGLETON; + } + + /** + * Currently this method always returns an instance of + * {@link BasicMDCAdapter}. + */ + public MDCAdapter getMDCA() { + // note that this method is invoked only from within the static initializer of + // the org.slf4j.MDC class. + return new BasicMDCAdapter(); + } + + public String getMDCAdapterClassStr() { + return BasicMDCAdapter.class.getName(); + } +} diff --git a/slf4j/src/main/java/org/slf4j/impl/StaticMarkerBinder.java b/slf4j/src/main/java/org/slf4j/impl/StaticMarkerBinder.java new file mode 100644 index 00000000..21a48df6 --- /dev/null +++ b/slf4j/src/main/java/org/slf4j/impl/StaticMarkerBinder.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import org.slf4j.IMarkerFactory; +import org.slf4j.MarkerFactory; +import org.slf4j.helpers.BasicMarkerFactory; +import org.slf4j.spi.MarkerFactoryBinder; + +/** + * + * The binding of {@link MarkerFactory} class with an actual instance of + * {@link IMarkerFactory} is performed using information returned by this class. + * + * @author Ceki Gülcü + */ +public class StaticMarkerBinder implements MarkerFactoryBinder { + + /** + * The unique instance of this class. + */ + public static final StaticMarkerBinder SINGLETON = new StaticMarkerBinder(); + + final IMarkerFactory markerFactory = new BasicMarkerFactory(); + + private StaticMarkerBinder() { + } + + /** + * Return the singleton of this class. + * + * @return the StaticMarkerBinder singleton + * @since 1.7.14 + */ + public static StaticMarkerBinder getSingleton() { + return SINGLETON; + } + + /** + * Currently this method always returns an instance of + * {@link BasicMarkerFactory}. + */ + public IMarkerFactory getMarkerFactory() { + return markerFactory; + } + + /** + * Currently, this method returns the class name of + * {@link BasicMarkerFactory}. + */ + public String getMarkerFactoryClassStr() { + return BasicMarkerFactory.class.getName(); + } + +}