ch.qos.cal10n
cal10n-api
diff --git a/slf4j-reload4j/LICENSE.txt b/slf4j-reload4j/LICENSE.txt
new file mode 100644
index 00000000..1a3d0532
--- /dev/null
+++ b/slf4j-reload4j/LICENSE.txt
@@ -0,0 +1,24 @@
+Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland)
+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.
+
+
+
diff --git a/slf4j-reload4j/pom.xml b/slf4j-reload4j/pom.xml
new file mode 100644
index 00000000..b03a13c8
--- /dev/null
+++ b/slf4j-reload4j/pom.xml
@@ -0,0 +1,67 @@
+
+
+
+ 4.0.0
+
+
+ org.slf4j
+ slf4j-parent
+ 2.0.0-alpha6-SNAPSHOT
+
+
+ slf4j-reload4j
+
+
+ jar
+ SLF4J Reload4j Binding
+ SLF4J Reload4j Binding
+ http://reload4j.qos.ch
+
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+ ch.qos.reload4j
+ reload4j
+
+
+
+ org.slf4j
+ slf4j-api
+ test-jar
+ ${project.version}
+ test
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.19.1
+
+ 1
+ false
+ plain
+ false
+
+ **/AllTest.java
+ **/PackageTest.java
+
+ -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8001
+
+
+
+
+
+
+
+
diff --git a/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerAdapter.java b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerAdapter.java
new file mode 100644
index 00000000..e4f3e117
--- /dev/null
+++ b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerAdapter.java
@@ -0,0 +1,232 @@
+/**
+ * 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.reload4j;
+
+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.event.SubstituteLoggingEvent;
+import org.slf4j.helpers.LegacyAbstractLogger;
+import org.slf4j.helpers.MessageFormatter;
+import org.slf4j.helpers.NormalizedParameters;
+import org.slf4j.helpers.SubstituteLogger;
+import org.slf4j.spi.LocationAwareLogger;
+import org.slf4j.spi.LoggingEventAware;
+import org.slf4j.spi.LoggingEventBuilder;
+
+/**
+ * A wrapper over {@link org.apache.log4j.Logger org.apache.log4j.Logger} in
+ * conforming to the {@link Logger} interface.
+ *
+ *
+ * Note that the logging levels mentioned in this class refer to those defined
+ * in the
+ * org.apache.log4j.Level class.
+ *
+ *
+ * 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
+ * SLF4J-59.
+ *
+ * @author Ceki Gülcü
+ */
+public final class Reload4jLoggerAdapter extends LegacyAbstractLogger implements LocationAwareLogger, LoggingEventAware, 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_NOMINAL = org.slf4j.helpers.AbstractLogger.class.getName();
+ final static String FQCN_SUBSTITUE = FQCN_NOMINAL;
+ final static String FQCN_FLUENT = org.slf4j.spi.DefaultLoggingEventBuilder.class.getName();
+
+ // Does the log4j version in use recognize the TRACE level?
+ // The trace level was introduced in log4j 1.2.12.
+ final boolean traceCapable;
+
+ // 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();
+ traceCapable = isTraceCapable();
+ }
+
+ private boolean isTraceCapable() {
+ try {
+ logger.isTraceEnabled();
+ return true;
+ } catch (NoSuchMethodError e) {
+ return false;
+ }
+ }
+
+ /**
+ * Is this logger instance enabled for the TRACE level?
+ *
+ * @return True if this Logger is enabled for level TRACE, false otherwise.
+ */
+ public boolean isTraceEnabled() {
+ if (traceCapable) {
+ return logger.isTraceEnabled();
+ } else {
+ return logger.isDebugEnabled();
+ }
+ }
+
+ /**
+ * 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();
+ }
+
+ /**
+ * 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();
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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);
+ }
+
+ @Override
+ public void log(Marker marker, String callerFQCN, int level, String msg, Object[] arguments, Throwable t) {
+ Level log4jLevel = toLog4jLevel(level);
+ NormalizedParameters np = NormalizedParameters.normalize(msg, arguments, t);
+ String formattedMessage = MessageFormatter.basicArrayFormat(np.getMessage(), np.getArguments());
+ logger.log(callerFQCN, log4jLevel, formattedMessage, np.getThrowable());
+ }
+
+ @Override
+ protected void handleNormalizedLoggingCall(org.slf4j.event.Level level, Marker marker, String msg, Object[] arguments, Throwable throwable) {
+ Level log4jLevel = toLog4jLevel(level.toInt());
+ String formattedMessage = MessageFormatter.basicArrayFormat(msg, arguments);
+ logger.log(getFullyQualifiedCallerName(), log4jLevel, formattedMessage, throwable);
+ }
+
+ /**
+ * Called by {@link SubstituteLogger} or by {@link LoggingEventBuilder} instances
+ * @param event
+ */
+ public void log(LoggingEvent event) {
+ Level log4jLevel = toLog4jLevel(event.getLevel().toInt());
+ if (!logger.isEnabledFor(log4jLevel))
+ return;
+
+ org.apache.log4j.spi.LoggingEvent log4jevent = event2Log4jEvent(event, log4jLevel);
+ logger.callAppenders(log4jevent);
+
+ }
+
+ private org.apache.log4j.spi.LoggingEvent event2Log4jEvent(LoggingEvent event, Level log4jLevel) {
+
+ String formattedMessage = MessageFormatter.basicArrayFormat(event.getMessage(), event.getArgumentArray());
+
+ LocationInfo locationInfo = null;
+ String fcqn = null;
+
+ if (event instanceof SubstituteLoggingEvent) {
+ locationInfo = new LocationInfo(NA_SUBST, NA_SUBST, NA_SUBST, "0");
+ fcqn = FQCN_SUBSTITUE;
+ } else {
+ fcqn = FQCN_FLUENT;
+ }
+
+ ThrowableInformation ti = null;
+ Throwable t = event.getThrowable();
+ if (t != null)
+ ti = new ThrowableInformation(t);
+
+ org.apache.log4j.spi.LoggingEvent log4jEvent = new org.apache.log4j.spi.LoggingEvent(fcqn, logger, event.getTimeStamp(), log4jLevel, formattedMessage,
+ event.getThreadName(), ti, null, locationInfo, null);
+
+ return log4jEvent;
+ }
+
+ private Level toLog4jLevel(int slf4jLevelInt) {
+ Level log4jLevel;
+ switch (slf4jLevelInt) {
+ case LocationAwareLogger.TRACE_INT:
+ log4jLevel = traceCapable ? Level.TRACE : Level.DEBUG;
+ 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 " + slf4jLevelInt + " is not recognized.");
+ }
+ return log4jLevel;
+ }
+
+ @Override
+ protected String getFullyQualifiedCallerName() {
+ return FQCN_NOMINAL;
+ }
+
+}
diff --git a/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerFactory.java b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerFactory.java
new file mode 100644
index 00000000..4c4aadeb
--- /dev/null
+++ b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerFactory.java
@@ -0,0 +1,90 @@
+/**
+ * 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.reload4j;
+
+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ülcü
+ */
+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-log4j12.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 loggerMap;
+
+ public Reload4jLoggerFactory() {
+ loggerMap = new ConcurrentHashMap<>();
+ // 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;
+ }
+ }
+}
diff --git a/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jMDCAdapter.java b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jMDCAdapter.java
new file mode 100644
index 00000000..f9e40372
--- /dev/null
+++ b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jMDCAdapter.java
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland)
+ * 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.reload4j;
+
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.slf4j.helpers.ThreadLocalMapOfStacks;
+import org.slf4j.spi.MDCAdapter;
+
+public class Reload4jMDCAdapter implements MDCAdapter {
+
+ private final ThreadLocalMapOfStacks threadLocalMapOfDeques = new ThreadLocalMapOfStacks();
+
+ @Override
+ public void clear() {
+ @SuppressWarnings("rawtypes")
+ Map map = org.apache.log4j.MDC.getContext();
+ if (map != null) {
+ map.clear();
+ }
+ }
+
+ @Override
+ public String get(String key) {
+ return (String) org.apache.log4j.MDC.get(key);
+ }
+
+ /**
+ * Put a context value (the val parameter) as identified with
+ * the key parameter into the current thread's context map. The
+ * key parameter cannot be null. Log4j does not
+ * support null for the val parameter.
+ *
+ *
+ * This method delegates all work to log4j's MDC.
+ *
+ * @throws IllegalArgumentException
+ * in case the "key" or "val" parameter is null
+ */
+ @Override
+ public void put(String key, String val) {
+ org.apache.log4j.MDC.put(key, val);
+ }
+
+ @Override
+ 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" })
+ @Override
+ public void setContextMap(Map contextMap) {
+ Map old = org.apache.log4j.MDC.getContext();
+
+ // we must cater for the case where the contextMap argument is null
+ if (contextMap == null) {
+ if (old != null) {
+ old.clear();
+ }
+ return;
+ }
+
+ if (old == null) {
+ for (Map.Entry mapEntry : contextMap.entrySet()) {
+ org.apache.log4j.MDC.put(mapEntry.getKey(), mapEntry);
+ }
+ } else {
+ old.clear();
+ old.putAll(contextMap);
+ }
+ }
+
+ @Override
+ public void pushByKey(String key, String value) {
+ threadLocalMapOfDeques.pushByKey(key, value);
+ }
+
+ @Override
+ public String popByKey(String key) {
+ return threadLocalMapOfDeques.popByKey(key);
+ }
+
+ @Override
+ public Deque getCopyOfDequeByKey(String key) {
+ return threadLocalMapOfDeques.getCopyOfDequeByKey(key);
+ }
+
+ @Override
+ public void clearDequeByKey(String key) {
+ threadLocalMapOfDeques.clearDequeByKey(key);
+ }
+}
diff --git a/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jServiceProvider.java b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jServiceProvider.java
new file mode 100644
index 00000000..4625b09c
--- /dev/null
+++ b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jServiceProvider.java
@@ -0,0 +1,61 @@
+package org.slf4j.reload4j;
+
+import org.apache.log4j.Level;
+import org.slf4j.ILoggerFactory;
+import org.slf4j.IMarkerFactory;
+import org.slf4j.helpers.BasicMarkerFactory;
+import org.slf4j.helpers.Util;
+import org.slf4j.spi.MDCAdapter;
+import org.slf4j.spi.SLF4JServiceProvider;
+
+public class Reload4jServiceProvider implements SLF4JServiceProvider {
+
+ /**
+ * 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 = "2.0.99"; // !final
+
+ private ILoggerFactory loggerFactory;
+ private IMarkerFactory markerFactory;
+ private MDCAdapter mdcAdapter;
+
+ public Reload4jServiceProvider() {
+ 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");
+ }
+ }
+
+ @Override
+ public void initialize() {
+ loggerFactory = new Reload4jLoggerFactory();
+ markerFactory = new BasicMarkerFactory();
+ mdcAdapter = new Reload4jMDCAdapter();
+ }
+
+ @Override
+ public ILoggerFactory getLoggerFactory() {
+ return loggerFactory;
+ }
+
+
+ @Override
+ public IMarkerFactory getMarkerFactory() {
+ return markerFactory;
+ }
+
+
+ @Override
+ public MDCAdapter getMDCAdapter() {
+ return mdcAdapter;
+ }
+
+ @Override
+ public String getRequestedApiVersion() {
+ return REQUESTED_API_VERSION;
+ }
+}
diff --git a/slf4j-reload4j/src/main/resources/META-INF/MANIFEST.MF b/slf4j-reload4j/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..980e84e6
--- /dev/null
+++ b/slf4j-reload4j/src/main/resources/META-INF/MANIFEST.MF
@@ -0,0 +1,12 @@
+Implementation-Title: slf4j-reload4j
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: slf4j.reload4j
+Bundle-Name: slf4j-reload4j
+Bundle-Vendor: SLF4J.ORG
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Export-Package: org.slf4j.reload4j;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
diff --git a/slf4j-reload4j/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider b/slf4j-reload4j/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider
new file mode 100644
index 00000000..b81f3e12
--- /dev/null
+++ b/slf4j-reload4j/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider
@@ -0,0 +1 @@
+org.slf4j.reload4j.Reload4jServiceProvider
diff --git a/slf4j-reload4j/src/test/java/org/slf4j/reload4j/InvocationTest.java b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/InvocationTest.java
new file mode 100644
index 00000000..12d6db19
--- /dev/null
+++ b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/InvocationTest.java
@@ -0,0 +1,209 @@
+/**
+ * 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.reload4j;
+
+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;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+
+/**
+ * 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 map = new HashMap<>();
+ 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"));
+ }
+
+ @Test
+ public void testCallerInfo() {
+ Logger logger = LoggerFactory.getLogger("testMarker");
+ listAppender.extractLocationInfo = true;
+ logger.debug("hello");
+ LoggingEvent event = listAppender.list.get(0);
+ assertEquals(this.getClass().getName(), event.getLocationInformation().getClassName());
+ }
+
+ @Test
+ public void testCallerInfoWithFluentAPI() {
+ Logger logger = LoggerFactory.getLogger("testMarker");
+ listAppender.extractLocationInfo = true;
+ logger.atDebug().log("hello");
+ LoggingEvent event = listAppender.list.get(0);
+ assertEquals(this.getClass().getName(), event.getLocationInformation().getClassName());
+ }
+
+}
diff --git a/slf4j-reload4j/src/test/java/org/slf4j/reload4j/ListAppender.java b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/ListAppender.java
new file mode 100644
index 00000000..92cd9d32
--- /dev/null
+++ b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/ListAppender.java
@@ -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.reload4j;
+
+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 list = new ArrayList<>();
+
+ public boolean extractLocationInfo = false;
+
+ protected void append(LoggingEvent event) {
+ list.add(event);
+ if (extractLocationInfo) {
+ event.getLocationInformation();
+ }
+ }
+
+ public void close() {
+ }
+
+ public boolean requiresLayout() {
+ return false;
+ }
+
+}
diff --git a/slf4j-reload4j/src/test/java/org/slf4j/reload4j/Log4j12MultithreadedInitializationTest.java b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/Log4j12MultithreadedInitializationTest.java
new file mode 100644
index 00000000..7d0e3751
--- /dev/null
+++ b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/Log4j12MultithreadedInitializationTest.java
@@ -0,0 +1,72 @@
+/**
+ * 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.reload4j;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.spi.LoggingEvent;
+import org.junit.After;
+import org.junit.Before;
+import org.slf4j.reload4j.testHarness.RecursiveAppender;
+
+public class Log4j12MultithreadedInitializationTest extends org.slf4j.testHarness.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 eventList = getRecordedEvents();
+ assertNotNull(eventList);
+ return eventList.size();
+ }
+
+ protected int extraLogEvents() {
+ return NUM_LINES_BY_RECURSIVE_APPENDER;
+ }
+
+ private List getRecordedEvents() {
+ org.apache.log4j.Logger root = LogManager.getRootLogger();
+ RecursiveAppender ra = (RecursiveAppender) root.getAppender("RECURSIVE");
+ assertNotNull(ra);
+ return ra.events;
+ }
+
+}
diff --git a/slf4j-reload4j/src/test/java/org/slf4j/reload4j/Log4jMDCAdapterTest.java b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/Log4jMDCAdapterTest.java
new file mode 100644
index 00000000..f6008176
--- /dev/null
+++ b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/Log4jMDCAdapterTest.java
@@ -0,0 +1,28 @@
+package org.slf4j.reload4j;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.slf4j.helpers.MDCAdapterTestBase;
+import org.slf4j.reload4j.Reload4jMDCAdapter;
+import org.slf4j.spi.MDCAdapter;
+
+public class Log4jMDCAdapterTest extends MDCAdapterTestBase {
+
+ protected MDCAdapter instantiateMDC() {
+ return new Reload4jMDCAdapter();
+ }
+
+
+ @Test
+ public void testClearingMDC() {
+ mdc.put("testKey", "testValue");
+ assertFalse(mdc.getCopyOfContextMap().isEmpty());
+ mdc.clear();
+ assertTrue(mdc.getCopyOfContextMap().isEmpty());
+ }
+
+
+
+}
diff --git a/slf4j-reload4j/src/test/java/org/slf4j/reload4j/RecursiveInitializationTest.java b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/RecursiveInitializationTest.java
new file mode 100644
index 00000000..ff68f2da
--- /dev/null
+++ b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/RecursiveInitializationTest.java
@@ -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.reload4j;
+
+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");
+ }
+
+}
diff --git a/slf4j-reload4j/src/test/java/org/slf4j/reload4j/testHarness/RecursiveAppender.java b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/testHarness/RecursiveAppender.java
new file mode 100644
index 00000000..3857ba32
--- /dev/null
+++ b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/testHarness/RecursiveAppender.java
@@ -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.reload4j.testHarness;
+
+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;
+
+ public List events = new ArrayList<>();
+
+ public RecursiveAppender() {
+ System.out.println("XXXXXXX 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;
+ }
+
+}
diff --git a/slf4j-reload4j/src/test/resources/recursiveInit.properties b/slf4j-reload4j/src/test/resources/recursiveInit.properties
new file mode 100644
index 00000000..a62a15e2
--- /dev/null
+++ b/slf4j-reload4j/src/test/resources/recursiveInit.properties
@@ -0,0 +1,9 @@
+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=[%t] %c - %m%n
+
+log4j.appender.RECURSIVE=org.slf4j.reload4j.testHarness.RecursiveAppender
+
\ No newline at end of file
diff --git a/slf4j-reload4j/src/test/resources/recursiveInitWithActivationDelay.properties b/slf4j-reload4j/src/test/resources/recursiveInitWithActivationDelay.properties
new file mode 100644
index 00000000..957894dd
--- /dev/null
+++ b/slf4j-reload4j/src/test/resources/recursiveInitWithActivationDelay.properties
@@ -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 [%t] %c - %m%n
+
+log4j.appender.RECURSIVE=org.slf4j.reload4j.testHarness.RecursiveAppender
+log4j.appender.RECURSIVE.activationDelay=10