add slf4j-reload4j module

Signed-off-by: Ceki Gulcu <ceki@qos.ch>
This commit is contained in:
Ceki Gulcu 2022-01-12 22:40:10 +01:00
parent 49f242400d
commit 0d2bd398f7
25 changed files with 1621 additions and 7 deletions

View File

@ -1,4 +1,4 @@
Copyright (c) 2004-2017 QOS.ch
Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland)
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining

View File

@ -43,6 +43,7 @@
<slf4j.api.minimum.compatible.version>1.6.0</slf4j.api.minimum.compatible.version>
<cal10n.version>0.8.1</cal10n.version>
<log4j.version>1.2.17</log4j.version>
<reload4j.version>1.2.18.0</reload4j.version>
<logback.version>1.0.13</logback.version>
<junit.version>4.12</junit.version>
<maven-site-plugin.version>3.3</maven-site-plugin.version>
@ -65,6 +66,7 @@
<module>slf4j-nop</module>
<module>slf4j-jdk14</module>
<module>slf4j-log4j12</module>
<module>slf4j-reload4j</module>
<module>slf4j-jcl</module>
<module>slf4j-android</module>
<module>slf4j-ext</module>
@ -107,6 +109,12 @@
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
<version>${reload4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.cal10n</groupId>
<artifactId>cal10n-api</artifactId>

View File

@ -1,4 +1,4 @@
Copyright (c) 2004-2007 QOS.ch
Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland)
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining

View File

@ -1,4 +1,4 @@
Copyright (c) 2004-2007 QOS.ch
Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland)
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining

View File

@ -1,4 +1,4 @@
Copyright (c) 2004-2007 QOS.ch
Copyright (c) 2004-2022 QOS.ch Sarl
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining

View File

@ -1,4 +1,4 @@
Copyright (c) 2004-2007 QOS.ch
Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland)
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining

View File

@ -1,4 +1,4 @@
Copyright (c) 2004-2007 QOS.ch
Copyright (c) 2004-2022 QOS.ch
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining

View File

@ -0,0 +1,24 @@
Copyright (c) 2004-2007 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.

41
slf4j-reload4j/pom.xml Executable file
View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.32-SNAPSHOT</version>
</parent>
<artifactId>slf4j-reload4j</artifactId>
<packaging>jar</packaging>
<name>SLF4J Reload4j Binding</name>
<description>SLF4J Reload4j Binding</description>
<url>http://reload4j.qos.ch</url>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<type>test-jar</type>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,617 @@
/**
* 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 static org.slf4j.event.EventConstants.NA_SUBST;
import java.io.Serializable;
import org.apache.log4j.Level;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.ThrowableInformation;
import org.slf4j.Logger;
import org.slf4j.Marker;
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 org.apache.log4j.Logger org.apache.log4j.Logger} in
* conforming to the {@link Logger} interface.
*
* <p>
* Note that the logging levels mentioned in this class refer to those defined
* in the <a
* href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/Level.html">
* <code>org.apache.log4j.Level</code></a> class.
*
* <p>
* The TRACE level was introduced in log4j version 1.2.12. In order to avoid
* crashing the host application, in the case the log4j version in use predates
* 1.2.12, the TRACE level will be mapped as DEBUG. See also <a
* href="http://jira.qos.ch/browse/SLF4J-59">SLF4J-59</a>.
*
* @author Ceki G&uuml;lc&uuml;
* @since 1.7.33
*/
public final class Reload4jLoggerAdapter extends MarkerIgnoringBase implements LocationAwareLogger, Serializable {
private static final long serialVersionUID = 6182834493563598289L;
final transient org.apache.log4j.Logger logger;
/**
* Following the pattern discussed in pages 162 through 168 of "The complete
* log4j manual".
*/
final static String FQCN = Reload4jLoggerAdapter.class.getName();
// WARN: Log4jLoggerAdapter constructor should have only package access so
// that only Log4jLoggerFactory be able to create one.
Reload4jLoggerAdapter(org.apache.log4j.Logger logger) {
this.logger = logger;
this.name = logger.getName();
}
/**
* Is this logger instance enabled for the TRACE level?
*
* @return True if this Logger is enabled for level TRACE, false otherwise.
*/
public boolean isTraceEnabled() {
return logger.isTraceEnabled();
}
/**
* Log a message object at level TRACE.
*
* @param msg
* - the message object to be logged
*/
public void trace(String msg) {
logger.log(FQCN, Level.TRACE, msg, null);
}
/**
* Log a message at level TRACE according to the specified format and
* argument.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for level TRACE.
* </p>
*
* @param format
* the format string
* @param arg
* the argument
*/
public void trace(String format, Object arg) {
if (isTraceEnabled()) {
FormattingTuple ft = MessageFormatter.format(format, arg);
logger.log(FQCN, Level.TRACE, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log a message at level TRACE according to the specified format and
* arguments.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the TRACE level.
* </p>
*
* @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 (isTraceEnabled()) {
FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
logger.log(FQCN, Level.TRACE, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log a message at level TRACE according to the specified format and
* arguments.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the TRACE level.
* </p>
*
* @param format
* the format string
* @param arguments
* an array of arguments
*/
public void trace(String format, Object... arguments) {
if (isTraceEnabled()) {
FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments);
logger.log(FQCN, Level.TRACE, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log an exception (throwable) at level TRACE 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) {
logger.log(FQCN, Level.TRACE, msg, t);
}
/**
* Is this logger instance enabled for the DEBUG level?
*
* @return True if this Logger is enabled for level DEBUG, false otherwise.
*/
public boolean isDebugEnabled() {
return logger.isDebugEnabled();
}
/**
* Log a message object at level DEBUG.
*
* @param msg
* - the message object to be logged
*/
public void debug(String msg) {
logger.log(FQCN, Level.DEBUG, msg, null);
}
/**
* Log a message at level DEBUG according to the specified format and
* argument.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for level DEBUG.
* </p>
*
* @param format
* the format string
* @param arg
* the argument
*/
public void debug(String format, Object arg) {
if (logger.isDebugEnabled()) {
FormattingTuple ft = MessageFormatter.format(format, arg);
logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log a message at level DEBUG according to the specified format and
* arguments.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the DEBUG level.
* </p>
*
* @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.isDebugEnabled()) {
FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log a message at level DEBUG according to the specified format and
* arguments.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the DEBUG level.
* </p>
*
* @param format
* the format string
* @param arguments an array of arguments
*/
public void debug(String format, Object... arguments) {
if (logger.isDebugEnabled()) {
FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments);
logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log an exception (throwable) at level DEBUG 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) {
logger.log(FQCN, Level.DEBUG, 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.isInfoEnabled();
}
/**
* Log a message object at the INFO level.
*
* @param msg
* - the message object to be logged
*/
public void info(String msg) {
logger.log(FQCN, Level.INFO, msg, null);
}
/**
* Log a message at level INFO according to the specified format and argument.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the INFO level.
* </p>
*
* @param format
* the format string
* @param arg
* the argument
*/
public void info(String format, Object arg) {
if (logger.isInfoEnabled()) {
FormattingTuple ft = MessageFormatter.format(format, arg);
logger.log(FQCN, Level.INFO, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log a message at the INFO level according to the specified format and
* arguments.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the INFO level.
* </p>
*
* @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.isInfoEnabled()) {
FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
logger.log(FQCN, Level.INFO, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log a message at level INFO according to the specified format and
* arguments.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the INFO level.
* </p>
*
* @param format
* the format string
* @param argArray
* an array of arguments
*/
public void info(String format, Object... argArray) {
if (logger.isInfoEnabled()) {
FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
logger.log(FQCN, 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) {
logger.log(FQCN, Level.INFO, msg, t);
}
/**
* Is this logger instance enabled for the WARN level?
*
* @return True if this Logger is enabled for the WARN level, false otherwise.
*/
public boolean isWarnEnabled() {
return logger.isEnabledFor(Level.WARN);
}
/**
* Log a message object at the WARN level.
*
* @param msg
* - the message object to be logged
*/
public void warn(String msg) {
logger.log(FQCN, Level.WARN, msg, null);
}
/**
* Log a message at the WARN level according to the specified format and
* argument.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the WARN level.
* </p>
*
* @param format
* the format string
* @param arg
* the argument
*/
public void warn(String format, Object arg) {
if (logger.isEnabledFor(Level.WARN)) {
FormattingTuple ft = MessageFormatter.format(format, arg);
logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log a message at the WARN level according to the specified format and
* arguments.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the WARN level.
* </p>
*
* @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.isEnabledFor(Level.WARN)) {
FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log a message at level WARN according to the specified format and
* arguments.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the WARN level.
* </p>
*
* @param format
* the format string
* @param argArray
* an array of arguments
*/
public void warn(String format, Object... argArray) {
if (logger.isEnabledFor(Level.WARN)) {
FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log an exception (throwable) at the WARN 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) {
logger.log(FQCN, Level.WARN, msg, t);
}
/**
* Is this logger instance enabled for level ERROR?
*
* @return True if this Logger is enabled for level ERROR, false otherwise.
*/
public boolean isErrorEnabled() {
return logger.isEnabledFor(Level.ERROR);
}
/**
* Log a message object at the ERROR level.
*
* @param msg
* - the message object to be logged
*/
public void error(String msg) {
logger.log(FQCN, Level.ERROR, msg, null);
}
/**
* Log a message at the ERROR level according to the specified format and
* argument.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the ERROR level.
* </p>
*
* @param format
* the format string
* @param arg
* the argument
*/
public void error(String format, Object arg) {
if (logger.isEnabledFor(Level.ERROR)) {
FormattingTuple ft = MessageFormatter.format(format, arg);
logger.log(FQCN, Level.ERROR, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log a message at the ERROR level according to the specified format and
* arguments.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the ERROR level.
* </p>
*
* @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.isEnabledFor(Level.ERROR)) {
FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
logger.log(FQCN, Level.ERROR, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log a message at level ERROR according to the specified format and
* arguments.
*
* <p>
* This form avoids superfluous object creation when the logger is disabled
* for the ERROR level.
* </p>
*
* @param format
* the format string
* @param argArray
* an array of arguments
*/
public void error(String format, Object... argArray) {
if (logger.isEnabledFor(Level.ERROR)) {
FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
logger.log(FQCN, Level.ERROR, ft.getMessage(), ft.getThrowable());
}
}
/**
* Log an exception (throwable) at the ERROR 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) {
logger.log(FQCN, Level.ERROR, msg, t);
}
public void log(Marker marker, String callerFQCN, int level, String msg, Object[] argArray, Throwable t) {
Level log4jLevel = toLog4jLevel(level);
logger.log(callerFQCN, log4jLevel, msg, t);
}
private Level toLog4jLevel(int level) {
Level log4jLevel;
switch (level) {
case LocationAwareLogger.TRACE_INT:
log4jLevel = Level.TRACE;
break;
case LocationAwareLogger.DEBUG_INT:
log4jLevel = Level.DEBUG;
break;
case LocationAwareLogger.INFO_INT:
log4jLevel = Level.INFO;
break;
case LocationAwareLogger.WARN_INT:
log4jLevel = Level.WARN;
break;
case LocationAwareLogger.ERROR_INT:
log4jLevel = Level.ERROR;
break;
default:
throw new IllegalStateException("Level number " + level + " is not recognized.");
}
return log4jLevel;
}
public void log(LoggingEvent event) {
Level log4jLevel = toLog4jLevel(event.getLevel().toInt());
if (!logger.isEnabledFor(log4jLevel))
return;
org.apache.log4j.spi.LoggingEvent log4jevent = toLog4jEvent(event, log4jLevel);
logger.callAppenders(log4jevent);
}
private org.apache.log4j.spi.LoggingEvent toLog4jEvent(LoggingEvent event, Level log4jLevel) {
FormattingTuple ft = MessageFormatter.format(event.getMessage(), event.getArgumentArray(), event.getThrowable());
LocationInfo locationInfo = new LocationInfo(NA_SUBST, NA_SUBST, NA_SUBST, "0");
ThrowableInformation ti = null;
Throwable t = ft.getThrowable();
if (t != null)
ti = new ThrowableInformation(t);
org.apache.log4j.spi.LoggingEvent log4jEvent = new org.apache.log4j.spi.LoggingEvent(FQCN, logger, event.getTimeStamp(), log4jLevel, ft.getMessage(),
event.getThreadName(), ti, null, locationInfo, null);
return log4jEvent;
}
}

View File

@ -0,0 +1,91 @@
/**
* 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.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.log4j.LogManager;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.helpers.Util;
/**
* Log4jLoggerFactory is an implementation of {@link ILoggerFactory} returning
* the appropriate named {@link Reload4jLoggerAdapter} instance.
*
* @author Ceki G&uuml;lc&uuml;
* @since 1.7.33
*/
public class Reload4jLoggerFactory implements ILoggerFactory {
private static final String LOG4J_DELEGATION_LOOP_URL = "http://www.slf4j.org/codes.html#log4jDelegationLoop";
// check for delegation loops
static {
try {
Class.forName("org.apache.log4j.Log4jLoggerFactory");
String part1 = "Detected both log4j-over-slf4j.jar AND bound slf4j-reload4j.jar on the class path, preempting StackOverflowError. ";
String part2 = "See also " + LOG4J_DELEGATION_LOOP_URL + " for more details.";
Util.report(part1);
Util.report(part2);
throw new IllegalStateException(part1 + part2);
} catch (ClassNotFoundException e) {
// this is the good case
}
}
// key: name (String), value: a Log4jLoggerAdapter;
ConcurrentMap<String, Logger> loggerMap;
public Reload4jLoggerFactory() {
loggerMap = new ConcurrentHashMap<String, Logger>();
// force log4j to initialize
org.apache.log4j.LogManager.getRootLogger();
}
/*
* (non-Javadoc)
*
* @see org.slf4j.ILoggerFactory#getLogger(java.lang.String)
*/
public Logger getLogger(String name) {
Logger slf4jLogger = loggerMap.get(name);
if (slf4jLogger != null) {
return slf4jLogger;
} else {
org.apache.log4j.Logger log4jLogger;
if (name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME))
log4jLogger = LogManager.getRootLogger();
else
log4jLogger = LogManager.getLogger(name);
Logger newInstance = new Reload4jLoggerAdapter(log4jLogger);
Logger oldInstance = loggerMap.putIfAbsent(name, newInstance);
return oldInstance == null ? newInstance : oldInstance;
}
}
}

View File

@ -0,0 +1,91 @@
/**
* 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.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.slf4j.spi.MDCAdapter;
public class Reload4jMDCAdapter implements MDCAdapter {
public void clear() {
@SuppressWarnings("rawtypes")
Map map = org.apache.log4j.MDC.getContext();
if (map != null) {
map.clear();
}
}
public String get(String key) {
return (String) org.apache.log4j.MDC.get(key);
}
/**
* Put a context value (the <code>val</code> parameter) as identified with
* the <code>key</code> parameter into the current thread's context map. The
* <code>key</code> parameter cannot be null. Log4j does <em>not</em>
* support null for the <code>val</code> parameter.
*
* <p>
* This method delegates all work to log4j's MDC.
*
* @throws IllegalArgumentException
* in case the "key" or <b>"val"</b> parameter is null
*/
public void put(String key, String val) {
org.apache.log4j.MDC.put(key, val);
}
public void remove(String key) {
org.apache.log4j.MDC.remove(key);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public Map getCopyOfContextMap() {
Map old = org.apache.log4j.MDC.getContext();
if (old != null) {
return new HashMap(old);
} else {
return null;
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public void setContextMap(Map contextMap) {
Map old = org.apache.log4j.MDC.getContext();
if (old == null) {
Iterator entrySetIterator = contextMap.entrySet().iterator();
while (entrySetIterator.hasNext()) {
Map.Entry mapEntry = (Map.Entry) entrySetIterator.next();
org.apache.log4j.MDC.put((String) mapEntry.getKey(), mapEntry.getValue());
}
} else {
old.clear();
old.putAll(contextMap);
}
}
}

View File

@ -0,0 +1,88 @@
/**
* 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.apache.log4j.Level;
import org.slf4j.ILoggerFactory;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.Util;
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&uuml;lc&uuml;
*/
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 = Reload4jLoggerFactory.class.getName();
/**
* The ILoggerFactory instance returned by the {@link #getLoggerFactory}
* method should always be the same object
*/
private final ILoggerFactory loggerFactory;
private StaticLoggerBinder() {
loggerFactory = new Reload4jLoggerFactory();
try {
@SuppressWarnings("unused")
Level level = Level.TRACE;
} catch (NoSuchFieldError nsfe) {
Util.report("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version");
}
}
public ILoggerFactory getLoggerFactory() {
return loggerFactory;
}
public String getLoggerFactoryClassStr() {
return loggerFactoryClassStr;
}
}

View File

@ -0,0 +1,65 @@
/**
* 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.spi.MDCAdapter;
/**
* This implementation is bound to {@link Reload4jMDCAdapter}.
*
* @author Ceki G&uuml;lc&uuml;
*/
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 StaticMDCBinder}.
*/
public MDCAdapter getMDCA() {
return new Reload4jMDCAdapter();
}
public String getMDCAdapterClassStr() {
return Reload4jMDCAdapter.class.getName();
}
}

View File

@ -0,0 +1,78 @@
/**
* 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&uuml;lc&uuml;
* @since 1.7.33
*/
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();
}
}

View File

@ -0,0 +1,13 @@
Implementation-Title: slf4j-reload4j
Bundle-ManifestVersion: 2
Bundle-SymbolicName: slf4j.reload4k
Bundle-Name: slf4j-reload4j
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Export-Package: org.slf4j.impl;version=${parsedVersion.osgiVersion}
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion},
org.slf4j.spi;version=${parsedVersion.osgiVersion},
org.slf4j.helpers;version=${parsedVersion.osgiVersion},
org.slf4j.event;version=${parsedVersion.osgiVersion},
org.apache.log4j
Fragment-Host: slf4j.api

View File

@ -0,0 +1,185 @@
/**
* 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;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.spi.LoggingEvent;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Test whether invoking the SLF4J API causes problems or not.
*
* @author Ceki Gulcu
*
*/
public class InvocationTest {
ListAppender listAppender = new ListAppender();
org.apache.log4j.Logger root;
@Before
public void setUp() throws Exception {
root = org.apache.log4j.Logger.getRootLogger();
root.addAppender(listAppender);
}
@After
public void tearDown() throws Exception {
root.getLoggerRepository().resetConfiguration();
}
@Test
public void test1() {
Logger logger = LoggerFactory.getLogger("test1");
logger.debug("Hello world.");
assertEquals(1, listAppender.list.size());
}
@Test
public void test2() {
Integer i1 = Integer.valueOf(1);
Integer i2 = Integer.valueOf(2);
Integer i3 = Integer.valueOf(3);
Exception e = new Exception("This is a test exception.");
Logger logger = LoggerFactory.getLogger("test2");
logger.trace("Hello trace.");
logger.debug("Hello world 1.");
logger.debug("Hello world {}", i1);
logger.debug("val={} val={}", i1, i2);
logger.debug("val={} val={} val={}", new Object[] { i1, i2, i3 });
logger.debug("Hello world 2", e);
logger.info("Hello world 2.");
logger.warn("Hello world 3.");
logger.warn("Hello world 3", e);
logger.error("Hello world 4.");
logger.error("Hello world {}", Integer.valueOf(3));
logger.error("Hello world 4.", e);
assertEquals(11, listAppender.list.size());
}
@Test
public void testNull() {
Logger logger = LoggerFactory.getLogger("testNull");
logger.trace(null);
logger.debug(null);
logger.info(null);
logger.warn(null);
logger.error(null);
Exception e = new Exception("This is a test exception.");
logger.debug(null, e);
logger.info(null, e);
logger.warn(null, e);
logger.error(null, e);
assertEquals(8, listAppender.list.size());
}
// http://jira.qos.ch/browse/SLF4J-69
// formerly http://bugzilla.slf4j.org/show_bug.cgi?id=78
@Test
public void testNullParameter_BUG78() {
Logger logger = LoggerFactory.getLogger("testNullParameter_BUG78");
String[] parameters = null;
String msg = "hello {}";
logger.debug(msg, (Object[]) parameters);
assertEquals(1, listAppender.list.size());
LoggingEvent e = (LoggingEvent) listAppender.list.get(0);
assertEquals(msg, e.getMessage());
}
@Test
public void testMarker() {
Logger logger = LoggerFactory.getLogger("testMarker");
Marker blue = MarkerFactory.getMarker("BLUE");
logger.trace(blue, "hello");
logger.debug(blue, "hello");
logger.info(blue, "hello");
logger.warn(blue, "hello");
logger.error(blue, "hello");
logger.debug(blue, "hello {}", "world");
logger.info(blue, "hello {}", "world");
logger.warn(blue, "hello {}", "world");
logger.error(blue, "hello {}", "world");
logger.debug(blue, "hello {} and {} ", "world", "universe");
logger.info(blue, "hello {} and {} ", "world", "universe");
logger.warn(blue, "hello {} and {} ", "world", "universe");
logger.error(blue, "hello {} and {} ", "world", "universe");
assertEquals(12, listAppender.list.size());
}
@Test
public void testMDC() {
MDC.put("k", "v");
assertNotNull(MDC.get("k"));
assertEquals("v", MDC.get("k"));
MDC.remove("k");
assertNull(MDC.get("k"));
MDC.put("k1", "v1");
assertEquals("v1", MDC.get("k1"));
MDC.clear();
assertNull(MDC.get("k1"));
try {
MDC.put(null, "x");
fail("null keys are invalid");
} catch (IllegalArgumentException e) {
}
}
@Test
public void testMDCContextMapValues() {
Map<String, String> map = new HashMap<String, String>();
map.put("ka", "va");
map.put("kb", "vb");
MDC.put("k", "v");
assertEquals("v", MDC.get("k"));
MDC.setContextMap(map);
assertNull(MDC.get("k"));
assertEquals("va", MDC.get("ka"));
assertEquals("vb", MDC.get("kb"));
}
}

View File

@ -0,0 +1,53 @@
/**
* 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;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
public class ListAppender extends AppenderSkeleton {
public List<LoggingEvent> list = new ArrayList<LoggingEvent>();
public boolean extractLocationInfo = false;
protected void append(LoggingEvent event) {
list.add(event);
if (extractLocationInfo) {
event.getLocationInformation();
}
}
public void close() {
}
public boolean requiresLayout() {
return false;
}
}

View File

@ -0,0 +1,28 @@
package org.slf4j;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.util.Random;
import org.apache.log4j.MDC;
import org.junit.Test;
public class MDCTest {
private static Random random = new Random();
int diff = random.nextInt(1024*8);
@Test
public void smoke() {
String key = "MDCFriendTest.smoke"+diff;
String val = "val"+diff;
MDC.put(key, val);
assertEquals(val, MDC.get(key));
MDC.clear();
assertNull(MDC.get(key));
}
}

View File

@ -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 java.util.List;
import org.apache.log4j.LogManager;
import org.apache.log4j.spi.LoggingEvent;
import org.junit.After;
import org.junit.Before;
import static org.junit.Assert.assertNotNull;
import org.slf4j.helpers.MultithreadedInitializationTest;
public class Log4j12MultithreadedInitializationTest extends MultithreadedInitializationTest {
static int NUM_LINES_BY_RECURSIVE_APPENDER = 3;
// value of LogManager.DEFAULT_CONFIGURATION_KEY;
static String CONFIG_FILE_KEY = "log4j.configuration";
final String loggerName = this.getClass().getName();
@Before
public void setup() {
System.setProperty(CONFIG_FILE_KEY, "recursiveInitWithActivationDelay.properties");
System.out.println("THREAD_COUNT=" + THREAD_COUNT);
}
@After
public void tearDown() throws Exception {
System.clearProperty(CONFIG_FILE_KEY);
}
protected long getRecordedEventCount() {
List<LoggingEvent> eventList = getRecordedEvents();
assertNotNull(eventList);
return eventList.size();
}
protected int extraLogEvents() {
return NUM_LINES_BY_RECURSIVE_APPENDER;
}
private List<LoggingEvent> getRecordedEvents() {
org.apache.log4j.Logger root = LogManager.getRootLogger();
RecursiveAppender ra = (RecursiveAppender) root.getAppender("RECURSIVE");
assertNotNull(ra);
return ra.events;
}
}

View File

@ -0,0 +1,88 @@
/**
* 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.ArrayList;
import java.util.List;
import java.util.Random;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RecursiveAppender extends AppenderSkeleton {
int diff = new Random().nextInt();
int activationDelay = 0;
String loggerName = "org.slf4j.impl.RecursiveAppender" + diff;
List<LoggingEvent> events = new ArrayList<LoggingEvent>();
public RecursiveAppender() {
System.out.println("entering RecursiveAppender constructor");
Logger logger = LoggerFactory.getLogger(loggerName);
logger.info("Calling a logger in the constructor");
System.out.println("exiting RecursiveAppender constructor");
}
protected void append(LoggingEvent e) {
events.add(e);
}
public void close() {
}
public boolean requiresLayout() {
return false;
}
@Override
public void activateOptions() {
System.out.println("entering RecursiveAppender.activateOptions");
if (activationDelay > 0) {
Logger logger = LoggerFactory.getLogger(loggerName);
logger.info("About to wait {} millis", activationDelay);
try {
Thread.sleep(activationDelay);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("Done waiting {} millis", activationDelay);
}
super.activateOptions();
System.out.println("exiting RecursiveAppender.activateOptions");
}
public int getActivationDelay() {
return activationDelay;
}
public void setActivationDelay(int activationDelay) {
this.activationDelay = activationDelay;
}
}

View File

@ -0,0 +1,54 @@
/**
* 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.Random;
import org.junit.After;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RecursiveInitializationTest {
// value of LogManager.DEFAULT_CONFIGURATION_KEY;
static String CONFIG_FILE_KEY = "log4j.configuration";
int diff = new Random().nextInt(10000);
String loggerName = "org.slf4j.impl.RecursiveInitializationTest";
@After
public void tearDown() throws Exception {
System.clearProperty(CONFIG_FILE_KEY);
}
@Test
public void loggingDuringInitialization() {
System.setProperty(CONFIG_FILE_KEY, "recursiveInit.properties");
Logger logger = LoggerFactory.getLogger(loggerName + ".loggingDuringInitialization-" + diff);
logger.info("hello");
}
}

View File

@ -0,0 +1,8 @@
log4j.debug=true
log4j.rootLogger=DEBUG, RECURSIVE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d [%t] %c - %m%n
log4j.appender.RECURSIVE=org.slf4j.impl.RecursiveAppender

View File

@ -0,0 +1,9 @@
log4j.debug=true
log4j.rootLogger=DEBUG, CONSOLE, RECURSIVE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=CON %d [%t] %c - %m%n
log4j.appender.RECURSIVE=org.slf4j.impl.RecursiveAppender
log4j.appender.RECURSIVE.activationDelay=10

View File

@ -1,4 +1,4 @@
Copyright (c) 2004-2007 QOS.ch
Copyright (c) 2004-2022 QOS.ch
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining