diff --git a/LoggerProxy.class b/LoggerProxy.class new file mode 100644 index 0000000..5593a9e Binary files /dev/null and b/LoggerProxy.class differ diff --git a/logger/build.gradle.kts b/logger/build.gradle.kts new file mode 100644 index 0000000..dfaacd9 --- /dev/null +++ b/logger/build.gradle.kts @@ -0,0 +1,8 @@ +dependencies { + api(project(":")) + + compileOnly("org.apache.logging.log4j:log4j-api:2.23.1") + // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl + testImplementation("org.apache.logging.log4j:log4j-slf4j-impl:2.23.1") + +} \ No newline at end of file diff --git a/logger/src/main/java/org/inksnow/cputil/logger/AuroraLogger.java b/logger/src/main/java/org/inksnow/cputil/logger/AuroraLogger.java new file mode 100644 index 0000000..0ec86b0 --- /dev/null +++ b/logger/src/main/java/org/inksnow/cputil/logger/AuroraLogger.java @@ -0,0 +1,331 @@ +package org.inksnow.cputil.logger; + +import org.slf4j.Logger; +import org.slf4j.Marker; + +public class AuroraLogger implements Logger { + public static final String UNMAPPED_SLF4J_PACKAGE_NAME = new String(new char[]{ + 'o', 'r', 'g', '.', 's', 'l', 'f', '4', 'j' + }); + public static final String SLF4J_PACKAGE_NAME = Logger.class.getName().substring(0, + Logger.class.getName().lastIndexOf('.') + ); + /* package-private */ final String name; + private final AuroraLoggerFactory factory; + /* package-private */ Logger delegate; + /* package-private */ int version = -1; + + public AuroraLogger(AuroraLoggerFactory factory, String name) { + this.factory = factory; + this.name = name; + } + + private Logger delegate() { + return factory.updateDelegate(this); + } + + @Override + public String getName() { + return delegate().getName(); + } + + @Override + public boolean isTraceEnabled() { + return delegate().isTraceEnabled(); + } + + @Override + public void trace(String msg) { + delegate().trace(msg); + } + + @Override + public void trace(String format, Object arg) { + delegate().trace(format, arg); + } + + @Override + public void trace(String format, Object arg1, Object arg2) { + delegate().trace(format, arg1, arg2); + } + + @Override + public void trace(String format, Object... arguments) { + delegate().trace(format, arguments); + } + + @Override + public void trace(String msg, Throwable t) { + delegate().trace(msg, t); + } + + @Override + public boolean isTraceEnabled(Marker marker) { + return delegate().isTraceEnabled(marker); + } + + @Override + public void trace(Marker marker, String msg) { + delegate().trace(marker, msg); + } + + @Override + public void trace(Marker marker, String format, Object arg) { + delegate().trace(marker, format, arg); + } + + @Override + public void trace(Marker marker, String format, Object arg1, Object arg2) { + delegate().trace(marker, format, arg1, arg2); + } + + @Override + public void trace(Marker marker, String format, Object... argArray) { + delegate().trace(marker, format, argArray); + } + + @Override + public void trace(Marker marker, String msg, Throwable t) { + delegate().trace(marker, msg, t); + } + + @Override + public boolean isDebugEnabled() { + return delegate().isDebugEnabled(); + } + + @Override + public void debug(String msg) { + delegate().debug(msg); + } + + @Override + public void debug(String format, Object arg) { + delegate().debug(format, arg); + } + + @Override + public void debug(String format, Object arg1, Object arg2) { + delegate().debug(format, arg1, arg2); + } + + @Override + public void debug(String format, Object... arguments) { + delegate().debug(format, arguments); + } + + @Override + public void debug(String msg, Throwable t) { + delegate().debug(msg, t); + } + + @Override + public boolean isDebugEnabled(Marker marker) { + return delegate().isDebugEnabled(marker); + } + + @Override + public void debug(Marker marker, String msg) { + delegate().debug(marker, msg); + } + + @Override + public void debug(Marker marker, String format, Object arg) { + delegate().debug(marker, format, arg); + } + + @Override + public void debug(Marker marker, String format, Object arg1, Object arg2) { + delegate().debug(marker, format, arg1, arg2); + } + + @Override + public void debug(Marker marker, String format, Object... arguments) { + delegate().debug(marker, format, arguments); + } + + @Override + public void debug(Marker marker, String msg, Throwable t) { + delegate().debug(marker, msg, t); + } + + @Override + public boolean isInfoEnabled() { + return delegate().isInfoEnabled(); + } + + @Override + public void info(String msg) { + delegate().info(msg); + } + + @Override + public void info(String format, Object arg) { + delegate().info(format, arg); + } + + @Override + public void info(String format, Object arg1, Object arg2) { + delegate().info(format, arg1, arg2); + } + + @Override + public void info(String format, Object... arguments) { + delegate().info(format, arguments); + } + + @Override + public void info(String msg, Throwable t) { + delegate().info(msg, t); + } + + @Override + public boolean isInfoEnabled(Marker marker) { + return delegate().isInfoEnabled(marker); + } + + @Override + public void info(Marker marker, String msg) { + delegate().info(marker, msg); + } + + @Override + public void info(Marker marker, String format, Object arg) { + delegate().info(marker, format, arg); + } + + @Override + public void info(Marker marker, String format, Object arg1, Object arg2) { + delegate().info(marker, format, arg1, arg2); + } + + @Override + public void info(Marker marker, String format, Object... arguments) { + delegate().info(marker, format, arguments); + } + + @Override + public void info(Marker marker, String msg, Throwable t) { + delegate().info(marker, msg, t); + } + + @Override + public boolean isWarnEnabled() { + return delegate().isWarnEnabled(); + } + + @Override + public void warn(String msg) { + delegate().warn(msg); + } + + @Override + public void warn(String format, Object arg) { + delegate().warn(format, arg); + } + + @Override + public void warn(String format, Object... arguments) { + delegate().warn(format, arguments); + } + + @Override + public void warn(String format, Object arg1, Object arg2) { + delegate().warn(format, arg1, arg2); + } + + @Override + public void warn(String msg, Throwable t) { + delegate().warn(msg, t); + } + + @Override + public boolean isWarnEnabled(Marker marker) { + return delegate().isWarnEnabled(marker); + } + + @Override + public void warn(Marker marker, String msg) { + delegate().warn(marker, msg); + } + + @Override + public void warn(Marker marker, String format, Object arg) { + delegate().warn(marker, format, arg); + } + + @Override + public void warn(Marker marker, String format, Object arg1, Object arg2) { + delegate().warn(marker, format, arg1, arg2); + } + + @Override + public void warn(Marker marker, String format, Object... arguments) { + delegate().warn(marker, format, arguments); + } + + @Override + public void warn(Marker marker, String msg, Throwable t) { + delegate().warn(marker, msg, t); + } + + @Override + public boolean isErrorEnabled() { + return delegate().isErrorEnabled(); + } + + @Override + public void error(String msg) { + delegate().error(msg); + } + + @Override + public void error(String format, Object arg) { + delegate().error(format, arg); + } + + @Override + public void error(String format, Object arg1, Object arg2) { + delegate().error(format, arg1, arg2); + } + + @Override + public void error(String format, Object... arguments) { + delegate().error(format, arguments); + } + + @Override + public void error(String msg, Throwable t) { + delegate().error(msg, t); + } + + @Override + public boolean isErrorEnabled(Marker marker) { + return delegate().isErrorEnabled(marker); + } + + @Override + public void error(Marker marker, String msg) { + delegate().error(marker, msg); + } + + @Override + public void error(Marker marker, String format, Object arg) { + delegate().error(marker, format, arg); + } + + @Override + public void error(Marker marker, String format, Object arg1, Object arg2) { + delegate().error(marker, format, arg1, arg2); + } + + @Override + public void error(Marker marker, String format, Object... arguments) { + delegate().error(marker, format, arguments); + } + + @Override + public void error(Marker marker, String msg, Throwable t) { + delegate().error(marker, msg, t); + } +} diff --git a/logger/src/main/java/org/inksnow/cputil/logger/AuroraLoggerFactory.java b/logger/src/main/java/org/inksnow/cputil/logger/AuroraLoggerFactory.java new file mode 100644 index 0000000..7b6d87c --- /dev/null +++ b/logger/src/main/java/org/inksnow/cputil/logger/AuroraLoggerFactory.java @@ -0,0 +1,69 @@ +package org.inksnow.cputil.logger; + +import org.inksnow.cputil.logger.impl.jul.JulLoggerFactory; +import org.inksnow.cputil.logger.impl.log4j2.Log4j2LoggerFactory; +import org.inksnow.cputil.logger.impl.parent.AuroraParentLogger; +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; + +public class AuroraLoggerFactory implements ILoggerFactory { + private static AuroraLoggerFactory INSTANCE; + + private ILoggerFactory provider; + private int currentVersion = 0; + + public AuroraLoggerFactory() { + if (INSTANCE != null) { + throw new IllegalStateException("AuroraLoggerFactory is a singleton"); + } + INSTANCE = this; + this.provider = selectDefaultProvider(); + } + + public static AuroraLoggerFactory instance() { + return INSTANCE; + } + + private ILoggerFactory selectDefaultProvider() { + try { + Class.forName(AuroraLogger.UNMAPPED_SLF4J_PACKAGE_NAME + ".Logger", false, Logger.class.getClassLoader()); + + if (!Logger.class.getName().equals(AuroraLogger.UNMAPPED_SLF4J_PACKAGE_NAME + ".Logger")) { + return new AuroraParentLogger(false); + } + } catch (ClassNotFoundException e) { + // + } + + try { + Class.forName("org.apache.logging.log4j.Logger", false, Logger.class.getClassLoader()); + return new Log4j2LoggerFactory(); + } catch (ClassNotFoundException e) { + // + } + + return new JulLoggerFactory(); + } + + public void setProvider(ILoggerFactory provider) { + if (this.provider != provider) { + this.provider = provider; + currentVersion++; + } + } + + @Override + public Logger getLogger(String name) { + return new AuroraLogger(this, name); + } + + public Logger updateDelegate(AuroraLogger auroraLogger) { + if (auroraLogger.version != currentVersion) { + Logger newLogger = provider.getLogger(auroraLogger.name); + auroraLogger.version = currentVersion; + auroraLogger.delegate = newLogger; + return newLogger; + } + return auroraLogger.delegate; + } +} diff --git a/logger/src/main/java/org/inksnow/cputil/logger/impl/jul/JulLoggerAdapter.java b/logger/src/main/java/org/inksnow/cputil/logger/impl/jul/JulLoggerAdapter.java new file mode 100644 index 0000000..b183c4e --- /dev/null +++ b/logger/src/main/java/org/inksnow/cputil/logger/impl/jul/JulLoggerAdapter.java @@ -0,0 +1,571 @@ +package org.inksnow.cputil.logger.impl.jul; + +import org.slf4j.Logger; +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; + +import java.util.logging.Level; +import java.util.logging.LogRecord; + +public final class JulLoggerAdapter extends MarkerIgnoringBase implements Logger { + static String SELF = JulLoggerAdapter.class.getName(); + static String SUPER = MarkerIgnoringBase.class.getName(); + transient final java.util.logging.Logger logger; + + // WARN: JDK14LoggerAdapter constructor should have only package access so + // that only JDK14LoggerFactory be able to create one. + JulLoggerAdapter(java.util.logging.Logger logger) { + this.logger = logger; + this.name = logger.getName(); + } + + public boolean isTraceEnabled() { + return logger.isLoggable(Level.FINEST); + } + + public void trace(String msg) { + if (logger.isLoggable(Level.FINEST)) { + log(SELF, Level.FINEST, msg, null); + } + } + + 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);
+ }
+
+ /**
+ * 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());
+ }
+ }
+
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/logger/src/main/java/org/inksnow/cputil/logger/impl/jul/JulLoggerFactory.java b/logger/src/main/java/org/inksnow/cputil/logger/impl/jul/JulLoggerFactory.java
new file mode 100644
index 0000000..d76b8e0
--- /dev/null
+++ b/logger/src/main/java/org/inksnow/cputil/logger/impl/jul/JulLoggerFactory.java
@@ -0,0 +1,19 @@
+package org.inksnow.cputil.logger.impl.jul;
+
+import org.slf4j.ILoggerFactory;
+import org.slf4j.Logger;
+
+public class JulLoggerFactory implements ILoggerFactory {
+ public JulLoggerFactory() {
+ java.util.logging.Logger.getLogger("");
+ }
+
+ public Logger getLogger(String name) {
+ // the root logger is called "" in JUL
+ if (name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME)) {
+ name = "";
+ }
+
+ return new JulLoggerAdapter(java.util.logging.Logger.getLogger(name));
+ }
+}
\ No newline at end of file
diff --git a/logger/src/main/java/org/inksnow/cputil/logger/impl/log4j2/Log4j2Logger.java b/logger/src/main/java/org/inksnow/cputil/logger/impl/log4j2/Log4j2Logger.java
new file mode 100644
index 0000000..829920c
--- /dev/null
+++ b/logger/src/main/java/org/inksnow/cputil/logger/impl/log4j2/Log4j2Logger.java
@@ -0,0 +1,173 @@
+package org.inksnow.cputil.logger.impl.log4j2;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.spi.ExtendedLogger;
+import org.slf4j.Logger;
+import org.slf4j.helpers.MarkerIgnoringBase;
+
+public class Log4j2Logger extends MarkerIgnoringBase implements Logger {
+
+ public static final String FQCN = Log4j2Logger.class.getName();
+ private final String name;
+ private transient ExtendedLogger logger;
+
+ public Log4j2Logger(final ExtendedLogger logger, final String name) {
+ this.logger = logger;
+ this.name = name;
+ }
+
+ @Override
+ public void trace(final String format) {
+ logger.logIfEnabled(FQCN, Level.TRACE, null, format);
+ }
+
+ @Override
+ public void trace(final String format, final Object o) {
+ logger.logIfEnabled(FQCN, Level.TRACE, null, format, o);
+ }
+
+ @Override
+ public void trace(final String format, final Object arg1, final Object arg2) {
+ logger.logIfEnabled(FQCN, Level.TRACE, null, format, arg1, arg2);
+ }
+
+ @Override
+ public void trace(final String format, final Object... args) {
+ logger.logIfEnabled(FQCN, Level.TRACE, null, format, args);
+ }
+
+ @Override
+ public void trace(final String format, final Throwable t) {
+ logger.logIfEnabled(FQCN, Level.TRACE, null, format, t);
+ }
+
+ @Override
+ public boolean isTraceEnabled() {
+ return logger.isEnabled(Level.TRACE, null, null);
+ }
+
+ @Override
+ public void debug(final String format) {
+ logger.logIfEnabled(FQCN, Level.DEBUG, null, format);
+ }
+
+ @Override
+ public void debug(final String format, final Object o) {
+ logger.logIfEnabled(FQCN, Level.DEBUG, null, format, o);
+ }
+
+ @Override
+ public void debug(final String format, final Object arg1, final Object arg2) {
+ logger.logIfEnabled(FQCN, Level.DEBUG, null, format, arg1, arg2);
+ }
+
+ @Override
+ public void debug(final String format, final Object... args) {
+ logger.logIfEnabled(FQCN, Level.DEBUG, null, format, args);
+ }
+
+ @Override
+ public void debug(final String format, final Throwable t) {
+ logger.logIfEnabled(FQCN, Level.DEBUG, null, format, t);
+ }
+
+ @Override
+ public boolean isDebugEnabled() {
+ return logger.isEnabled(Level.DEBUG, null, null);
+ }
+
+ @Override
+ public void info(final String format) {
+ logger.logIfEnabled(FQCN, Level.INFO, null, format);
+ }
+
+ @Override
+ public void info(final String format, final Object o) {
+ logger.logIfEnabled(FQCN, Level.INFO, null, format, o);
+ }
+
+ @Override
+ public void info(final String format, final Object arg1, final Object arg2) {
+ logger.logIfEnabled(FQCN, Level.INFO, null, format, arg1, arg2);
+ }
+
+ @Override
+ public void info(final String format, final Object... args) {
+ logger.logIfEnabled(FQCN, Level.INFO, null, format, args);
+ }
+
+ @Override
+ public void info(final String format, final Throwable t) {
+ logger.logIfEnabled(FQCN, Level.INFO, null, format, t);
+ }
+
+ @Override
+ public boolean isInfoEnabled() {
+ return logger.isEnabled(Level.INFO, null, null);
+ }
+
+ @Override
+ public void warn(final String format) {
+ logger.logIfEnabled(FQCN, Level.WARN, null, format);
+ }
+
+ @Override
+ public void warn(final String format, final Object o) {
+ logger.logIfEnabled(FQCN, Level.WARN, null, format, o);
+ }
+
+ @Override
+ public void warn(final String format, final Object arg1, final Object arg2) {
+ logger.logIfEnabled(FQCN, Level.WARN, null, format, arg1, arg2);
+ }
+
+ @Override
+ public void warn(final String format, final Object... args) {
+ logger.logIfEnabled(FQCN, Level.WARN, null, format, args);
+ }
+
+ @Override
+ public void warn(final String format, final Throwable t) {
+ logger.logIfEnabled(FQCN, Level.WARN, null, format, t);
+ }
+
+ @Override
+ public boolean isWarnEnabled() {
+ return logger.isEnabled(Level.WARN, null, null);
+ }
+
+ @Override
+ public void error(final String format) {
+ logger.logIfEnabled(FQCN, Level.ERROR, null, format);
+ }
+
+ @Override
+ public void error(final String format, final Object o) {
+ logger.logIfEnabled(FQCN, Level.ERROR, null, format, o);
+ }
+
+ @Override
+ public void error(final String format, final Object arg1, final Object arg2) {
+ logger.logIfEnabled(FQCN, Level.ERROR, null, format, arg1, arg2);
+ }
+
+ @Override
+ public void error(final String format, final Object... args) {
+ logger.logIfEnabled(FQCN, Level.ERROR, null, format, args);
+ }
+
+ @Override
+ public void error(final String format, final Throwable t) {
+ logger.logIfEnabled(FQCN, Level.ERROR, null, format, t);
+ }
+
+ @Override
+ public boolean isErrorEnabled() {
+ return logger.isEnabled(Level.ERROR, null, null);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+}
diff --git a/logger/src/main/java/org/inksnow/cputil/logger/impl/log4j2/Log4j2LoggerFactory.java b/logger/src/main/java/org/inksnow/cputil/logger/impl/log4j2/Log4j2LoggerFactory.java
new file mode 100644
index 0000000..8323e92
--- /dev/null
+++ b/logger/src/main/java/org/inksnow/cputil/logger/impl/log4j2/Log4j2LoggerFactory.java
@@ -0,0 +1,37 @@
+package org.inksnow.cputil.logger.impl.log4j2;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.spi.AbstractLoggerAdapter;
+import org.apache.logging.log4j.spi.LoggerContext;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.util.StackLocatorUtil;
+import org.inksnow.cputil.logger.AuroraLogger;
+import org.slf4j.ILoggerFactory;
+import org.slf4j.Logger;
+
+import java.util.function.Predicate;
+
+/**
+ * Log4j implementation of SLF4J ILoggerFactory interface.
+ */
+public class Log4j2LoggerFactory extends AbstractLoggerAdapter