Compare commits

...

35 Commits

Author SHA1 Message Date
Ceki Gulcu 2758a97426 prepare release 1.7.33
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-01-13 15:33:45 +01:00
Ceki Gulcu a0681b72eb fix SLF4J-499
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-01-13 15:16:39 +01:00
Ceki Gulcu c89dc3db0f Merge branch '1.7-maintenance' of github.com:qos-ch/slf4j into 1.7-maintenance 2022-01-12 22:40:47 +01:00
Ceki Gulcu 0d2bd398f7 add slf4j-reload4j module
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-01-12 22:40:10 +01:00
Ceki Gulcu ae9ee009f6 start work on 1.7.33-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2021-07-29 21:31:50 +02:00
Ceki Gulcu 0d8774854f this is version 1.7.32
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2021-07-29 20:27:41 +02:00
Ceki Gulcu 49f242400d make CONFIG_PARAMS aa final field
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2021-07-09 23:02:02 +02:00
Ceki Gulcu e4fd949462 improvements to SLF4J-515
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2021-07-09 09:59:48 +02:00
Ceki Gulcu b6fb6e3b1d changes after feedback from Tibor Digana
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2021-07-09 00:23:22 +02:00
Ceki Gulcu 816da3d857 fixing SLF4J-515
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2021-07-08 23:38:29 +02:00
Ceki Gulcu 33e7bf2b97 start work on 1.7.32
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2021-07-08 20:05:39 +02:00
Ceki Gulcu 502c5286e9 prepare release 1.7.31 2021-06-17 23:32:18 +02:00
Ceki Gulcu 12183e0a1c fix SLF4J-514 2021-06-17 10:59:55 +02:00
Antonio Tomac 940c462556 Avoid potentially "expensive" rendering of message Object to String when log level is disabled SLF4J-497 2021-06-16 00:51:24 +02:00
Ceki Gulcu 62309486d3 next version is 1.7.31 2019-12-20 16:28:48 +01:00
Ceki Gulcu 0b97c416e4 move to 1.7.30 2019-12-16 22:01:36 +01:00
Ceki Gulcu c6c7a98a7e fix SLF4J-469 2019-12-16 21:52:14 +01:00
Ceki Gulcu ca93154c79 do not deploy slf4j-site 2019-10-31 22:16:34 +01:00
Hervé Boutemy d061e25477 this module is Apache 2.0 licensed 2019-10-31 13:08:47 +01:00
Ceki Gulcu e8ce694e2e preapre release 1.7.29 2019-10-31 12:51:26 +01:00
Ceki Gulcu 125e7cca19
Merge pull request #219 from delgurth/1.7-maintenance-with-slf4j-466
SLF4J-466: backport changes to 1.7
2019-08-14 07:46:57 +02:00
Wessel van Norel a7562cb4b9 SLF4J-466: backport changes to 1.7
SLF4J-466: backport changes to 1.7

SLF4J-466: corrected whitespace

SLF4J-466: corrected whitespace
2019-08-14 01:29:58 +02:00
Ceki Gulcu 9752c892fd specify jdk8 in travis 2019-08-10 11:05:48 +02:00
Ceki Gulcu b44fbd53cc prepare release 1.7.28 2019-08-10 10:21:59 +02:00
Ceki Gulcu 2a1374691f correct Automatic-Module-Name: org.apache.log4j 2019-08-10 10:21:11 +02:00
Ceki Gulcu 4c6c574a7a fix javadoc issues 2019-08-06 11:35:23 +02:00
Ceki Gulcu 71291d97ba prepare release 1.7.27 2019-08-06 01:03:12 +02:00
Ceki Gulcu bf50c49d10 fix SLF4J-420 2019-08-06 00:56:24 +02:00
Ceki Gulcu 4e5ddca4ea add Automatic-Module-Name for slf4j-api 2019-08-05 19:03:45 +02:00
Ceki Gulcu e69d4a9c73 fix SLF4J-460 2019-08-05 18:58:53 +02:00
Ceki Gulcu acb850d669 fix link 2019-08-05 18:49:52 +02:00
Ceki Gulcu 179350d855 up version 2019-08-05 18:49:21 +02:00
Ceki Gulcu 7a35058597 rework on site creation, keep Nexus/Central happy 2019-02-19 00:13:52 +01:00
Ceki Gulcu 3cd3f3e5cc enable source jar creation only for select modules to keep Nexus happy 2019-02-18 23:24:43 +01:00
Ceki Gulcu 918a055bdf fix CVE-2018-8088, prepare 1.7.26 release 2019-02-16 13:26:17 +01:00
68 changed files with 3224 additions and 848 deletions

View File

@ -1,4 +1,9 @@
language: java
jdk:
- openjdk8
notifications:
email:
- notification@qos.ch

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

@ -56,7 +56,12 @@
<pathelement location="../slf4j-simple/target/slf4j-simple-${currentVersion}.jar" />
</path >
<path id="pathNoBinding">
<pathelement location="target/test-classes/" />
<pathelement location="../slf4j-api/target/slf4j-api-${currentVersion}.jar" />
</path >
<path id="incompatibleMultiBinding">
<pathelement location="target/test-classes/" />
<pathelement location="../slf4j-api/target/slf4j-api-${currentVersion}.jar" />
@ -102,11 +107,12 @@
</target>
<target name="testAll" depends="init,
testMissingSingletonMethod,
testMissingSingletonMethod,
testMismatch,
testMatch,
testMultiBinding,
testIncompatibleMultiBinding,
testNoBinding,
testMatch,
testMultiBinding,
testIncompatibleMultiBinding,
testFuture_16Series,
testActiveSecurityManager">
</target>
@ -215,7 +221,17 @@
</junit>
</target>
<target name="testNoBinding">
<junit printsummary="yes" fork="no" haltonfailure="yes">
<classpath refid="pathNoBinding" />
<formatter type="plain" />
<test fork="yes" todir="target/unit-reports"
outfile="TEST-NOBINDING"
name="org.slf4j.helpers.NoBindingMultithreadedInitializationTest2" />
</junit>
</target>
<condition property="runFromWithinIntegrationModule">
<contains string="${user.dir}" substring="integration" />

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>integration</artifactId>

View File

@ -0,0 +1,65 @@
/**
* Copyright (c) 2004-2016 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.helpers;
import java.util.List;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoggerAccessingThread2 extends Thread {
private static int LOOP_LEN = 64;
final CyclicBarrier barrier;
final int count;
final AtomicLong eventCount;
List<Logger> loggerList;
public LoggerAccessingThread2(final CyclicBarrier barrier, List<Logger> loggerList, final int count, final AtomicLong eventCount) {
this.barrier = barrier;
this.loggerList = loggerList;
this.count = count;
this.eventCount = eventCount;
}
public void run() {
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
String loggerNamePrefix = this.getClass().getName();
for (int i = 0; i < LOOP_LEN; i++) {
Logger logger = LoggerFactory.getLogger(loggerNamePrefix + "-" + count + "-" + i);
loggerList.add(logger);
Thread.yield();
logger.info("in run method");
eventCount.getAndIncrement();
}
}
}

View File

@ -0,0 +1,112 @@
/**
* Copyright (c) 2004-2016 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.helpers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.EventRecodingLogger;
import junit.framework.TestCase;
public class NoBindingMultithreadedInitializationTest2 extends TestCase {
final protected static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2;
private final List<Logger> createdLoggers = Collections.synchronizedList(new ArrayList<Logger>());
protected final AtomicLong eventCount = new AtomicLong(0);
final private CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
int diff = new Random().nextInt(10000);
public NoBindingMultithreadedInitializationTest2(String name) {
super(name);
}
public void testNoBindingMultiThreadedInitialization() throws InterruptedException, BrokenBarrierException {
@SuppressWarnings("unused")
LoggerAccessingThread2[] accessors = harness();
Logger logger = LoggerFactory.getLogger(getClass().getName());
logger.info("hello");
eventCount.getAndIncrement();
assertAllSubstLoggersAreFixed();
long recordedEventCount = getRecordedEventCount();
int LENIENCY_COUNT = 16;
long expectedEventCount = eventCount.get() + extraLogEvents();
assertTrue(expectedEventCount + " >= " + recordedEventCount, expectedEventCount >= recordedEventCount);
assertTrue(expectedEventCount + " < " + recordedEventCount + "+" + LENIENCY_COUNT,
expectedEventCount < recordedEventCount + LENIENCY_COUNT);
}
protected int extraLogEvents() {
return 0;
}
private void assertAllSubstLoggersAreFixed() {
for (Logger logger : createdLoggers) {
if (logger instanceof SubstituteLogger) {
SubstituteLogger substLogger = (SubstituteLogger) logger;
if (substLogger.delegate() instanceof EventRecodingLogger)
fail("substLogger " + substLogger.getName() + " has a delegate of type EventRecodingLogger");
}
}
}
private LoggerAccessingThread2[] harness() throws InterruptedException, BrokenBarrierException {
LoggerAccessingThread2[] threads = new LoggerAccessingThread2[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i] = new LoggerAccessingThread2(barrier, createdLoggers, i, eventCount);
threads[i].start();
}
// trigger barrier
barrier.await();
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i].join();
}
return threads;
}
final String loggerName = this.getClass().getName();
protected long getRecordedEventCount() {
return eventCount.get();
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -16,6 +16,14 @@
<description>JCL 1.2 implemented over SLF4J</description>
<url>http://www.slf4j.org</url>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
@ -28,4 +36,5 @@
</dependency>
</dependencies>
</project>
</project>

View File

@ -104,7 +104,9 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
* the message to log. Converted to {@link String}
*/
public void trace(Object message) {
logger.log(null, FQCN, LocationAwareLogger.TRACE_INT, String.valueOf(message), null, null);
if (isTraceEnabled()) {
logger.log(null, FQCN, LocationAwareLogger.TRACE_INT, String.valueOf(message), null, null);
}
}
/**
@ -117,7 +119,9 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
* the exception to log
*/
public void trace(Object message, Throwable t) {
logger.log(null, FQCN, LocationAwareLogger.TRACE_INT, String.valueOf(message), null, t);
if (isTraceEnabled()) {
logger.log(null, FQCN, LocationAwareLogger.TRACE_INT, String.valueOf(message), null, t);
}
}
/**
@ -128,7 +132,9 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
* the message to log. Converted to {@link String}
*/
public void debug(Object message) {
logger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, String.valueOf(message), null, null);
if (isDebugEnabled()) {
logger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, String.valueOf(message), null, null);
}
}
/**
@ -141,7 +147,9 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
* the exception to log
*/
public void debug(Object message, Throwable t) {
logger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, String.valueOf(message), null, t);
if (isDebugEnabled()) {
logger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, String.valueOf(message), null, t);
}
}
/**
@ -152,7 +160,9 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
* the message to log. Converted to {@link String}
*/
public void info(Object message) {
logger.log(null, FQCN, LocationAwareLogger.INFO_INT, String.valueOf(message), null, null);
if (isInfoEnabled()) {
logger.log(null, FQCN, LocationAwareLogger.INFO_INT, String.valueOf(message), null, null);
}
}
/**
@ -165,7 +175,9 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
* the exception to log
*/
public void info(Object message, Throwable t) {
logger.log(null, FQCN, LocationAwareLogger.INFO_INT, String.valueOf(message), null, t);
if (isInfoEnabled()) {
logger.log(null, FQCN, LocationAwareLogger.INFO_INT, String.valueOf(message), null, t);
}
}
/**
@ -176,7 +188,9 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
* the message to log. Converted to {@link String}
*/
public void warn(Object message) {
logger.log(null, FQCN, LocationAwareLogger.WARN_INT, String.valueOf(message), null, null);
if (isWarnEnabled()) {
logger.log(null, FQCN, LocationAwareLogger.WARN_INT, String.valueOf(message), null, null);
}
}
/**
@ -189,7 +203,9 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
* the exception to log
*/
public void warn(Object message, Throwable t) {
logger.log(null, FQCN, LocationAwareLogger.WARN_INT, String.valueOf(message), null, t);
if (isWarnEnabled()) {
logger.log(null, FQCN, LocationAwareLogger.WARN_INT, String.valueOf(message), null, t);
}
}
/**
@ -200,7 +216,9 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
* the message to log. Converted to {@link String}
*/
public void error(Object message) {
logger.log(null, FQCN, LocationAwareLogger.ERROR_INT, String.valueOf(message), null, null);
if (isErrorEnabled()) {
logger.log(null, FQCN, LocationAwareLogger.ERROR_INT, String.valueOf(message), null, null);
}
}
/**
@ -213,7 +231,9 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
* the exception to log
*/
public void error(Object message, Throwable t) {
logger.log(null, FQCN, LocationAwareLogger.ERROR_INT, String.valueOf(message), null, t);
if (isErrorEnabled()) {
logger.log(null, FQCN, LocationAwareLogger.ERROR_INT, String.valueOf(message), null, t);
}
}
/**
@ -224,7 +244,9 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
* the message to log. Converted to {@link String}
*/
public void fatal(Object message) {
logger.log(null, FQCN, LocationAwareLogger.ERROR_INT, String.valueOf(message), null, null);
if (isErrorEnabled()) {
logger.log(null, FQCN, LocationAwareLogger.ERROR_INT, String.valueOf(message), null, null);
}
}
/**
@ -237,7 +259,9 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
* the exception to log
*/
public void fatal(Object message, Throwable t) {
logger.log(null, FQCN, LocationAwareLogger.ERROR_INT, String.valueOf(message), null, t);
if (isErrorEnabled()) {
logger.log(null, FQCN, LocationAwareLogger.ERROR_INT, String.valueOf(message), null, t);
}
}
/**

View File

@ -4,6 +4,7 @@ Bundle-SymbolicName: jcl.over.slf4j
Bundle-Name: jcl-over-slf4j
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Automatic-Module-Name: org.apache.commons.logging
Export-Package: org.apache.commons.logging;version=1.2,
org.apache.commons.logging.impl;version=1.2
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion}, org.slf4j.spi;version=${parsedVersion.osgiVersion}

View File

@ -27,6 +27,7 @@ package org.apache.commons.logging;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
@ -85,4 +86,56 @@ public class InvokeJCLTest {
log.fatal(null, e);
log.fatal("fatal message", e);
}
@Test
public void testAvoidConvertingObjectToString() {
Log log = LogFactory.getLog(InvokeJCLTest.class);
Exception e = new Exception("just testing");
TestMessage fatalMsg = new TestMessage("fatal msg");
TestMessage errorMsg = new TestMessage("error msg");
TestMessage warnMsg = new TestMessage("warn msg");
TestMessage infoMsg = new TestMessage("info msg");
TestMessage debugMsg = new TestMessage("debug msg");
TestMessage traceMsg = new TestMessage("trace msg");
log.fatal(fatalMsg);
log.fatal(fatalMsg, e);
assertEquals(2, fatalMsg.invokedCount);
log.error(errorMsg);
log.error(errorMsg, e);
assertEquals(2, errorMsg.invokedCount);
log.warn(warnMsg);
log.warn(warnMsg, e);
assertEquals(2, warnMsg.invokedCount);
log.info(infoMsg);
log.info(infoMsg, e);
assertEquals(2, infoMsg.invokedCount);
log.debug(debugMsg);
log.debug(debugMsg, e);
assertEquals(0, debugMsg.invokedCount);
log.trace(traceMsg);
log.trace(traceMsg, e);
assertEquals(0, traceMsg.invokedCount);
}
static class TestMessage {
private final String msg;
int invokedCount = 0;
TestMessage(String msg) {this.msg = msg;}
@Override
public String toString() {
invokedCount++;
return msg;
}
}
}

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>jul-to-slf4j</artifactId>
@ -30,5 +30,5 @@
<scope>test</scope>
</dependency>
</dependencies>
</project>
</project>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
@ -36,5 +36,5 @@
<scope>test</scope>
</dependency>
</dependencies>
</project>
</project>

View File

@ -15,6 +15,18 @@
*/
package org.apache.log4j;
/**
* Skeleton implementation of ConsoleAppender
*/
public class ConsoleAppender extends WriterAppender {
public ConsoleAppender() {
}
public ConsoleAppender(Layout layout) {
}
public ConsoleAppender(Layout layout, String target) {
}
}

View File

@ -4,6 +4,7 @@ Bundle-SymbolicName: log4j.over.slf4j
Bundle-Name: log4j-over-slf4j
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Automatic-Module-Name: org.apache.log4j
Export-Package: org.apache.log4j;version=${log4j.version},
org.apache.log4j.helpers;version=${log4j.version},
org.apache.log4j.spi;version=${log4j.version},

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>osgi-over-slf4j</artifactId>
@ -41,4 +41,6 @@
<scope>provided</scope>
</dependency>
</dependencies>
</project>

51
pom.xml
View File

@ -6,7 +6,7 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
<packaging>pom</packaging>
<name>SLF4J</name>
@ -43,10 +43,13 @@
<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>
<javadoc.plugin.version>2.10.4</javadoc.plugin.version>
<maven-source-plugin.version>3.0.1</maven-source-plugin.version>
<javadoc.plugin.version>3.1.0</javadoc.plugin.version>
<doclint>none</doclint>
</properties>
<developers>
@ -63,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>
@ -105,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>
@ -145,7 +155,7 @@
</configuration>
</plugin>
</plugins>
</pluginManagement>
</pluginManagement>
<plugins>
@ -177,7 +187,21 @@
<skipIfEmpty>true</skipIfEmpty>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven-source-plugin.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
@ -194,20 +218,6 @@
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
@ -262,6 +272,8 @@
<version>${javadoc.plugin.version}</version>
<configuration>
<linksource>true</linksource>
<doclint>none</doclint>
<!--<aggregate>true</aggregate>-->
<excludePackageNames>org.slf4j.migrator:org.slf4j.migrator.*</excludePackageNames>
<links>
@ -323,6 +335,9 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${javadoc.plugin.version}</version>
<configuration>
<doclint>none</doclint>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>

49
release.sh Executable file
View File

@ -0,0 +1,49 @@
#mvn versions:set -DgenerateBackupPoms=false -DnewVersion=${VERSION_NUMBER}
MVN='/java/maven-3.5.2//bin/mvn'
PASS=$1
echo $PASS
function checkExit(){
if test "$?" != "0"; then
echo Command $1 exited with abnormal status
exit 1;
else echo $?
fi
}
function echoThenRun () { # echo and then run the command
echo $1
$1
ret=$?
echo $ret
return $ret
}
$MVN clean
checkExit "mvn clean"
$MVN install
checkExit "mvn install"
$MVN site:site
checkExit "mvn site:ste"
$MVN assembly:single
checkExit "mvn assembly:single"
$MVN deploy -P javadocjar,sign-artifacts -Dgpg.passphrase=$PASS
checkExit "mvn deploy -P javadocjar,sign-artifacts -Dgpg.passphrase=xxx"
#$MVN site:deploy -N # with Java 8!!!
#checkExit "mvn site:deploy -N"
#git tag -m "tagging" -a v_${VERSION_NUMBER}
#git push --tags
#release version and add next version on jira

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>slf4j-android</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

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>slf4j-api</artifactId>
@ -117,4 +117,4 @@
</pluginManagement>
</build>
</project>
</project>

View File

@ -150,10 +150,6 @@ public final class LoggerFactory {
StaticLoggerBinder.getSingleton();
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
reportActualBinding(staticLoggerBinderPathSet);
fixSubstituteLoggers();
replayEvents();
// release all resources in SUBST_FACTORY
SUBST_FACTORY.clear();
} catch (NoClassDefFoundError ncde) {
String msg = ncde.getMessage();
if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
@ -177,9 +173,18 @@ public final class LoggerFactory {
} catch (Exception e) {
failedBinding(e);
throw new IllegalStateException("Unexpected initialization failure", e);
} finally {
postBindCleanUp();
}
}
private static void postBindCleanUp() {
fixSubstituteLoggers();
replayEvents();
// release all resources in SUBST_FACTORY
SUBST_FACTORY.clear();
}
private static void fixSubstituteLoggers() {
synchronized (SUBST_FACTORY) {
SUBST_FACTORY.postInitialization();

View File

@ -4,14 +4,28 @@ import java.util.Queue;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.helpers.MessageFormatter;
import org.slf4j.helpers.SubstituteLogger;
/**
*
* This class is used to record events during the initialization phase of the
* underlying logging framework. It is called by {@link SubstituteLogger}.
*
*
* @author Ceki G&uumllc&uuml;
* @author Wessel van Norel
*
*/
public class EventRecodingLogger implements Logger {
String name;
SubstituteLogger logger;
Queue<SubstituteLoggingEvent> eventQueue;
// as an event recording logger we have no choice but to record all events
final static boolean RECORD_ALL_EVENTS = true;
public EventRecodingLogger(SubstituteLogger logger, Queue<SubstituteLoggingEvent> eventQueue) {
this.logger = logger;
this.name = logger.getName();
@ -22,12 +36,276 @@ public class EventRecodingLogger implements Logger {
return name;
}
private void recordEvent(Level level, String msg, Object[] args, Throwable throwable) {
recordEvent(level, null, msg, args, throwable);
public boolean isTraceEnabled() {
return RECORD_ALL_EVENTS;
}
public void trace(String msg) {
recordEvent_0Args(Level.TRACE, null, msg, null);
}
public void trace(String format, Object arg) {
recordEvent_1Args(Level.TRACE, null, format, arg);
}
public void trace(String format, Object arg1, Object arg2) {
recordEvent2Args(Level.TRACE, null, format, arg1, arg2);
}
public void trace(String format, Object... arguments) {
recordEventArgArray(Level.TRACE, null, format, arguments);
}
public void trace(String msg, Throwable t) {
recordEvent_0Args(Level.TRACE, null, msg, t);
}
public boolean isTraceEnabled(Marker marker) {
return RECORD_ALL_EVENTS;
}
public void trace(Marker marker, String msg) {
recordEvent_0Args(Level.TRACE, marker, msg, null);
}
public void trace(Marker marker, String format, Object arg) {
recordEvent_1Args(Level.TRACE, marker, format, arg);
}
public void trace(Marker marker, String format, Object arg1, Object arg2) {
recordEvent2Args(Level.TRACE, marker, format, arg1, arg2);
}
public void trace(Marker marker, String format, Object... argArray) {
recordEventArgArray(Level.TRACE, marker, format, argArray);
}
public void trace(Marker marker, String msg, Throwable t) {
recordEvent_0Args(Level.TRACE, marker, msg, t);
}
public boolean isDebugEnabled() {
return RECORD_ALL_EVENTS;
}
public void debug(String msg) {
recordEvent_0Args(Level.DEBUG, null, msg, null);
}
public void debug(String format, Object arg) {
recordEvent_1Args(Level.DEBUG, null, format, arg);
}
public void debug(String format, Object arg1, Object arg2) {
recordEvent2Args(Level.DEBUG, null, format, arg1, arg2);
}
public void debug(String format, Object... arguments) {
recordEventArgArray(Level.DEBUG, null, format, arguments);
}
public void debug(String msg, Throwable t) {
recordEvent_0Args(Level.DEBUG, null, msg, t);
}
public boolean isDebugEnabled(Marker marker) {
return RECORD_ALL_EVENTS;
}
public void debug(Marker marker, String msg) {
recordEvent_0Args(Level.DEBUG, marker, msg, null);
}
public void debug(Marker marker, String format, Object arg) {
recordEvent_1Args(Level.DEBUG, marker, format, arg);
}
public void debug(Marker marker, String format, Object arg1, Object arg2) {
recordEvent2Args(Level.DEBUG, marker, format, arg1, arg2);
}
public void debug(Marker marker, String format, Object... arguments) {
recordEventArgArray(Level.DEBUG, marker, format, arguments);
}
public void debug(Marker marker, String msg, Throwable t) {
recordEvent_0Args(Level.DEBUG, marker, msg, t);
}
public boolean isInfoEnabled() {
return RECORD_ALL_EVENTS;
}
public void info(String msg) {
recordEvent_0Args(Level.INFO, null, msg, null);
}
public void info(String format, Object arg) {
recordEvent_1Args(Level.INFO, null, format, arg);
}
public void info(String format, Object arg1, Object arg2) {
recordEvent2Args(Level.INFO, null, format, arg1, arg2);
}
public void info(String format, Object... arguments) {
recordEventArgArray(Level.INFO, null, format, arguments);
}
public void info(String msg, Throwable t) {
recordEvent_0Args(Level.INFO, null, msg, t);
}
public boolean isInfoEnabled(Marker marker) {
return RECORD_ALL_EVENTS;
}
public void info(Marker marker, String msg) {
recordEvent_0Args(Level.INFO, marker, msg, null);
}
public void info(Marker marker, String format, Object arg) {
recordEvent_1Args(Level.INFO, marker, format, arg);
}
public void info(Marker marker, String format, Object arg1, Object arg2) {
recordEvent2Args(Level.INFO, marker, format, arg1, arg2);
}
public void info(Marker marker, String format, Object... arguments) {
recordEventArgArray(Level.INFO, marker, format, arguments);
}
public void info(Marker marker, String msg, Throwable t) {
recordEvent_0Args(Level.INFO, marker, msg, t);
}
public boolean isWarnEnabled() {
return RECORD_ALL_EVENTS;
}
public void warn(String msg) {
recordEvent_0Args(Level.WARN, null, msg, null);
}
public void warn(String format, Object arg) {
recordEvent_1Args(Level.WARN, null, format, arg);
}
public void warn(String format, Object arg1, Object arg2) {
recordEvent2Args(Level.WARN, null, format, arg1, arg2);
}
public void warn(String format, Object... arguments) {
recordEventArgArray(Level.WARN, null, format, arguments);
}
public void warn(String msg, Throwable t) {
recordEvent_0Args(Level.WARN, null, msg, t);
}
public boolean isWarnEnabled(Marker marker) {
return RECORD_ALL_EVENTS;
}
public void warn(Marker marker, String msg) {
recordEvent_0Args(Level.WARN, marker, msg, null);
}
public void warn(Marker marker, String format, Object arg) {
recordEvent_1Args(Level.WARN, marker, format, arg);
}
public void warn(Marker marker, String format, Object arg1, Object arg2) {
recordEvent2Args(Level.WARN, marker, format, arg1, arg2);
}
public void warn(Marker marker, String format, Object... arguments) {
recordEventArgArray(Level.WARN, marker, format, arguments);
}
public void warn(Marker marker, String msg, Throwable t) {
recordEvent_0Args(Level.WARN, marker, msg, t);
}
public boolean isErrorEnabled() {
return RECORD_ALL_EVENTS;
}
public void error(String msg) {
recordEvent_0Args(Level.ERROR, null, msg, null);
}
public void error(String format, Object arg) {
recordEvent_1Args(Level.ERROR, null, format, arg);
}
public void error(String format, Object arg1, Object arg2) {
recordEvent2Args(Level.ERROR, null, format, arg1, arg2);
}
public void error(String format, Object... arguments) {
recordEventArgArray(Level.ERROR, null, format, arguments);
}
public void error(String msg, Throwable t) {
recordEvent_0Args(Level.ERROR, null, msg, t);
}
public boolean isErrorEnabled(Marker marker) {
return RECORD_ALL_EVENTS;
}
public void error(Marker marker, String msg) {
recordEvent_0Args(Level.ERROR, marker, msg, null);
}
public void error(Marker marker, String format, Object arg) {
recordEvent_1Args(Level.ERROR, marker, format, arg);
}
public void error(Marker marker, String format, Object arg1, Object arg2) {
recordEvent2Args(Level.ERROR, marker, format, arg1, arg2);
}
public void error(Marker marker, String format, Object... arguments) {
recordEventArgArray(Level.ERROR, marker, format, arguments);
}
public void error(Marker marker, String msg, Throwable t) {
recordEvent_0Args(Level.ERROR, marker, msg, t);
}
private void recordEvent_0Args(Level level, Marker marker, String msg, Throwable t) {
recordEvent(level, marker, msg, null, t);
}
private void recordEvent_1Args(Level level, Marker marker, String msg, Object arg1) {
recordEvent(level, marker, msg, new Object[] { arg1 }, null);
}
private void recordEvent2Args(Level level, Marker marker, String msg, Object arg1, Object arg2) {
if (arg2 instanceof Throwable) {
recordEvent(level, marker, msg, new Object[] { arg1 }, (Throwable) arg2);
} else {
recordEvent(level, marker, msg, new Object[] { arg1, arg2 }, null);
}
}
private void recordEventArgArray(Level level, Marker marker, String msg, Object[] args) {
Throwable throwableCandidate = MessageFormatter.getThrowableCandidate(args);
if (throwableCandidate != null) {
Object[] trimmedCopy = MessageFormatter.trimmedCopy(args);
recordEvent(level, marker, msg, trimmedCopy, throwableCandidate);
} else {
recordEvent(level, marker, msg, args, null);
}
}
// WARNING: this method assumes that any throwable is properly extracted
private void recordEvent(Level level, Marker marker, String msg, Object[] args, Throwable throwable) {
// System.out.println("recording logger:"+name+", msg:"+msg);
SubstituteLoggingEvent loggingEvent = new SubstituteLoggingEvent();
loggingEvent.setTimeStamp(System.currentTimeMillis());
loggingEvent.setLevel(level);
@ -35,262 +313,11 @@ public class EventRecodingLogger implements Logger {
loggingEvent.setLoggerName(name);
loggingEvent.setMarker(marker);
loggingEvent.setMessage(msg);
loggingEvent.setThreadName(Thread.currentThread().getName());
loggingEvent.setArgumentArray(args);
loggingEvent.setThrowable(throwable);
loggingEvent.setThreadName(Thread.currentThread().getName());
eventQueue.add(loggingEvent);
}
public boolean isTraceEnabled() {
return true;
}
public void trace(String msg) {
recordEvent(Level.TRACE, msg, null, null);
}
public void trace(String format, Object arg) {
recordEvent(Level.TRACE, format, new Object[] { arg }, null);
}
public void trace(String format, Object arg1, Object arg2) {
recordEvent(Level.TRACE, format, new Object[] { arg1, arg2 }, null);
}
public void trace(String format, Object... arguments) {
recordEvent(Level.TRACE, format, arguments, null);
}
public void trace(String msg, Throwable t) {
recordEvent(Level.TRACE, msg, null, t);
}
public boolean isTraceEnabled(Marker marker) {
return true;
}
public void trace(Marker marker, String msg) {
recordEvent(Level.TRACE, marker, msg, null, null);
}
public void trace(Marker marker, String format, Object arg) {
recordEvent(Level.TRACE, marker, format, new Object[] { arg }, null);
}
public void trace(Marker marker, String format, Object arg1, Object arg2) {
recordEvent(Level.TRACE, marker, format, new Object[] { arg1, arg2 }, null);
}
public void trace(Marker marker, String format, Object... argArray) {
recordEvent(Level.TRACE, marker, format, argArray, null);
}
public void trace(Marker marker, String msg, Throwable t) {
recordEvent(Level.TRACE, marker, msg, null, t);
}
public boolean isDebugEnabled() {
return true;
}
public void debug(String msg) {
recordEvent(Level.TRACE, msg, null, null);
}
public void debug(String format, Object arg) {
recordEvent(Level.DEBUG, format, new Object[] { arg }, null);
}
public void debug(String format, Object arg1, Object arg2) {
recordEvent(Level.DEBUG, format, new Object[] { arg1, arg2 }, null);
}
public void debug(String format, Object... arguments) {
recordEvent(Level.DEBUG, format, arguments, null);
}
public void debug(String msg, Throwable t) {
recordEvent(Level.DEBUG, msg, null, t);
}
public boolean isDebugEnabled(Marker marker) {
return true;
}
public void debug(Marker marker, String msg) {
recordEvent(Level.DEBUG, marker, msg, null, null);
}
public void debug(Marker marker, String format, Object arg) {
recordEvent(Level.DEBUG, marker, format, new Object[] { arg }, null);
}
public void debug(Marker marker, String format, Object arg1, Object arg2) {
recordEvent(Level.DEBUG, marker, format, new Object[] { arg1, arg2 }, null);
}
public void debug(Marker marker, String format, Object... arguments) {
recordEvent(Level.DEBUG, marker, format, arguments, null);
}
public void debug(Marker marker, String msg, Throwable t) {
recordEvent(Level.DEBUG, marker, msg, null, t);
}
public boolean isInfoEnabled() {
return true;
}
public void info(String msg) {
recordEvent(Level.INFO, msg, null, null);
}
public void info(String format, Object arg) {
recordEvent(Level.INFO, format, new Object[] { arg }, null);
}
public void info(String format, Object arg1, Object arg2) {
recordEvent(Level.INFO, format, new Object[] { arg1, arg2 }, null);
}
public void info(String format, Object... arguments) {
recordEvent(Level.INFO, format, arguments, null);
}
public void info(String msg, Throwable t) {
recordEvent(Level.INFO, msg, null, t);
}
public boolean isInfoEnabled(Marker marker) {
return true;
}
public void info(Marker marker, String msg) {
recordEvent(Level.INFO, marker, msg, null, null);
}
public void info(Marker marker, String format, Object arg) {
recordEvent(Level.INFO, marker, format, new Object[] { arg }, null);
}
public void info(Marker marker, String format, Object arg1, Object arg2) {
recordEvent(Level.INFO, marker, format, new Object[] { arg1, arg2 }, null);
}
public void info(Marker marker, String format, Object... arguments) {
recordEvent(Level.INFO, marker, format, arguments, null);
}
public void info(Marker marker, String msg, Throwable t) {
recordEvent(Level.INFO, marker, msg, null, t);
}
public boolean isWarnEnabled() {
return true;
}
public void warn(String msg) {
recordEvent(Level.WARN, msg, null, null);
}
public void warn(String format, Object arg) {
recordEvent(Level.WARN, format, new Object[] { arg }, null);
}
public void warn(String format, Object arg1, Object arg2) {
recordEvent(Level.WARN, format, new Object[] { arg1, arg2 }, null);
}
public void warn(String format, Object... arguments) {
recordEvent(Level.WARN, format, arguments, null);
}
public void warn(String msg, Throwable t) {
recordEvent(Level.WARN, msg, null, t);
}
public boolean isWarnEnabled(Marker marker) {
return true;
}
public void warn(Marker marker, String msg) {
recordEvent(Level.WARN, msg, null, null);
}
public void warn(Marker marker, String format, Object arg) {
recordEvent(Level.WARN, format, new Object[] { arg }, null);
}
public void warn(Marker marker, String format, Object arg1, Object arg2) {
recordEvent(Level.WARN, marker, format, new Object[] { arg1, arg2 }, null);
}
public void warn(Marker marker, String format, Object... arguments) {
recordEvent(Level.WARN, marker, format, arguments, null);
}
public void warn(Marker marker, String msg, Throwable t) {
recordEvent(Level.WARN, marker, msg, null, t);
}
public boolean isErrorEnabled() {
return true;
}
public void error(String msg) {
recordEvent(Level.ERROR, msg, null, null);
}
public void error(String format, Object arg) {
recordEvent(Level.ERROR, format, new Object[] { arg }, null);
}
public void error(String format, Object arg1, Object arg2) {
recordEvent(Level.ERROR, format, new Object[] { arg1, arg2 }, null);
}
public void error(String format, Object... arguments) {
recordEvent(Level.ERROR, format, arguments, null);
}
public void error(String msg, Throwable t) {
recordEvent(Level.ERROR, msg, null, t);
}
public boolean isErrorEnabled(Marker marker) {
return true;
}
public void error(Marker marker, String msg) {
recordEvent(Level.ERROR, marker, msg, null, null);
}
public void error(Marker marker, String format, Object arg) {
recordEvent(Level.ERROR, marker, format, new Object[] { arg }, null);
}
public void error(Marker marker, String format, Object arg1, Object arg2) {
recordEvent(Level.ERROR, marker, format, new Object[] { arg1, arg2 }, null);
}
public void error(Marker marker, String format, Object... arguments) {
recordEvent(Level.ERROR, marker, format, arguments, null);
}
public void error(Marker marker, String msg, Throwable t) {
recordEvent(Level.ERROR, marker, msg, null, t);
}
}

View File

@ -152,37 +152,15 @@ final public class MessageFormatter {
}
static final Throwable getThrowableCandidate(Object[] argArray) {
if (argArray == null || argArray.length == 0) {
return null;
}
final Object lastEntry = argArray[argArray.length - 1];
if (lastEntry instanceof Throwable) {
return (Throwable) lastEntry;
}
return null;
}
final public static FormattingTuple arrayFormat(final String messagePattern, final Object[] argArray) {
Throwable throwableCandidate = getThrowableCandidate(argArray);
Throwable throwableCandidate = MessageFormatter.getThrowableCandidate(argArray);
Object[] args = argArray;
if (throwableCandidate != null) {
args = trimmedCopy(argArray);
args = MessageFormatter.trimmedCopy(argArray);
}
return arrayFormat(messagePattern, args, throwableCandidate);
}
private static Object[] trimmedCopy(Object[] argArray) {
if (argArray == null || argArray.length == 0) {
throw new IllegalStateException("non-sensical empty or null argument array");
}
final int trimemdLen = argArray.length - 1;
Object[] trimmed = new Object[trimemdLen];
System.arraycopy(argArray, 0, trimmed, 0, trimemdLen);
return trimmed;
}
final public static FormattingTuple arrayFormat(final String messagePattern, final Object[] argArray, Throwable throwable) {
if (messagePattern == null) {
@ -411,4 +389,49 @@ final public class MessageFormatter {
sbuf.append(']');
}
/**
* Helper method to determine if an {@link Object} array contains a {@link Throwable} as last element
*
* @param argArray
* The arguments off which we want to know if it contains a {@link Throwable} as last element
* @return if the last {@link Object} in argArray is a {@link Throwable} this method will return it,
* otherwise it returns null
*/
public static Throwable getThrowableCandidate(final Object[] argArray) {
if (argArray == null || argArray.length == 0) {
return null;
}
final Object lastEntry = argArray[argArray.length - 1];
if (lastEntry instanceof Throwable) {
return (Throwable) lastEntry;
}
return null;
}
/**
* Helper method to get all but the last element of an array
*
* @param argArray
* The arguments from which we want to remove the last element
*
* @return a copy of the array without the last element
*/
public static Object[] trimmedCopy(final Object[] argArray) {
if (argArray == null || argArray.length == 0) {
throw new IllegalStateException("non-sensical empty or null argument array");
}
final int trimmedLen = argArray.length - 1;
Object[] trimmed = new Object[trimmedLen];
if (trimmedLen > 0) {
System.arraycopy(argArray, 0, trimmed, 0, trimmedLen);
}
return trimmed;
}
}

View File

@ -4,6 +4,7 @@ Bundle-SymbolicName: slf4j.api
Bundle-Name: slf4j-api
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Automatic-Module-Name: org.slf4j
Export-Package: org.slf4j;version=${parsedVersion.osgiVersion},
org.slf4j.spi;version=${parsedVersion.osgiVersion},
org.slf4j.helpers;version=${parsedVersion.osgiVersion},

View File

@ -0,0 +1,525 @@
package org.slf4j.event;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Marker;
import org.slf4j.helpers.BasicMarkerFactory;
import org.slf4j.helpers.SubstituteLogger;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import static org.junit.Assert.*;
public class EventRecodingLoggerTest {
private Queue<SubstituteLoggingEvent> queue;
private EventRecodingLogger logger;
private String message;
private Object param1;
private Object param2;
private Object param3;
private Object[] oneParam;
private Object[] twoParams;
private Object[] threeParams;
private Throwable exception;
private Marker marker;
@Before
public void setUp() {
queue = new LinkedBlockingQueue<SubstituteLoggingEvent>();
logger = new EventRecodingLogger(new SubstituteLogger("testLogger", queue, true), queue);
message = "Test message with 3 parameters {} {} {} {}";
param1 = 1;
param2 = 2;
param3 = 3;
oneParam = new Object[] { param1 };
twoParams = new Object[] { param1, param2 };
threeParams = new Object[] { param1, param2, param3 };
exception = new IllegalStateException("We just need an exception");
marker = new BasicMarkerFactory().getMarker("testMarker");
}
@After
public void tearDown() {
assertTrue(queue.isEmpty());
}
@Test
public void singleMessage() {
for (Level level : Level.values()) {
singleMessageCheck(level);
}
}
private void singleMessageCheck(Level level) {
switch (level) {
case TRACE:
logger.trace(message);
break;
case DEBUG:
logger.debug(message);
break;
case INFO:
logger.info(message);
break;
case WARN:
logger.warn(message);
break;
case ERROR:
logger.error(message);
break;
}
verifyMessageWithoutMarker(level, null, null);
}
@Test
public void oneParameter() {
for (Level level : Level.values()) {
oneParameterCheck(level);
}
}
private void oneParameterCheck(Level level) {
switch (level) {
case TRACE:
logger.trace(message, param1);
break;
case DEBUG:
logger.debug(message, param1);
break;
case INFO:
logger.info(message, param1);
break;
case WARN:
logger.warn(message, param1);
break;
case ERROR:
logger.error(message, param1);
break;
}
verifyMessageWithoutMarker(level, oneParam, null);
}
@Test
public void messageTwoParameters() {
for (Level level : Level.values()) {
messageTwoParametersCheck(level);
}
}
private void messageTwoParametersCheck(Level level) {
switch (level) {
case TRACE:
logger.trace(message, param1, param2);
break;
case DEBUG:
logger.debug(message, param1, param2);
break;
case INFO:
logger.info(message, param1, param2);
break;
case WARN:
logger.warn(message, param1, param2);
break;
case ERROR:
logger.error(message, param1, param2);
break;
}
verifyMessageWithoutMarker(level, twoParams, null);
}
@Test
public void traceMessageThreeParameters() {
for (Level level : Level.values()) {
threeParameterCheck(level);
}
}
private void threeParameterCheck(Level level) {
switch (level) {
case TRACE:
logger.trace(message, param1, param2, param3);
break;
case DEBUG:
logger.debug(message, param1, param2, param3);
break;
case INFO:
logger.info(message, param1, param2, param3);
break;
case WARN:
logger.warn(message, param1, param2, param3);
break;
case ERROR:
logger.error(message, param1, param2, param3);
break;
}
verifyMessageWithoutMarker(level, threeParams, null);
}
@Test
public void testMessageThrowable() {
for (Level level : Level.values()) {
throwableCheck(level);
}
}
private void throwableCheck(Level level) {
switch (level) {
case TRACE:
logger.trace(message, exception);
break;
case DEBUG:
logger.debug(message, exception);
break;
case INFO:
logger.info(message, exception);
break;
case WARN:
logger.warn(message, exception);
break;
case ERROR:
logger.error(message, exception);
break;
}
verifyMessageWithoutMarker(level, null, exception);
}
@Test
public void traceMessageOneParameterThrowable() {
for (Level level : Level.values()) {
oneParamThrowableCheck(level);
}
}
private void oneParamThrowableCheck(Level level) {
switch (level) {
case TRACE:
logger.trace(message, param1, exception);
break;
case DEBUG:
logger.debug(message, param1, exception);
break;
case INFO:
logger.info(message, param1, exception);
break;
case WARN:
logger.warn(message, param1, exception);
break;
case ERROR:
logger.error(message, param1, exception);
break;
}
verifyMessageWithoutMarker(level, oneParam, exception);
}
@Test
public void traceMessageTwoParametersThrowable() {
for (Level level : Level.values()) {
twoParamThrowableCheck(level);
}
}
private void twoParamThrowableCheck(Level level) {
switch (level) {
case TRACE:
logger.trace(message, param1, param2, exception);
break;
case DEBUG:
logger.debug(message, param1, param2, exception);
break;
case INFO:
logger.info(message, param1, param2, exception);
break;
case WARN:
logger.warn(message, param1, param2, exception);
break;
case ERROR:
logger.error(message, param1, param2, exception);
break;
}
verifyMessageWithoutMarker(level, twoParams, exception);
}
@Test
public void testMessageThreeParametersThrowable() {
for (Level level : Level.values()) {
messageWith3ArgsPlusException(level);
}
}
private void messageWith3ArgsPlusException(Level level) {
switch (level) {
case TRACE:
logger.trace(message, param1, param2, param3, exception);
break;
case DEBUG:
logger.debug(message, param1, param2, param3, exception);
break;
case INFO:
logger.info(message, param1, param2, param3, exception);
break;
case WARN:
logger.warn(message, param1, param2, param3, exception);
break;
case ERROR:
logger.error(message, param1, param2, param3, exception);
break;
}
verifyMessageWithoutMarker(level, threeParams, exception);
}
@Test
public void markerMessage() {
for (Level level : Level.values()) {
markerMessageCheck(level);
}
}
private void markerMessageCheck(Level level) {
switch (level) {
case TRACE:
logger.trace(marker, message);
break;
case DEBUG:
logger.debug(marker, message);
break;
case INFO:
logger.info(marker, message);
break;
case WARN:
logger.warn(marker, message);
break;
case ERROR:
logger.error(marker, message);
break;
}
verifyMessage(level, marker, null, null);
}
@Test
public void markerMessageOneParameter() {
for (Level level : Level.values()) {
markerMessageOneParameter(level);
}
}
private void markerMessageOneParameter(Level level) {
switch (level) {
case TRACE:
logger.trace(marker, message, param1);
break;
case DEBUG:
logger.debug(marker, message, param1);
break;
case INFO:
logger.info(marker, message, param1);
break;
case WARN:
logger.warn(marker, message, param1);
break;
case ERROR:
logger.error(marker, message, param1);
break;
}
verifyMessage(level, marker, oneParam, null);
}
@Test
public void traceMarkerMessageTwoParameters() {
for (Level level : Level.values()) {
markerMessageTwoParameters(level);
}
}
private void markerMessageTwoParameters(Level level) {
switch (level) {
case TRACE:
logger.trace(marker, message, param1, param2);
break;
case DEBUG:
logger.debug(marker, message, param1, param2);
break;
case INFO:
logger.info(marker, message, param1, param2);
break;
case WARN:
logger.warn(marker, message, param1, param2);
break;
case ERROR:
logger.error(marker, message, param1, param2);
break;
}
verifyMessage(level, marker, twoParams, null);
}
@Test
public void traceMarkerMessageThreeParameters() {
for (Level level : Level.values()) {
markerMessageThreeParameters(level);
}
}
private void markerMessageThreeParameters(Level level) {
switch (level) {
case TRACE:
logger.trace(marker, message, param1, param2, param3);
break;
case DEBUG:
logger.debug(marker, message, param1, param2, param3);
break;
case INFO:
logger.info(marker, message, param1, param2, param3);
break;
case WARN:
logger.warn(marker, message, param1, param2, param3);
break;
case ERROR:
logger.error(marker, message, param1, param2, param3);
break;
}
verifyMessage(level, marker, threeParams, null);
}
@Test
public void markerMessageThrowable() {
for (Level level : Level.values()) {
markerMessageThrowable(level);
}
}
private void markerMessageThrowable(Level level) {
switch (level) {
case TRACE:
logger.trace(marker, message, exception);
break;
case DEBUG:
logger.debug(marker, message, exception);
break;
case INFO:
logger.info(marker, message, exception);
break;
case WARN:
logger.warn(marker, message, exception);
break;
case ERROR:
logger.error(marker, message, exception);
break;
}
verifyMessage(level, marker, null, exception);
}
@Test
public void markerMessageOneParameterThrowable() {
for (Level level : Level.values()) {
markerMessageOneParameterThrowableCheck(level);
}
}
private void markerMessageOneParameterThrowableCheck(Level level) {
switch (level) {
case TRACE:
logger.trace(marker, message, param1, exception);
break;
case DEBUG:
logger.debug(marker, message, param1, exception);
break;
case INFO:
logger.info(marker, message, param1, exception);
break;
case WARN:
logger.warn(marker, message, param1, exception);
break;
case ERROR:
logger.error(marker, message, param1, exception);
break;
}
verifyMessage(level, marker, oneParam, exception);
}
@Test
public void traceMarkerMessageTwoParametersThrowable() {
for (Level level : Level.values()) {
markerMessageTwoParametersThrowableCheck(level);
}
}
private void markerMessageTwoParametersThrowableCheck(Level level) {
switch (level) {
case TRACE:
logger.trace(marker, message, param1, param2, exception);
break;
case DEBUG:
logger.debug(marker, message, param1, param2, exception);
break;
case INFO:
logger.info(marker, message, param1, param2, exception);
break;
case WARN:
logger.warn(marker, message, param1, param2, exception);
break;
case ERROR:
logger.error(marker, message, param1, param2, exception);
break;
}
verifyMessage(level, marker, twoParams, exception);
}
@Test
public void traceMarkerMessageThreeParametersThrowable() {
for (Level level : Level.values()) {
markerMessageThreeParametersThrowableCheck(level);
}
}
private void markerMessageThreeParametersThrowableCheck(Level level) {
switch (level) {
case TRACE:
logger.trace(marker, message, param1, param2, param3, exception);
break;
case DEBUG:
logger.debug(marker, message, param1, param2, param3, exception);
break;
case INFO:
logger.info(marker, message, param1, param2, param3, exception);
break;
case WARN:
logger.warn(marker, message, param1, param2, param3, exception);
break;
case ERROR:
logger.error(marker, message, param1, param2, param3, exception);
break;
}
verifyMessage(level, marker, threeParams, exception);
}
private void verifyMessageWithoutMarker(Level level, Object[] arguments, Throwable exception) {
verifyMessage(level, null, arguments, exception);
}
private void verifyMessage(Level level, Marker marker, Object[] arguments, Throwable exception) {
assertEquals("missing event: ", 1, queue.size());
SubstituteLoggingEvent event = queue.poll();
assertNotNull(event);
if (marker == null) {
assertNull(event.getMarker());
} else {
assertEquals(marker, event.getMarker());
}
assertEquals(message, event.getMessage());
if (arguments == null) {
assertNull(event.getArgumentArray());
} else {
assertArrayEquals(arguments, event.getArgumentArray());
}
assertEquals("wrong level: ", level, event.getLevel());
if (exception == null) {
assertNull(event.getThrowable());
} else {
assertEquals(exception, event.getThrowable());
}
}
}

View File

@ -22,7 +22,7 @@ abstract public class MultithreadedInitializationTest {
private final List<Logger> createdLoggers = Collections.synchronizedList(new ArrayList<Logger>());
final private AtomicLong eventCount = new AtomicLong(0);
protected final AtomicLong eventCount = new AtomicLong(0);
final private CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
int diff = new Random().nextInt(10000);

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>slf4j-ext</artifactId>

View File

@ -1,305 +0,0 @@
/**
* 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.ext;
import java.io.Serializable;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.beans.ExceptionListener;
/**
* Base class for Event Data. Event Data contains data to be logged about an
* event. Users may extend this class for each EventType they want to log.
*
* @author Ralph Goers
*/
public class EventData implements Serializable {
private static final long serialVersionUID = 153270778642103985L;
private Map<String, Object> eventData = new HashMap<String, Object>();
public static final String EVENT_MESSAGE = "EventMessage";
public static final String EVENT_TYPE = "EventType";
public static final String EVENT_DATETIME = "EventDateTime";
public static final String EVENT_ID = "EventId";
/**
* Default Constructor
*/
public EventData() {
}
/**
* Constructor to create event data from a Map.
*
* @param map
* The event data.
*/
public EventData(Map<String, Object> map) {
eventData.putAll(map);
}
/**
* Construct from a serialized form of the Map containing the RequestInfo
* elements
*
* @param xml
* The serialized form of the RequestInfo Map.
*/
@SuppressWarnings("unchecked")
public EventData(String xml) {
ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
try {
XMLDecoder decoder = new XMLDecoder(bais);
this.eventData = (Map<String, Object>) decoder.readObject();
} catch (Exception e) {
throw new EventException("Error decoding " + xml, e);
}
}
/**
* Serialize all the EventData items into an XML representation.
*
* @return an XML String containing all the EventData items.
*/
public String toXML() {
return toXML(eventData);
}
/**
* Serialize all the EventData items into an XML representation.
*
* @param map the Map to transform
* @return an XML String containing all the EventData items.
*/
public static String toXML(Map<String, Object> map) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
XMLEncoder encoder = new XMLEncoder(baos);
encoder.setExceptionListener(new ExceptionListener() {
public void exceptionThrown(Exception exception) {
exception.printStackTrace();
}
});
encoder.writeObject(map);
encoder.close();
return baos.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Retrieve the event identifier.
*
* @return The event identifier
*/
public String getEventId() {
return (String) this.eventData.get(EVENT_ID);
}
/**
* Set the event identifier.
*
* @param eventId
* The event identifier.
*/
public void setEventId(String eventId) {
if (eventId == null) {
throw new IllegalArgumentException("eventId cannot be null");
}
this.eventData.put(EVENT_ID, eventId);
}
/**
* Retrieve the message text associated with this event, if any.
*
* @return The message text associated with this event or null if there is
* none.
*/
public String getMessage() {
return (String) this.eventData.get(EVENT_MESSAGE);
}
/**
* Set the message text associated with this event.
*
* @param message
* The message text.
*/
public void setMessage(String message) {
this.eventData.put(EVENT_MESSAGE, message);
}
/**
* Retrieve the date and time the event occurred.
*
* @return The Date associated with the event.
*/
public Date getEventDateTime() {
return (Date) this.eventData.get(EVENT_DATETIME);
}
/**
* Set the date and time the event occurred in case it is not the same as when
* the event was logged.
*
* @param eventDateTime
* The event Date.
*/
public void setEventDateTime(Date eventDateTime) {
this.eventData.put(EVENT_DATETIME, eventDateTime);
}
/**
* Set the type of event that occurred.
*
* @param eventType
* The type of the event.
*/
public void setEventType(String eventType) {
this.eventData.put(EVENT_TYPE, eventType);
}
/**
* Retrieve the type of the event.
*
* @return The event type.
*/
public String getEventType() {
return (String) this.eventData.get(EVENT_TYPE);
}
/**
* Add arbitrary attributes about the event.
*
* @param name
* The attribute's key.
* @param obj
* The data associated with the key.
*/
public void put(String name, Serializable obj) {
this.eventData.put(name, obj);
}
/**
* Retrieve an event attribute.
*
* @param name
* The attribute's key.
* @return The value associated with the key or null if the key is not
* present.
*/
public Serializable get(String name) {
return (Serializable) this.eventData.get(name);
}
/**
* Populate the event data from a Map.
*
* @param data
* The Map to copy.
*/
public void putAll(Map<String, Object> data) {
this.eventData.putAll(data);
}
/**
* Returns the number of attributes in the EventData.
*
* @return the number of attributes in the EventData.
*/
public int getSize() {
return this.eventData.size();
}
/**
* Returns an Iterator over all the entries in the EventData.
*
* @return an Iterator that can be used to access all the event attributes.
*/
public Iterator<Map.Entry<String, Object>> getEntrySetIterator() {
return this.eventData.entrySet().iterator();
}
/**
* Retrieve all the attributes in the EventData as a Map. Changes to this map
* will be reflected in the EventData.
*
* @return The Map of attributes in this EventData instance.
*/
public Map<String, Object> getEventMap() {
return this.eventData;
}
/**
* Convert the EventData to a String.
*
* @return The EventData as a String.
*/
@Override
public String toString() {
return toXML();
}
/**
* Compare two EventData objects for equality.
*
* @param o
* The Object to compare.
* @return true if the objects are the same instance or contain all the same
* keys and their values.
*/
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof EventData || o instanceof Map)) {
return false;
}
Map<String, Object> map = (o instanceof EventData) ? ((EventData) o).getEventMap() : (Map<String, Object>) o;
return this.eventData.equals(map);
}
/**
* Compute the hashCode for this EventData instance.
*
* @return The hashcode for this EventData instance.
*/
@Override
public int hashCode() {
return this.eventData.hashCode();
}
}

View File

@ -1,106 +0,0 @@
/**
* 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.dummyExt;
import static org.junit.Assert.assertEquals;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.MDC;
import org.slf4j.ext.EventData;
import org.slf4j.ext.EventLogger;
public class EventLoggerTest {
ListAppender listAppender;
org.apache.log4j.Logger log4;
final static String EXPECTED_FILE_NAME = "EventLoggerTest.java";
@Before
public void setUp() throws Exception {
// start from a clean slate for each test
listAppender = new ListAppender();
listAppender.extractLocationInfo = true;
org.apache.log4j.Logger eventLogger = org.apache.log4j.Logger.getLogger("EventLogger");
eventLogger.addAppender(listAppender);
eventLogger.setLevel(org.apache.log4j.Level.TRACE);
eventLogger.setAdditivity(false);
// Items that apply to any activity
MDC.put("ipAddress", "192.168.1.110");
MDC.put("login", "TestUSer");
MDC.put("hostname", "localhost");
MDC.put("productName", "SLF4J");
MDC.put("locale", Locale.getDefault().getDisplayName());
MDC.put("timezone", TimeZone.getDefault().getDisplayName());
}
@After
public void tearDown() throws Exception {
MDC.clear();
}
void verify(LoggingEvent le, String expectedMsg) {
assertEquals(expectedMsg, le.getMessage());
assertEquals(EXPECTED_FILE_NAME, le.getLocationInformation().getFileName());
}
@Test
public void testEventLogger() {
EventData data[] = new EventData[2];
data[0] = new EventData();
data[0].setEventType("Login");
data[0].setEventId("1");
data[0].setEventDateTime(new Date());
data[0].put("Userid", "TestUser");
EventLogger.logEvent(data[0]);
data[1] = new EventData();
data[1].setEventType("Update");
data[1].setEventId("2");
data[1].setEventDateTime(new Date());
data[1].put("FileName", "/etc/hosts");
EventLogger.logEvent(data[1]);
assertEquals(2, listAppender.list.size());
for (int i = 0; i < 2; ++i) {
LoggingEvent event = listAppender.list.get(i);
verify(event, data[i].toXML());
LocationInfo li = event.getLocationInformation();
assertEquals(this.getClass().getName(), li.getClassName());
assertEquals(event.getMDC("hostname"), "localhost");
}
}
}

View File

@ -29,6 +29,6 @@ import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({ MDCStrLookupTest.class, XLoggerTest.class, EventLoggerTest.class })
@SuiteClasses({ MDCStrLookupTest.class, XLoggerTest.class })
public class PackageTest {
}

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

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>slf4j-jcl</artifactId>

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

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>slf4j-jdk14</artifactId>
@ -31,4 +31,5 @@
</dependency>
</dependencies>
</project>
</project>

View File

@ -4,6 +4,7 @@ Bundle-SymbolicName: slf4j.jdk14
Bundle-Name: slf4j-jdk14
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Automatic-Module-Name: org.slf4j.jul
Export-Package: org.slf4j.impl;version=${parsedVersion.osgiVersion}
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion},
org.slf4j.spi;version=${parsedVersion.osgiVersion},

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

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>slf4j-log4j12</artifactId>
@ -37,4 +37,5 @@
</dependency>
</dependencies>
</project>
</project>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>slf4j-migrator</artifactId>

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

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>slf4j-nop</artifactId>
@ -24,4 +24,5 @@
</dependency>
</dependencies>
</project>
</project>

View File

@ -4,6 +4,7 @@ Bundle-SymbolicName: slf4j.nop
Bundle-Name: slf4j-nop
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Automatic-Module-Name: org.slf4j.nop
Export-Package: org.slf4j.impl;version=${parsedVersion.osgiVersion}
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion},
org.slf4j.spi;version=${parsedVersion.osgiVersion},

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.33</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,614 @@
/**
* 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}
* 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>This class is a copy-and-paste of Log4j12LoggerAdapter from the
* slf4j-log4j12 module.</p>
*
* @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

@ -22,45 +22,32 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.slf4j.ext;
package org.slf4j;
/**
* Exception used to identify issues related to an event that is being logged.
*/
public class EventException extends RuntimeException {
import java.util.ArrayList;
import java.util.List;
private static final long serialVersionUID = -22873966112391992L;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
/**
* Default constructor.
*/
public EventException() {
super();
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();
}
}
/**
* Constructor that allows an exception message.
* @param exceptionMessage The exception message.
*/
public EventException(String exceptionMessage) {
super(exceptionMessage);
public void close() {
}
/**
* Constructor that chains another Exception or Error.
* @param originalException The original exception.
*/
public EventException(Throwable originalException) {
super(originalException);
public boolean requiresLayout() {
return false;
}
/**
* Constructor that chains another Exception or Error and also allows a message
* to be specified.
* @param exceptionMessage The exception message.
* @param originalException The original exception.
*/
public EventException(String exceptionMessage, Throwable originalException) {
super(exceptionMessage, originalException);
}
}

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

@ -22,43 +22,33 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.slf4j.ext;
package org.slf4j.impl;
import java.util.Random;
import org.junit.After;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import org.slf4j.spi.LocationAwareLogger;
/**
* Simple Logger used to log events. All events are directed to a logger named "EventLogger"
* with a level of INFO and with an Event marker.
*
* @author Ralph Goers
*/
public class EventLogger {
public class RecursiveInitializationTest {
private static final String FQCN = EventLogger.class.getName();
// value of LogManager.DEFAULT_CONFIGURATION_KEY;
static String CONFIG_FILE_KEY = "log4j.configuration";
static Marker EVENT_MARKER = MarkerFactory.getMarker("EVENT");
int diff = new Random().nextInt(10000);
String loggerName = "org.slf4j.impl.RecursiveInitializationTest";
private static LoggerWrapper eventLogger = new LoggerWrapper(LoggerFactory.getLogger("EventLogger"), FQCN);
/**
* There can only be a single EventLogger.
*/
private EventLogger() {
@After
public void tearDown() throws Exception {
System.clearProperty(CONFIG_FILE_KEY);
}
/**
* Logs the event.
*
* @param data The EventData.
*/
public static void logEvent(EventData data) {
if (eventLogger.instanceofLAL) {
((LocationAwareLogger) eventLogger.logger).log(EVENT_MARKER, FQCN, LocationAwareLogger.INFO_INT, data.toXML(), new Object[] { data }, null);
} else {
eventLogger.logger.info(EVENT_MARKER, data.toXML(), data);
}
@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

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>slf4j-simple</artifactId>
@ -31,4 +31,5 @@
</dependency>
</dependencies>
</project>
</project>

View File

@ -56,20 +56,20 @@ import org.slf4j.spi.LocationAwareLogger;
* </li>
*
* <li><code>org.slf4j.simpleLogger.defaultLogLevel</code> - Default log level
* for all instances of SimpleLogger. Must be one of ("trace", "debug", "info",
* "warn", "error" or "off"). If not specified, defaults to "info".</li>
* for all instances of SimpleLogger. Must be one of "trace", "debug", "info",
* "warn", "error" or "off". If not specified, defaults to "info".</li>
*
* <li><code>org.slf4j.simpleLogger.log.<em>a.b.c</em></code> - Logging detail
* level for a SimpleLogger instance named "a.b.c". Right-side value must be one
* <li><code>org.slf4j.simpleLogger.log.<em>com.foo.bar</em></code> - Logging detail
* level for a SimpleLogger instance named "com.foo.bar". Right-side value must be one
* of "trace", "debug", "info", "warn", "error" or "off". When a SimpleLogger
* named "a.b.c" is initialized, its level is assigned from this property. If
* unspecified, the level of nearest parent logger will be used, and if none is
* set, then the value specified by
* <code>org.slf4j.simpleLogger.defaultLogLevel</code> will be used.</li>
*
* <li><code>org.slf4j.simpleLogger.showDateTime</code> - Set to
* <code>true</code> if you want the current date and time to be included in
* output messages. Default is <code>false</code></li>
* <li><code>org.slf4j.simpleLogger.showDateTime</code> - If you would like the
* current date and time to be included in output messages, then set it to
* <code>true</code>. Default is <code>false</code></li>
*
* <li><code>org.slf4j.simpleLogger.dateTimeFormat</code> - The date and time
* format to be used in the output messages. The pattern describing the date and
@ -78,13 +78,17 @@ import org.slf4j.spi.LocationAwareLogger;
* <code>SimpleDateFormat</code></a>. If the format is not specified or is
* invalid, the number of milliseconds since start up will be output.</li>
*
* <li><code>org.slf4j.simpleLogger.showThreadName</code> -Set to
* <code>true</code> if you want to output the current thread name. Defaults to
* <li><code>org.slf4j.simpleLogger.showThreadName</code> - If you want to output
* the current thread name, then set it to <code>true</code>. Defaults to
* <code>true</code>.</li>
*
* <li><code>org.slf4j.simpleLogger.showLogName</code> - Set to
* <code>true</code> if you want the Logger instance name to be included in
* output messages. Defaults to <code>true</code>.</li>
* <li>(since version 1.7.33 and 2.0.0-alpha6) <code>org.slf4j.simpleLogger.showThreadId</code> -
* If you would like to output the current thread name, then set to
* <code>true</code>. Defaults to <code>false</code>.</li>
*
* <li><code>org.slf4j.simpleLogger.showLogName</code> - If you would like
* the Logger instance name to be included in output messages, then set it to
* <code>true</code>. Defaults to <code>true</code>.</li>
*
* <li><code>org.slf4j.simpleLogger.showShortLogName</code> - Set to
* <code>true</code> if you want the last component of the name to be included
@ -142,7 +146,8 @@ import org.slf4j.spi.LocationAwareLogger;
*/
public class SimpleLogger extends MarkerIgnoringBase {
private static final long serialVersionUID = -632788891211436180L;
private static final long serialVersionUID = -632788891211436180L;
private static long START_TIME = System.currentTimeMillis();
@ -151,13 +156,16 @@ public class SimpleLogger extends MarkerIgnoringBase {
protected static final int LOG_LEVEL_INFO = LocationAwareLogger.INFO_INT;
protected static final int LOG_LEVEL_WARN = LocationAwareLogger.WARN_INT;
protected static final int LOG_LEVEL_ERROR = LocationAwareLogger.ERROR_INT;
private static final String TID_PREFIX = "tid=";
// The OFF level can only be used in configuration files to disable logging.
// It has
// no printing method associated with it in o.s.Logger interface.
protected static final int LOG_LEVEL_OFF = LOG_LEVEL_ERROR + 10;
private static boolean INITIALIZED = false;
static SimpleLoggerConfiguration CONFIG_PARAMS = null;
static final private SimpleLoggerConfiguration CONFIG_PARAMS = new SimpleLoggerConfiguration();
static void lazyInit() {
if (INITIALIZED) {
@ -170,7 +178,6 @@ public class SimpleLogger extends MarkerIgnoringBase {
// external software might be invoking this method directly. Do not rename
// or change its semantics.
static void init() {
CONFIG_PARAMS = new SimpleLoggerConfiguration();
CONFIG_PARAMS.init();
}
@ -201,6 +208,8 @@ public class SimpleLogger extends MarkerIgnoringBase {
public static final String SHOW_THREAD_NAME_KEY = SimpleLogger.SYSTEM_PREFIX + "showThreadName";
public static final String SHOW_THREAD_ID_KEY = SimpleLogger.SYSTEM_PREFIX + "showThreadId";
public static final String DATE_TIME_FORMAT_KEY = SimpleLogger.SYSTEM_PREFIX + "dateTimeFormat";
public static final String SHOW_DATE_TIME_KEY = SimpleLogger.SYSTEM_PREFIX + "showDateTime";
@ -270,6 +279,12 @@ public class SimpleLogger extends MarkerIgnoringBase {
buf.append("] ");
}
if (CONFIG_PARAMS.showThreadId) {
buf.append(TID_PREFIX);
buf.append(Thread.currentThread().getId());
buf.append(' ');
}
if (CONFIG_PARAMS.levelInBrackets)
buf.append('[');
@ -312,12 +327,21 @@ public class SimpleLogger extends MarkerIgnoringBase {
throw new IllegalStateException("Unrecognized level [" + level + "]");
}
/**
* To avoid intermingling of log messages and associated stack traces, the two
* operations are done in a synchronized block.
*
* @param buf
* @param t
*/
void write(StringBuilder buf, Throwable t) {
PrintStream targetStream = CONFIG_PARAMS.outputChoice.getTargetPrintStream();
targetStream.println(buf.toString());
writeThrowable(t, targetStream);
targetStream.flush();
synchronized (CONFIG_PARAMS) {
targetStream.println(buf.toString());
writeThrowable(t, targetStream);
targetStream.flush();
}
}
protected void writeThrowable(Throwable t, PrintStream targetStream) {

View File

@ -45,6 +45,13 @@ public class SimpleLoggerConfiguration {
private static final boolean SHOW_THREAD_NAME_DEFAULT = true;
boolean showThreadName = SHOW_THREAD_NAME_DEFAULT;
/**
* See https://jira.qos.ch/browse/SLF4J-499
* @since 1.7.33 and 2.0.0-alpha6
*/
private static final boolean SHOW_THREAD_ID_DEFAULT = false;
boolean showThreadId = SHOW_THREAD_ID_DEFAULT;
final static boolean SHOW_LOG_NAME_DEFAULT = true;
boolean showLogName = SHOW_LOG_NAME_DEFAULT;
@ -77,6 +84,8 @@ public class SimpleLoggerConfiguration {
showShortLogName = getBooleanProperty(SimpleLogger.SHOW_SHORT_LOG_NAME_KEY, SHOW_SHORT_LOG_NAME_DEFAULT);
showDateTime = getBooleanProperty(SimpleLogger.SHOW_DATE_TIME_KEY, SHOW_DATE_TIME_DEFAULT);
showThreadName = getBooleanProperty(SimpleLogger.SHOW_THREAD_NAME_KEY, SHOW_THREAD_NAME_DEFAULT);
showThreadId = getBooleanProperty(SimpleLogger.SHOW_THREAD_ID_KEY, SHOW_THREAD_ID_DEFAULT);
dateTimeFormatStr = getStringProperty(SimpleLogger.DATE_TIME_FORMAT_KEY, DATE_TIME_FORMAT_STR_DEFAULT);
levelInBrackets = getBooleanProperty(SimpleLogger.LEVEL_IN_BRACKETS_KEY, LEVEL_IN_BRACKETS_DEFAULT);
warnLevelString = getStringProperty(SimpleLogger.WARN_LEVEL_STRING_KEY, WARN_LEVELS_STRING_DEFAULT);

View File

@ -5,6 +5,7 @@ Bundle-Name: slf4j-simple
Bundle-Vendor: SLF4J.ORG
Require-Bundle: slf4j.api
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Automatic-Module-Name: org.slf4j.simple
Export-Package: org.slf4j.impl;version=${parsedVersion.osgiVersion}
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion},
org.slf4j.spi;version=${parsedVersion.osgiVersion},

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2004-2012 QOS.ch
* Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland)
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
@ -31,6 +31,7 @@ import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.regex.Pattern;
import org.junit.After;
import org.junit.Before;
@ -52,6 +53,8 @@ public class SimpleLoggerTest {
public void after() {
System.clearProperty(A_KEY);
System.clearProperty(SimpleLogger.CACHE_OUTPUT_STREAM_STRING_KEY);
System.clearProperty(SimpleLogger.SHOW_THREAD_ID_KEY);
System.clearProperty(SimpleLogger.SHOW_THREAD_NAME_KEY);
System.setErr(original);
}
@ -120,4 +123,30 @@ public class SimpleLoggerTest {
replacement.flush();
assertTrue(bout.toString().contains("INFO org.slf4j.impl.SimpleLoggerTest - hello"));
}
@Test
public void testTheadIdWithoutThreadName () {
System.setProperty(SimpleLogger.SHOW_THREAD_NAME_KEY, Boolean.FALSE.toString());
String patternStr = "^tid=\\d{1,12} INFO org.slf4j.impl.SimpleLoggerTest - hello";
commonTestThreadId(patternStr);
}
@Test
public void testThreadId() {
String patternStr = "^\\[.*\\] tid=\\d{1,12} INFO org.slf4j.impl.SimpleLoggerTest - hello";
commonTestThreadId(patternStr);
}
private void commonTestThreadId(String patternStr) {
System.setErr(replacement);
System.setProperty(SimpleLogger.SHOW_THREAD_ID_KEY, Boolean.TRUE.toString());
SimpleLogger.init();
SimpleLogger simpleLogger = new SimpleLogger(this.getClass().getName());
simpleLogger.info("hello");
replacement.flush();
String output = bout.toString();
System.out.println(patternStr);
System.out.println(output);
assertTrue(Pattern.compile(patternStr).matcher(output).lookingAt());
}
}

View File

@ -0,0 +1,128 @@
/**
* Copyright (c) 2004-2021 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.simple.multiThreadedExecution;
import java.io.PrintStream;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Tests that output in multi-threaded environments is not mingled.
*
* See also https://jira.qos.ch/browse/SLF4J-515
*/
public class MultithereadedExecutionTest {
private static int THREAD_COUNT = 2;
private static long TEST_DURATION_IN_MILLIS = 100;
private Thread[] threads = new Thread[THREAD_COUNT];
private final PrintStream oldOut = System.out;
StateCheckingPrintStream scps = new StateCheckingPrintStream(oldOut);
volatile boolean signal = false;
@Before
public void setup() {
System.setErr(scps);
// System.setProperty(SimpleLogger.LOG_FILE_KEY, "System.err");
// LoggerFactoryFriend.reset();
}
@After
public void tearDown() throws Exception {
// LoggerFactoryFriend.reset();
// System.clearProperty(SimpleLogger.LOG_FILE_KEY);
System.setErr(oldOut);
}
@Test
public void test() throws Throwable {
WithException withException = new WithException();
Other other = new Other();
threads[0] = new Thread(withException);
threads[1] = new Thread(other);
threads[0].start();
threads[1].start();
Thread.sleep(TEST_DURATION_IN_MILLIS);
signal = true;
threads[0].join();
threads[1].join();
if (withException.throwable != null) {
throw withException.throwable;
}
if (other.throwable != null) {
throw other.throwable;
}
}
class WithException implements Runnable {
volatile Throwable throwable;
Logger logger = LoggerFactory.getLogger(WithException.class);
public void run() {
int i = 0;
while (!signal) {
try {
logger.info("Hello {}", i, new Throwable("i=" + i));
i++;
} catch (Throwable t) {
throwable = t;
MultithereadedExecutionTest.this.signal = true;
return;
}
}
}
}
class Other implements Runnable {
volatile Throwable throwable;
Logger logger = LoggerFactory.getLogger(Other.class);
public void run() {
int i = 0;
while (!signal) {
try {
logger.info("Other {}", i++);
} catch (Throwable t) {
throwable = t;
MultithereadedExecutionTest.this.signal = true;
return;
}
}
}
}
}

View File

@ -0,0 +1,141 @@
/**
* Copyright (c) 2004-2021 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.simple.multiThreadedExecution;
import java.io.PrintStream;
import java.util.regex.Pattern;
/**
* This PrintStream checks that output lines are in an expected order.
*
* @author ceki
*/
public class StateCheckingPrintStream extends PrintStream {
enum State {
INITIAL, UNKNOWN, HELLO, THROWABLE, AT1, AT2, OTHER;
}
volatile State currentState = State.INITIAL;
public StateCheckingPrintStream(PrintStream ps) {
super(ps);
}
public void print(String s) {
}
public void println(String s) {
State next = computeState(s);
//System.out.println(next + " " + s);
switch (currentState) {
case INITIAL:
currentState = next;
break;
case UNKNOWN:
// ignore garbage
currentState = next;
break;
case OTHER:
if (next == State.UNKNOWN) {
currentState = State.UNKNOWN;
return;
}
if (next != State.OTHER && next != State.HELLO) {
throw badState(s, currentState, next);
}
currentState = next;
break;
case HELLO:
if (next != State.THROWABLE) {
throw badState(s, currentState, next);
}
currentState = next;
break;
case THROWABLE:
if (next != State.AT1) {
throw badState(s, currentState, next);
}
currentState = next;
break;
case AT1:
if (next != State.AT2) {
throw badState(s, currentState, next);
}
currentState = next;
break;
case AT2:
currentState = next;
break;
default:
throw new IllegalStateException("Unreachable code");
}
}
private IllegalStateException badState(String s, State currentState2, State next) {
return new IllegalStateException("Unexpected state " + next + " for current state " + currentState2 + " for " + s);
}
String OTHER_PATTERN_STR = ".*Other \\d{1,5}";
String HELLO_PATTERN_STR = ".*Hello \\d{1,5}";
String THROWABLE_PATTERN_STR = "java.lang.Throwable: i=\\d{1,5}";
String AT1_PATTERN_STR = "\\s*at " + this.getClass().getPackage().getName() + ".*";
String AT2_PATTERN_STR = "\\s*at " + ".*Thread.java.*";
Pattern PATTERN_OTHER = Pattern.compile(OTHER_PATTERN_STR);
Pattern PATTERN_HELLO = Pattern.compile(HELLO_PATTERN_STR);
Pattern PATTERN_THROWABLE = Pattern.compile(THROWABLE_PATTERN_STR);
Pattern PATTERN_AT1 = Pattern.compile(AT1_PATTERN_STR);
Pattern PATTERN_AT2 = Pattern.compile(AT2_PATTERN_STR);
private State computeState(String s) {
if (PATTERN_OTHER.matcher(s).matches()) {
return State.OTHER;
} else if (PATTERN_HELLO.matcher(s).matches()) {
return State.HELLO;
} else if (PATTERN_THROWABLE.matcher(s).matches()) {
return State.THROWABLE;
} else if (PATTERN_AT1.matcher(s).matches()) {
return State.AT1;
} else if (PATTERN_AT2.matcher(s).matches()) {
return State.AT2;
} else {
return State.UNKNOWN;
}
}
public void println(Object o) {
println(o.toString());
}
}

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>1.7.25</version>
<version>1.7.33</version>
</parent>
<artifactId>slf4j-site</artifactId>
@ -30,6 +30,37 @@
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven-source-plugin.version}</version>
<configuration>
<includes>
<include>**/META-INF/*</include>
</includes>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
@ -41,4 +72,4 @@
</plugins>
</build>
</project>
</project>

View File

@ -71,7 +71,7 @@
<ul>
<li><a
href="http://jira.qos.ch/issues/?jql=project%20%3D%20SLF4J">Search for
href="https://jira.qos.ch/issues/?jql=project%3DSLF4J">Search for
SLF4J bugs</a></li>
</ul>