Compare commits

..

58 Commits

Author SHA1 Message Date
ceki 61400453cd start work on 2.0.19-SNAPSHOT
Signed-off-by: ceki <ceki@qos.ch>
2026-05-12 20:37:36 +02:00
ceki 58b66c2c7e update central-publishing-maven-plugin
Signed-off-by: ceki <ceki@qos.ch>
2026-05-12 20:32:21 +02:00
ceki be4841cce8 prepare release 2.0.18
Signed-off-by: ceki <ceki@qos.ch>
2026-05-12 20:15:59 +02:00
ceki d2073bece8 minor refactoring, javadoc changes
Signed-off-by: ceki <ceki@qos.ch>
2025-11-24 17:51:51 +01:00
ceki 32a9854cf4 add a trivial test for CONFIG_PARAMS.warnLevelString
Signed-off-by: ceki <ceki@qos.ch>
2025-11-03 15:24:43 +01:00
ceki 77936c6f1f CONFIG_PARAMS.warnLevelString should be taken into account
See https://github.com/qos-ch/slf4j/issues/471

Signed-off-by: ceki <ceki@qos.ch>
2025-11-03 14:31:01 +01:00
ceki 34c9d30af5 extract first marker when caller locationAwareLogger
Signed-off-by: ceki <ceki@qos.ch>
2025-11-01 20:09:13 +01:00
ceki 902b463957 remove cruft
Signed-off-by: ceki <ceki@qos.ch>
2025-10-01 16:00:03 +02:00
ceki b3c2f16f12 security manager is no longer supported in later JDKs
Signed-off-by: ceki <ceki@qos.ch>
2025-10-01 15:59:29 +02:00
ceki 9468c7a28f remove unneccessary and unused files
Signed-off-by: ceki <ceki@qos.ch>
2025-10-01 15:58:52 +02:00
Ceki Gulcu 183aaa5070 start work on 2.0.18-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2025-02-25 18:40:43 +01:00
Ceki Gulcu c233ea1932 prepare release 2.0.17
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2025-02-25 17:36:36 +01:00
Ceki Gulcu 4b4d533771 In SLF4JProviders, move initialization of the markerFactory and
mdcAdapter fields to the constructor.

Added comments regarding LoggerFactory expectation of providers to
initialize their MDCAdapter and markerFactory field as early as
possible, preferably at construction time.

Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2025-02-07 10:36:45 +01:00
Ceki Gulcu 9349d64f95 In response to issue 450, moved the binding of the MDCAdapter in the
MDC class from the static initializer to the LoggerFactory.bind method.

In case MDC methods are called before LoggerFactory, the various methods
in MDC have been modified to go through the getMDCAdapter method which
checks for this rare case.

https://github.com/qos-ch/slf4j/issues/450

Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2025-02-07 10:05:06 +01:00
Piotr P. Karwasz 0def25ebfa Replace license names with SPDX identifiers
As suggested by [Maven documentation](https://maven.apache.org/pom.html#Licenses) the `/project/licenses/licence/name` element in the POM file should contain a SPDX identifier of the license.
The license element is often used by external tools, such as SBOM generators.

This PR:

- Replaces the current content of the `<name>` element with the appropriate SPDX identifier.
- Follows all HTTP 301 redirections of the currently provided license URLs.

Signed-off-by: Piotr P. Karwasz <piotr.github@karwasz.org>
2024-12-10 11:01:56 +01:00
Ceki Gulcu 69c333de28 fix issues/425
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-10-21 20:50:59 +02:00
Ceki Gülcü 2470fad4fd
Update README.md 2024-09-22 11:14:48 +02:00
Ceki Gülcü c2c29fec98
Update README.md 2024-09-22 11:12:06 +02:00
Ceki Gulcu 0597225b5b README updates
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-09-22 11:07:14 +02:00
Ceki Gulcu f7b34c2e60 fix incorrect interpretation of Level.OFF and Level.ALL in SLF4JPlatformLogger
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-09-21 13:16:33 +02:00
Ceki Gulcu 4fa92fc007 start work on 2.0.17-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-10 11:38:41 +02:00
Ceki Gulcu 101086ba35 prepare release 2.0.16
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-10 11:11:51 +02:00
Ceki Gulcu 8ae0efca23 class.getModule is new in Java9
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-10 11:00:18 +02:00
Ceki Gulcu 3ff00870b3 print connected provider only if DEBUG level for internal reporting is enabled
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-10 09:49:56 +02:00
Manfred Hanke 0df43e9e53 fix javadoc of Slf4jEnvUtil
resolves #423

Signed-off-by: Manfred Hanke <Manfred.Hanke@tngtech.com>
2024-08-08 22:24:18 +02:00
Ceki Gulcu 46b5ea54a6 start work on 2.0.16-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-08 16:48:10 +02:00
Ceki Gulcu 5321a975d4 prepare release 2.0.15
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-08 14:56:10 +02:00
Ceki Gulcu 09111e8c1e added copyright, @since to Slf4jEnvUtil
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-07 17:46:14 +02:00
Ceki Gulcu 6a04f67fdd start work on version 2.0.15-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-07 17:31:29 +02:00
Ceki Gulcu 03aa6b915a prepare release 2.0.14
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-06 22:30:45 +02:00
Ceki Gulcu 7c3b0ef011 added method returning slf4j version
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-06 22:17:49 +02:00
Ceki Gulcu 42810107b0 LoggerFactory emits 'SLF4J(I): Connected with provider of type'
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-05 22:10:08 +02:00
Ceki Gulcu 982e4b067f clearer assertion take II
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-04 21:30:31 +02:00
Ceki Gulcu dd4486b5c5 clearer assertion
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-04 21:25:43 +02:00
Ceki Gulcu 1d82519b07 start work on 2.0.14-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-04-12 18:05:28 +02:00
Ceki Gulcu 5ffbc67def prepare release 2.0.13
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-04-12 16:21:00 +02:00
Ceki Gulcu 3386517ad6 fix issues/409 SLF4J-601, wrong classname when using slf4j inside a wrapper
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-04-12 15:47:48 +02:00
Ceki Gulcu 448bca173c start work on 2.0.13-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-02-05 22:58:12 +01:00
Ceki Gulcu 955209464d increase leniency count
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-02-05 22:32:22 +01:00
Ceki Gulcu c1473c957a prepare release 2.0.12
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-02-05 22:21:34 +01:00
Ceki Gulcu 98932348fb minor reminder
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-02-05 22:20:48 +01:00
Ceki Gulcu c52da92599 revert Util.report methods removed by mistake
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-02-05 22:17:54 +01:00
Ceki Gulcu da91e4f219 export provider packages, allow reflection by org.slf4j
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-02-05 21:45:58 +01:00
Ceki Gulcu 8c4ea8f225 more comments
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-23 15:51:31 +01:00
Ceki Gulcu 6b2921a523 start wotk on 2.0.12-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 20:50:02 +01:00
Ceki Gulcu 3f4717c44e get javadoc:aggregate command to work
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 20:48:59 +01:00
Ceki Gulcu d9145fba56 prepare release 2.0.11
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 18:58:10 +01:00
Ceki Gulcu 68ff7064ec acceptance test, disabled for the moment
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 18:50:54 +01:00
Guillaume Nodet db8cd90c10 Use computeIfAbsent with a protected method, make reset protected
Signed-off-by: Guillaume Nodet <gnodet@gmail.com>
2024-01-08 17:39:25 +01:00
Guillaume Nodet d564304a61 Use computeIfAbsent with a protected method, make reset protected
Signed-off-by: Guillaume Nodet <gnodet@gmail.com>
2024-01-08 17:39:25 +01:00
Ceki Gulcu ef8dda71dd javadoc changed for SimpleLogger constructor
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 15:23:23 +01:00
Ceki Gulcu fe42ecb5f7 change constructor access modifier instead of
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 15:16:08 +01:00
Ceki Gulcu 7029a8b7fd add renderLevel method in SimpleLogger
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 15:02:22 +01:00
Ceki Gulcu 8c873b2e75 start work on 2.0.11-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-12-29 00:03:40 +01:00
Ceki Gulcu 7bcee9aa1f javadoc configuration tweak
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-12-29 00:02:38 +01:00
Ceki Gulcu 6fe9c07113 more javadoc adjustments
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-12-28 21:48:34 +01:00
Ceki Gulcu df562c22d8 migrator should have javadocs
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-12-28 21:38:38 +01:00
Ceki Gulcu 6d39ca8bf9 prepare release 2.0.10
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-12-28 21:14:08 +01:00
125 changed files with 1693 additions and 2728 deletions

View File

@ -2,31 +2,33 @@
The Simple Logging Facade for Java (SLF4J) serves as a simple facade
or abstraction for various logging frameworks (e.g. java.util.logging,
logback, reload4j, log4j 2.x) allowing the end user to plug in the desired logging
framework at deployment time.
logback, reload4j, log4j 2.x, logevents, penna, rainbowgum, tinylog)
allowing the end user to plug in the desired logging framework at
deployment time.
More information can be found on the [SLF4J website](http://www.slf4j.org).
# Build Status
[![Build Status](https://travis-ci.org/qos-ch/slf4j.svg)](https://travis-ci.org/qos-ch/slf4j)
# Search org.slf4j artifacts on Maven Central
[![Maven Central](https://img.shields.io/badge/Search%20org%2Eslf4j%20artifacts%20on%20Maven%20Central-2.0.x-green)](https://search.maven.org/search?q=g:org.slf4j%20AND%20v:2.0.%3F)
[![Maven Central](https://img.shields.io/badge/Search%20org%2Eslf4j%20artifacts%20on%20Maven%20Central-2.0.x-green)](https://central.sonatype.com/search?namespace=org.slf4j)
# In case of problems
In case of problems please do not hesitate to post an e-mail message
on the slf4j-user@qos.ch mailing list. However, please do not
directly e-mail SLF4J developers. The answer to your question might
be useful to other users. Moreover, there are many knowledgeable users
on the slf4j-user mailing lists who can quickly answer your
questions.
on the [slf4j-user@qos.ch](https://mailman.qos.ch/cgi-bin/mailman/listinfo/slf4j-user)
mailing list or to start a <a
href="https://github.com/qos-ch/slf4j/discussions">discussion</a> on
github. However, please do not directly e-mail SLF4J developers. The
answer to your question might be useful to other users. Moreover,
there are many knowledgeable users on the slf4j-user mailing lists who
can quickly answer your questions.
# Urgent issues
For urgent issues do not hesitate to [champion a release](https://github.com/sponsors/qos-ch/sponsorships?tier_id=77436).
In principle, most championed issues are solved within 3 business days ensued by a release.
For urgent issues do not hesitate to [champion a
release](https://github.com/sponsors/qos-ch/sponsorships?tier_id=77436).
In principle, most championed issues are solved within 3 business days
ensued by a release.
# How to build SLF4J
@ -43,14 +45,13 @@ process:
1. Start a discussion on the [slf4j-dev mailing
list](http://www.slf4j.org/mailing-lists.html) about your proposed
change. Alternately, file a [bug
report](http://www.slf4j.org/bug-reporting.html) to initiate the
discussion. Note that we ask pull requests to be linked to a [Jira
ticket](https://jira.qos.ch/).
report](https://github.com/qos-ch/slf4j/issues) on github to initiate the
discussion.
2. Fork qos-ch/slf4j. Ideally, create a new branch from your fork for
your contribution to make it easier to merge your changes back.
3. Make your changes on the branch you hopefully created in Step 2. Be
3. Make your changes on the branch created in Step 2. Be
sure that your code passes existing unit tests. Please add unit tests
for your work if appropriate. It usually is.
@ -61,10 +62,8 @@ will be automatically rejected by the [DCO GitHub
check](https://probot.github.io/apps/dco/) application.
5. Push your changes to your fork/branch in GitHub. Don't push it to
your master! If you do it will make it harder to submit new changes
your master! If you do, it will make it harder to submit new changes
later.
6. Submit a pull request to SLF4J from your commit page on GitHub.
7. Did we mention that you will be asked to link your pull request
with a Jira ticket?

View File

@ -82,12 +82,12 @@
</target>
<target name="testAll" depends="init,
testNoProvider150,
testNoProvider150,
testMismatch,
testMatch,
testMultiBinding,
testFuture_16Series,
testActiveSecurityManager">
testMultiBinding,
testFuture_16Series"
>
</target>
@ -201,7 +201,7 @@
<property name="path_to_policy" value="file:./src/policy/java-under-ant.policy"/>
</target>
<!-- no longer supported in JDK 24 and later -->
<target name="testActiveSecurityManager" depends="setPathToPolicy_FromTop, setPathToPolicy_FromIntegration">
<junit printsummary="yes" fork="no" haltonfailure="yes">
<jvmarg value="-Djava.security.manager"/>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>

View File

@ -27,6 +27,7 @@ package org.slf4j;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.slf4j.helpers.Reporter.SLF4J_INTERNAL_VERBOSITY_KEY;
import java.io.PrintStream;
import java.util.Random;
@ -43,11 +44,13 @@ public class CompatibilityAssertionTest {
@Before
public void setUp() throws Exception {
System.setProperty(SLF4J_INTERNAL_VERBOSITY_KEY, "debug");
System.setErr(sps);
}
@After
public void tearDown() throws Exception {
System.clearProperty(SLF4J_INTERNAL_VERBOSITY_KEY);
System.setErr(old);
}
@ -57,8 +60,10 @@ public class CompatibilityAssertionTest {
String msg = "hello world " + diff;
logger.info(msg);
assertEquals(2, sps.stringList.size());
String s0 = (String) sps.stringList.get(0);
assertTrue(s0.startsWith("SLF4J(I): Connected with provider of type [org.slf4j.simple.SimpleServiceProvider"));
assertTrue(s0.startsWith("SLF4J(D): Connected with provider of type [org.slf4j.simple.SimpleServiceProvider]"));
String s1 = (String) sps.stringList.get(1);
assertTrue(s1.contains(msg));

View File

@ -55,11 +55,13 @@ public class MultiBindingAssertionTest {
String msg = "hello world " + diff;
logger.info(msg);
List<String> list = sps.stringList;
assertMsgContains(list, 0, "Class path contains multiple SLF4J providers.");
assertMsgContains(list, 1, "Found provider");
assertMsgContains(list, 2, "Found provider");
assertMsgContains(list, 3, "See https://www.slf4j.org/codes.html#multiple_bindings for an explanation.");
assertMsgContains(list, 4, "SLF4J(I): Connected with provider of type [org.slf4j.simple.SimpleServiceProvider");
int line = 0;
assertMsgContains(list, line++, "Class path contains multiple SLF4J providers.");
assertMsgContains(list, line++, "Found provider");
assertMsgContains(list, line++, "Found provider");
assertMsgContains(list, line++, "See https://www.slf4j.org/codes.html#multiple_bindings for an explanation.");
//assertMsgContains(list, line++, "SLF4J(D): Connected with provider of type [");
}
void assertMsgContains(List<String> strList, int index, String msg) {

View File

@ -1,68 +0,0 @@
<?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">
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jcl-over-slf4j-blackbox</artifactId>
<packaging>jar</packaging>
<name>jcl-over-slf4j blackbox testing</name>
<description>jcl-over-slf4j blackbox testing</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>
<properties>
<jdk.version>${jdk9.version}</jdk.version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,7 +0,0 @@
module org.apache.commons.logging.blackbox {
requires org.slf4j;
requires org.slf4j.jul;
requires org.apache.commons.logging;
requires java.logging;
requires junit;
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
@ -14,12 +14,12 @@
<artifactId>jcl-over-slf4j</artifactId>
<packaging>jar</packaging>
<name>JCL 1.2 implemented over SLF4J</name>
<description>Jakarta/Apache commons logging 1.2 implemented over SLF4J</description>
<description>JCL 1.2 implemented over SLF4J</description>
<url>http://www.slf4j.org</url>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<name>Apache-2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>

View File

@ -1,151 +0,0 @@
/**
* <p>Jakarta Commons Logging implemented over SLF4J.</p>
*
*
* <h3>Overview</h3>
*
* <p>This package contains the same public user interface as <a
* href="http://jakarta.apache.org/commons/logging/">Jakarta Commons
* Logging (JCL)</a>. <b>It is intended as a 100% compatible drop-in
* replacement for the original JCL version 1.0.4</b>.
* </p>
*
* <p>As the original JCL version 1.0.4, the present version supports
* various logging APIs. It differs from the original in implementation
* but not the public API. This implementation uses SLF4J under the
* covers. As such, all the logging systems that SLF4J supports,
* e.g. NOP, Simple, logback, java.util.logging, log4j 1.x are supported
* indirectly by this version of JCL via SLF4J.
* </p>
*
* <h3>Quick Start Guide</h3>
*
* <p>For those impatient to just get on with it, the following example
* illustrates the typical declaration and use of a logger that is named (by
* convention) after the calling class:
*
* <pre>
* import org.apache.commons.logging.Log;
* import org.apache.commons.logging.LogFactory;
*
* public class Foo {
*
* static Log log = LogFactory.getLog(Foo.class);
*
* public void foo() {
* ...
* try {
* if (log.isDebugEnabled()) {
* log.debug("About to do something to object " + name);
* }
* name.bar();
* } catch (IllegalStateException e) {
* log.error("Something bad happened to " + name, e);
* }
* ...
* }
* </pre>
*
* <h3>Configuring the Commons Logging Package</h3>
*
* <p>In this version of JCL, the selection of the logging system to use
* is chosen by SLF4J at initialization time. Consequently, all JCL-specific
* configuration parameters are ignored.
* </p>
*
* <h4>Choosing a <code>LogFactory</code> Implementation</h4>
*
* <p>From an application perspective, the first requirement is to
* retrieve an object reference to the <code>LogFactory</code> instance
* that will be used to create <code><a href="Log.html">Log</a></code>
* instances for this application. This is normally accomplished by
* calling the static <code>getFactory()</code> method. This method
* always returns the same factory, i.e. a unique instance of the <a
* href="impl/SLF4FLogFactory.html">SLF4FLogFactory</a> class.
* </p>
*
*
*
* <h4>Configuring the Underlying Logging System</h4>
*
* <p>The basic principle is that the user is totally responsible for the
* configuration of the underlying logging system.
* Commons-logging should not change the existing configuration.</p>
*
* <p>Each individual <a href="Log.html">Log</a> implementation may
* support its own configuration properties. These will be documented in the
* class descriptions for the corresponding implementation class.</p>
*
* <p>Finally, some <code>Log</code> implementations (such logback or log4j)
* require an external configuration file for the entire logging environment.
* This file should be prepared in a manner that is specific to the actual logging
* technology being used.</p>
*
*
* <h3>Using the Logging Package APIs</h3>
*
* <p>Use of the Logging Package APIs, from the perspective of an application
* component, consists of the following steps:</p>
* <ol>
* <li>Acquire a reference to an instance of
* <a href="Log.html">org.apache.commons.logging.Log</a>, by calling the
* factory method
* <a href="LogFactory.html#getInstance(java.lang.String)">
* LogFactory.getInstance(String name)</a>. Your application can contain
* references to multiple loggers that are used for different
* purposes. A typical scenario for a server application is to have each
* major component of the server use its own Log instance.</li>
* <li>Cause messages to be logged (if the corresponding detail level is enabled)
* by calling appropriate methods (<code>trace()</code>, <code>debug()</code>,
* <code>info()</code>, <code>warn()</code>, <code>error</code>, and
* <code>fatal()</code>).</li>
* </ol>
*
* <p>For convenience, <code>LogFactory</code> also offers a static method
* <code>getLog()</code> that combines the typical two-step pattern:</p>
* <pre>
* Log log = LogFactory.getFactory().getInstance(Foo.class);
* </pre>
* <p>into a single method call:</p>
* <pre>
* Log log = LogFactory.getLog(Foo.class);
* </pre>
*
* <p>For example, you might use the following technique to initialize and
* use a <a href="Log.html">Log</a> instance in an application component:</p>
* <pre>
* import org.apache.commons.logging.Log;
* import org.apache.commons.logging.LogFactory;
*
* public class MyComponent {
*
* protected static Log log =
* LogFactory.getLog(MyComponent.class);
*
* // Called once at startup time
* public void start() {
* ...
* log.info("MyComponent started");
* ...
* }
*
* // Called once at shutdown time
* public void stop() {
* ...
* log.info("MyComponent stopped");
* ...
* }
*
* // Called repeatedly to process a particular argument value
* // which you want logged if debugging is enabled
* public void process(String value) {
* ...
* // Do the string concatenation only if logging is enabled
* if (log.isDebugEnabled())
* log.debug("MyComponent processing " + value);
* ...
* }
* }
*
*/
package org.apache.commons.logging;

View File

@ -0,0 +1,169 @@
<!--
Copyright 2001-2004 The Apache Software Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<body>
<p>Jakarta Commons Logging implemented over SLF4J.</p>
<h3>Overview</h3>
<p>This package contains the same public user interface as <a
href="http://jakarta.apache.org/commons/logging/">Jakarta Commons
Logging (JCL)</a>. It is intended as a 100% compatible drop-in
replacement for the original JCL version 1.0.4.
</p>
<p>As the original JCL version 1.0.4, the present version supports
various logging APIs. It differs from the original in implementation
but not the public API. This implementation uses SLF4J under the
covers. As such, all the logging systems that SLF4J supports,
e.g. NOP, Simple, JDK14, nlog4j are supported by this version of JCL.
</p>
<h3>Quick Start Guide</h3>
<p>For those impatient to just get on with it, the following example
illustrates the typical declaration and use of a logger that is named (by
convention) after the calling class:
<pre>
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Foo {
static Log log = LogFactory.getLog(Foo.class);
public void foo() {
...
try {
if (log.isDebugEnabled()) {
log.debug("About to do something to object " + name);
}
name.bar();
} catch (IllegalStateException e) {
log.error("Something bad happened to " + name, e);
}
...
}
</pre>
<h3>Configuring the Commons Logging Package</h3>
<p>In this version of JCL, the selection of the logging system to use
is chosen by the underlying SLF4J API. Consequently, all JCL-specific
configuration parameters are ignored.
</p>
<h4>Choosing a <code>LogFactory</code> Implementation</h4>
<p>From an application perspective, the first requirement is to
retrieve an object reference to the <code>LogFactory</code> instance
that will be used to create <code><a href="Log.html">Log</a></code>
instances for this application. This is normally accomplished by
calling the static <code>getFactory()</code> method. This method
always returns the same factory, i.e. a unique instance of the <a
href="impl/SLF4FLogFactory.html">SLF4FLogFactory</a> class.
</p>
<h4>Configuring the Underlying Logging System</h4>
<p>The basic principle is that the user is totally responsible for the
configuration of the underlying logging system.
Commons-logging should not change the existing configuration.</p>
<p>Each individual <a href="Log.html">Log</a> implementation may
support its own configuration properties. These will be documented in the
class descriptions for the corresponding implementation class.</p>
<p>Finally, some <code>Log</code> implementations (such as the one for Log4J)
require an external configuration file for the entire logging environment.
This file should be prepared in a manner that is specific to the actual logging
technology being used.</p>
<h3>Using the Logging Package APIs</h3>
<p>Use of the Logging Package APIs, from the perspective of an application
component, consists of the following steps:</p>
<ol>
<li>Acquire a reference to an instance of
<a href="Log.html">org.apache.commons.logging.Log</a>, by calling the
factory method
<a href="LogFactory.html#getInstance(java.lang.String)">
LogFactory.getInstance(String name)</a>. Your application can contain
references to multiple loggers that are used for different
purposes. A typical scenario for a server application is to have each
major component of the server use its own Log instance.</li>
<li>Cause messages to be logged (if the corresponding detail level is enabled)
by calling appropriate methods (<code>trace()</code>, <code>debug()</code>,
<code>info()</code>, <code>warn()</code>, <code>error</code>, and
<code>fatal()</code>).</li>
</ol>
<p>For convenience, <code>LogFactory</code> also offers a static method
<code>getLog()</code> that combines the typical two-step pattern:</p>
<pre>
Log log = LogFactory.getFactory().getInstance(Foo.class);
</pre>
<p>into a single method call:</p>
<pre>
Log log = LogFactory.getLog(Foo.class);
</pre>
<p>For example, you might use the following technique to initialize and
use a <a href="Log.html">Log</a> instance in an application component:</p>
<pre>
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class MyComponent {
protected static Log log =
LogFactory.getLog(MyComponent.class);
// Called once at startup time
public void start() {
...
log.info("MyComponent started");
...
}
// Called once at shutdown time
public void stop() {
...
log.info("MyComponent stopped");
...
}
// Called repeatedly to process a particular argument value
// which you want logged if debugging is enabled
public void process(String value) {
...
// Do the string concatenation only if logging is enabled
if (log.isDebugEnabled())
log.debug("MyComponent processing " + value);
...
}
}
</pre>
</body>

4
jcl-over-slf4j/src/main/java9/module-info.java Normal file → Executable file
View File

@ -1,8 +1,4 @@
/**
* Jakarta/Apache Commons Logging implemented over SLF4J.
*/
module org.apache.commons.logging {
requires org.slf4j;
exports org.apache.commons.logging;
exports org.apache.commons.logging.impl;
}

View File

@ -22,7 +22,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.apache.commons.logging.blackbox;
package org.apache.commons.logging.test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@ -36,7 +36,6 @@ import org.apache.commons.logging.impl.SLF4JLocationAwareLog;
import org.apache.commons.logging.impl.SLF4JLog;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.jul.JDK14LoggerFactory;
import org.slf4j.spi.LocationAwareLogger;

View File

@ -1,69 +0,0 @@
<?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">
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jul-to-slf4j-blackbox</artifactId>
<packaging>jar</packaging>
<name>jul-to-slf4j blackbox testing</name>
<description>jul-to-slf4j blackbox testing</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>
<properties>
<jdk.version>${jdk9.version}</jdk.version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,8 +0,0 @@
module jul.to.slf4j.blackbox {
requires jul.to.slf4j;
requires ch.qos.reload4j;
requires junit;
requires java.logging;
requires org.slf4j;
}

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
@ -24,7 +24,12 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@ -41,8 +41,8 @@ import org.slf4j.spi.LocationAwareLogger;
/**
* <p>Bridge/route all JUL log records to the SLF4J API.
* <p>Essentially, the idea is to install on the root logger an instance of
* {@link SLF4JBridgeHandler} as the sole JUL handler in the system. Subsequently, the
* <code>SLF4JBridgeHandler</code> instance will redirect all JUL log records are redirected
* <code>SLF4JBridgeHandler</code> as the sole JUL handler in the system. Subsequently, the
* SLF4JBridgeHandler instance will redirect all JUL log records are redirected
* to the SLF4J API based on the following mapping of levels:
*
* <pre>
@ -92,10 +92,13 @@ import org.slf4j.spi.LocationAwareLogger;
*
* <h2>As a Java 9/Jigsaw module</h2>
*
* <p>As of SLF4J 2.0x, the module name for <em>jul-to-slf4j.jar</em> is
* <b>jul.to.slf4j</b>. In SLF4J 1.7.x it was declared via an Automatic-Module-Name statement
* as <b>jul_to_slf4j</b> (note the two underscores).
* <p>Given that <b>to</b> is a reserved keyword under Java 9 within module productions,
* the MANIFEST.MF file in <em>jul-to-slf4j.jar</em> declares <b>jul_to_slf4j</b> as
* its Automatic Module Name. Thus, if your application is Jigsaw modularized, the requires
* statement in your <em>module-info.java</em> needs to be <b>jul_to_slf4j</b>
* (note the two underscores).
*
*
* @author Christian Stein
* @author Joern Huxhorn
* @author Ceki G&uuml;lc&uuml;

View File

@ -1,4 +0,0 @@
/**
* Bridge/route all JUL log records to the SLF4J API.
*/
package org.slf4j.bridge;

View File

@ -0,0 +1,15 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title></title>
</head>
<body>
<p>Bridge/route all JUL log records to the SLF4J API.</p>
<hr>
</body>
</html>

View File

@ -1,6 +1,3 @@
/**
* Bridge/route all JUL log records to the SLF4J API.
*/
module jul.to.slf4j {
requires org.slf4j;

View File

@ -22,7 +22,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.slf4j.bridge.blackbox;
package org.slf4j.bridge;
import java.util.ArrayList;
import java.util.List;

View File

@ -22,7 +22,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.slf4j.bridge.blackbox;
package org.slf4j.bridge;
import java.util.logging.Handler;
import java.util.logging.LogManager;
@ -31,10 +31,8 @@ import org.apache.log4j.FileAppender;
import org.apache.log4j.PatternLayout;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;
public class SLF4JBridgeHandlerPerfTest {

View File

@ -22,7 +22,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.slf4j.bridge.blackbox;
package org.slf4j.bridge;
import static org.junit.Assert.assertEquals;
@ -35,7 +35,6 @@ import org.apache.log4j.spi.LoggingEvent;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.bridge.SLF4JBridgeHandler;
public class SLF4JBridgeHandlerTest {

View File

@ -1,68 +0,0 @@
<?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">
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>log4j-over-slf4j-blackbox</artifactId>
<packaging>jar</packaging>
<name>log4j-over-slf4j blackbox testing</name>
<description>log4j-over-slf4j blackbox testing</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>
<properties>
<jdk.version>${jdk9.version}</jdk.version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,6 +0,0 @@
module log4j.over.slf4j.blackbox {
requires log4j.over.slf4j;
requires java.logging;
requires junit;
}

View File

@ -1,137 +0,0 @@
<project name="testing-log4j-bridge" default="usage" basedir=".">
<property name="lbversion" value="0.9.8-SNAPSHOT" />
<property name="slf4jversion" value="1.4.2" />
<property name="source.home" value="./src/main/java/" />
<property name="javac.dest.12" value="./target/classes12/" />
<property name="javac.dest.13" value="./target/classes13/" />
<property name="lib" value="./lib" />
<property name="deprecation" value="on" />
<path id="basic.classpath">
<pathelement location="${source.home}" />
<pathelement location="${lib}/junit-3.8.1.jar" />
</path>
<path id="log4j12.classpath">
<path refid="basic.classpath" />
<pathelement location="${javac.dest.12}" />
<pathelement location="${lib}/log4j-1.2.14.jar" />
</path>
<path id="log4j13.classpath">
<path refid="basic.classpath" />
<pathelement location="${javac.dest.13}" />
<pathelement location="${lib}/log4j-1.3alpha-8.jar" />
</path>
<path id="los.classpath">
<path refid="basic.classpath" />
<pathelement location="${lib}/log4j-over-slf4j-${slf4jversion}.jar" />
<pathelement location="${lib}/logback-classic-${lbversion}.jar" />
<pathelement location="${lib}/logback-core-${lbversion}.jar" />
<pathelement location="${lib}/slf4j-api-${slf4jversion}.jar" />
</path>
<!-- ================================================================= -->
<!-- Default target -->
<!-- ================================================================= -->
<target name="usage">
<echo>
These are some of the targets supported by this ANT build script:
all - run all available tests
refresh - copy required jar files to the lib directory
</echo>
</target>
<delete>
<fileset dir="." includes="**/*.bak"/>
</delete>
<target name="refresh">
<delete>
<fileset dir="lib">
<include name="logback-*.jar"/>
<include name="log4j-bridge-*.jar"/>
</fileset>
</delete>
<copy file="../../slf4j-api/target/slf4j-api-${slf4jversion}.jar" todir="lib/"/>
<copy file="../target/log4j-over-slf4j-${slf4jversion}.jar" todir="lib/"/>
</target>
<target name="init">
<mkdir dir="${javac.dest.12}" />
<mkdir dir="${javac.dest.13}" />
</target>
<target name="clean">
<delete>
<fileset dir="${javac.dest.12}" includes="**" />
<fileset dir="${javac.dest.13}" includes="**" />
</delete>
</target>
<target name="build_log4j12" depends="init">
<javac srcdir="${source.home}"
destdir="${javac.dest.12}"
includes="**/Log4j12Calls.java"
deprecation="${deprecation}" debug="on">
<classpath refid="log4j12.classpath" />
</javac>
</target>
<target name="build_log4j13" depends="init">
<javac srcdir="${source.home}"
destdir="${javac.dest.13}"
includes="**/Log4j13Calls.java" deprecation="${deprecation}" debug="on">
<classpath refid="log4j13.classpath" />
</javac>
</target>
<target name="build_loggerTest" depends="init">
<javac srcdir="${source.home}"
destdir="${javac.dest.12}"
includes="**/LoggerTest.java"
deprecation="${deprecation}" debug="on">
<classpath refid="los.classpath" />
</javac>
</target>
<!-- ================================================================= -->
<!-- Run tests -->
<!-- ================================================================= -->
<target name="all" depends="test12, test13, loggerTest" />
<target name="loggerTest" depends="build_loggerTest">
<junit printsummary="yes" fork="yes" haltonfailure="yes">
<classpath refid="los.classpath" />
<classpath location="${javac.dest.12}" />
<formatter type="plain" usefile="false" />
<test name="test.LoggerTest" />
</junit>
</target>
<target name="test12" depends="build_log4j12">
<junit printsummary="yes" fork="yes" haltonfailure="yes">
<classpath refid="los.classpath" />
<classpath location="${javac.dest.12}" />
<formatter type="plain" usefile="false" />
<test name="test.Log4j12Calls" />
</junit>
</target>
<target name="test13" depends="build_log4j13">
<junit printsummary="yes" fork="yes" haltonfailure="yes">
<classpath refid="los.classpath" />
<classpath location="${javac.dest.13}" />
<formatter type="plain" usefile="false" />
<test name="test.Log4j13Calls" />
</junit>
</target>
</project>

View File

@ -1,17 +0,0 @@
This directory is used to test the module against various log4j calls.
Two test cases simulate the typical calls that one can find in an application
that uses either log4j 1.2.x, or log4j 1.3.x.
In the same directory is a build.xml file that uses ant to
compile the test cases with the corresponding log4j version,
and to run these tests without log4j in the classpath but with
logback jars instead.
To run the tests, one must have ant installed. Issuing the following command,
once in the compatibility directory will launch the tests:
ant all
To obtain more information about the use of the log4j-over-slf4j module,
please visit http://www.slf4j.org/log4j-over-slf4j.html

View File

@ -1,8 +0,0 @@
package test;
public class DummyObject {
public String toString() {
return "dummy";
}
}

View File

@ -1,39 +0,0 @@
/**
* Logback: the reliable, generic, fast and flexible logging framework.
*
* Copyright (C) 1999-2006, QOS.ch
*
* This library is free software, you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation.
*/
package test;
import junit.framework.TestCase;
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
/**
*
* A test case that issues the typical calls
* that an application using log4j 1.2 would do.
*
* @author Ceki G&uuml;lc&uuml;
* @author S&eacute;bastien Pennec
*/
public class Log4j12Calls extends TestCase {
public static final Logger logger = Logger.getLogger(Log4j12Calls.class);
public void testLog() {
MDC.put("key", "value1");
logger.trace("Trace level can be noisy");
logger.debug("Entering application");
logger.info("Violets are blue");
logger.warn("Here is a warning");
logger.error("Exiting application", new Exception("just testing"));
MDC.remove("key");
}
}

View File

@ -1,46 +0,0 @@
/**
* Logback: the reliable, generic, fast and flexible logging framework.
*
* Copyright (C) 1999-2006, QOS.ch
*
* This library is free software, you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation.
*/
package test;
import junit.framework.TestCase;
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
/**
*
* A test case that issues the typical calls
* that an application using log4j 1.3 would do.
*
* @author Ceki G&uuml;lc&uuml;
* @author S&eacute;bastien Pennec
*/
public class Log4j13Calls extends TestCase {
public static final Logger logger = Logger.getLogger(Log4j12Calls.class);
public void testLog() {
MDC.put("key", "value1");
logger.trace("Trace level can be noisy");
logger.debug("Entering application");
logger.info("Violets are blue");
logger.warn("Here is a warning");
logger.info("The answer is {}.", new Integer(42));
logger.info("Number: {} and another one: {}.", new Integer(42), new Integer(24));
logger.error("Exiting application", new Exception("just testing"));
MDC.remove("key");
MDC.clear();
}
}

View File

@ -1,169 +0,0 @@
package test;
import junit.framework.TestCase;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.read.ListAppender;
import org.apache.log4j.Level;
/**
* A class that tests the invocation of the org.apache.log4j.Logger class that
* belongs to the log4j-bridge package
*
* @author S&eacute;bastien Pennec
* @author Ceki G&uuml;lc&uuml;
*/
public class LoggerTest extends TestCase {
LoggerContext context;
ListAppender<LoggingEvent> appender;
ch.qos.logback.classic.Logger logbackLogger;
org.apache.log4j.Logger log4jLogger;
public void setUp() throws Exception {
context = (LoggerContext) LoggerFactory.getILoggerFactory();
context.shutdownAndReset();
appender = new ListAppender<LoggingEvent>();
appender.setContext(context);
appender.setName("listAppender");
appender.start();
ch.qos.logback.classic.Logger lbLogger = context
.getLogger(LoggerContext.ROOT_NAME);
lbLogger.addAppender(appender);
log4jLogger = org.apache.log4j.Logger.getLogger(LoggerTest.class);
logbackLogger = context.getLogger(LoggerTest.class);
super.setUp();
}
public void tearDown() throws Exception {
appender.stop();
context.stop();
appender = null;
context = null;
logbackLogger = null;
log4jLogger = null;
super.tearDown();
}
public void testLogWithObjectMessages() {
LoggingEvent event;
log4jLogger.debug("test");
event = appender.list.get(0);
assertEquals("test", event.getMessage());
appender.list.clear();
log4jLogger.debug(null);
event = appender.list.get(0);
assertEquals(null, event.getMessage());
appender.list.clear();
DummyObject dummy = new DummyObject();
log4jLogger.debug(dummy);
event = appender.list.get(0);
assertEquals(dummy.toString(), event.getMessage());
appender.list.clear();
}
public void testIsEnabledAPI() {
assertFalse(log4jLogger.isTraceEnabled());
assertTrue(log4jLogger.isDebugEnabled());
assertTrue(log4jLogger.isInfoEnabled());
assertTrue(log4jLogger.isWarnEnabled());
assertTrue(log4jLogger.isErrorEnabled());
}
public void testPrintAPI() {
Exception e = new Exception("just testing");
log4jLogger.trace(null);
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.debug(null);
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.debug("debug message");
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.info(null);
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.info("info message");
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.warn(null);
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.warn("warn message");
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.error(null);
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.error("error message");
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.debug(null, e);
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.debug("debug message", e);
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.info(null, e);
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.info("info message", e);
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.warn(null, e);
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.warn("warn message", e);
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.error(null, e);
assertEquals(1, appender.list.size());
appender.list.clear();
log4jLogger.error("error message", e);
assertEquals(1, appender.list.size());
appender.list.clear();
}
public void testLogAPI() {
log4jLogger.log("x", Level.TRACE, "x", null);
assertEquals(0, appender.list.size());
log4jLogger.log("x", Level.DEBUG, "x", null);
log4jLogger.log("x", Level.INFO, "x", null);
log4jLogger.log("x", Level.WARN, "x", null);
log4jLogger.log("x", Level.ERROR, "x", null);
log4jLogger.log("x", Level.FATAL, "x", null);
assertEquals(5, appender.list.size());
appender.list.clear();
}
}

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
@ -21,8 +21,8 @@
<licenses>
<license>
<name>Apache Software Licenses</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<name>Apache-2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>

2
log4j-over-slf4j/src/main/java9/module-info.java Normal file → Executable file
View File

@ -1,4 +1,4 @@
module log4j.over.slf4j {
module log4j {
requires org.slf4j;
requires java.xml;
exports org.apache.log4j;

View File

@ -22,7 +22,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.apache.log4j.blackbox;
package org.dummy;
import static org.junit.Assert.assertEquals;

View File

@ -22,7 +22,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.apache.log4j.blackbox;
package org.dummy;
import static org.junit.Assert.assertEquals;

View File

@ -22,7 +22,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.apache.log4j.blackbox;
package org.dummy;
import java.util.ArrayList;
import java.util.List;

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
@ -53,22 +53,11 @@
<Bundle-SymbolicName>org.slf4j.osgi-over-slf4j</Bundle-SymbolicName>
<Bundle-Activator>org.slf4j.osgi.logservice.impl.Activator</Bundle-Activator>
<Bundle-Category>osgi</Bundle-Category>
<_exportcontents combine.self="override"/>
<_exportcontents combine.self="override" />
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>org.slf4j.osgi.logservice</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-bom</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -18,7 +18,7 @@
<organization>
<name>QOS.CH Sarl</name>
<name>QOS.ch</name>
<url>http://www.qos.ch</url>
</organization>
<inceptionYear>2005</inceptionYear>
@ -26,32 +26,29 @@
<properties>
<!-- yyyy-MM-dd'T'HH:mm:ss'Z' -->
<project.build.outputTimestamp>2024-01-02T19:20:00Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2026-05-12T18:37:04Z</project.build.outputTimestamp>
<latest.1.version>1.7.36</latest.1.version>
<!-- java.util.ServiceLoader requires Java 6 -->
<jdk.version>8</jdk.version>
<!-- used in test modules, unpublished modules or where it does not matter -->
<jdk9.version>9</jdk9.version>
<maven.compiler.source>${jdk.version}</maven.compiler.source>
<maven.compiler.target>${jdk.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.resourceEncoding>UTF-8</project.build.resourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- used in integration testing -->
<cal10n.version>0.8.1</cal10n.version>
<reload4j.version>1.2.25</reload4j.version>
<reload4j.version>1.2.22</reload4j.version>
<logback.version>1.2.10</logback.version>
<jcl.version>1.2</jcl.version>
<junit.version>4.13.1</junit.version>
<maven-site-plugin.version>3.12.1</maven-site-plugin.version>
<maven-site-plugin.version>3.7.1</maven-site-plugin.version>
<maven-compiler-plugin.version>3.10.1</maven-compiler-plugin.version>
<maven-surefire-plugin.version>3.0.0-M7</maven-surefire-plugin.version>
<maven-javadoc-plugin.version>3.6.3</maven-javadoc-plugin.version>
<maven-source-plugin.version>3.2.1</maven-source-plugin.version>
<maven-deploy-plugin.version>3.0.0-M1</maven-deploy-plugin.version>
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
<maven-jxr-plugin.version>3.3.1</maven-jxr-plugin.version>
<maven-jxr-plugin.version>3.1.1</maven-jxr-plugin.version>
<maven-bundle-plugin.version>5.1.9</maven-bundle-plugin.version>
</properties>
@ -145,17 +142,8 @@
<goal>compile</goal>
</goals>
<configuration>
<release>${jdk.version}</release>
</configuration>
</execution>
<execution>
<id>default-testCompile</id>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<release>${jdk.version}</release>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</execution>
@ -173,6 +161,8 @@
<multiReleaseOutput>true</multiReleaseOutput>
</configuration>
</execution>
</executions>
</plugin>
@ -262,43 +252,20 @@
</executions>
</plugin>
<!-- <plugin>-->
<!-- <groupId>org.apache.maven.plugins</groupId>-->
<!-- <artifactId>maven-javadoc-plugin</artifactId>-->
<!-- <version>3.6.3</version>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <id>default-cli</id>-->
<!-- <goals>-->
<!-- <goal>aggregate</goal>-->
<!-- </goals>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- <configuration>-->
<!-- <verbose>true</verbose>-->
<!-- &lt;!&ndash; <sourceFileExcludes>&ndash;&gt;-->
<!-- &lt;!&ndash; <sourceFileExclude>**/xmodule-info.java</sourceFileExclude>&ndash;&gt;-->
<!-- &lt;!&ndash; </sourceFileExcludes>&ndash;&gt;-->
<!-- <skippedModules>-->
<!-- slf4j-testing,slf4j-ext,log4j-over-slf4j,log4j-over-slf4j-blackbox,jul-to-slf4j-blackbox,slf4j-migrator,osgi-over-slf4j-->
<!-- </skippedModules>-->
<!-- <detectLinks>true</detectLinks>-->
<!-- <doctitle>SLF4J project modules ${project.version}</doctitle>-->
<!-- <windowtitle>SLF4J javadoc</windowtitle>-->
<!-- <linksource>true</linksource>-->
<!-- <additionalOptions>-->
<!-- <additionalOption>-Xdoclint:none</additionalOption>-->
<!-- </additionalOptions>-->
<!-- </configuration>-->
<!-- </plugin>-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>${maven-site-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</build>
<reporting>
</reporting>
</build>
<profiles>
<profile>
@ -336,8 +303,6 @@
</build>
</profile>
<profile>
<id>license</id>
<build>
@ -400,6 +365,32 @@
</build>
</profile>
<!--
<profile>
<id>travis</id>
<activation>
<property>
<name>env.TRAVIS</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-toolchains-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<id>toolchain</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
-->
</profiles>

69
pom.xml
View File

@ -6,34 +6,34 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-bom</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<packaging>pom</packaging>
<url>http://www.slf4j.org</url>
<name>SLF4J BOM</name>
<description>SLF4J project BOM</description>
<licenses>
<license>
<name>MIT License</name>
<url>http://www.opensource.org/licenses/mit-license.php</url>
<name>MIT</name>
<url>https://opensource.org/license/mit</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<url>https://github.com/qos-ch/slf4j</url>
<connection>scm:git:https://github.com/qos-ch/slf4j.git</connection>
</scm>
</scm>
<!-- Inspired by Improving the Maven Bill of Materials (BOM) Pattern -->
<!-- https://www.garretwilson.com/blog/2023/06/14/improve-maven-bom-pattern -->
<modules>
<module>parent</module>
<module>slf4j-api</module>
<module>slf4j-testing</module>
<module>slf4j-simple</module>
<module>slf4j-nop</module>
<module>slf4j-jdk14</module>
@ -42,16 +42,17 @@
<module>slf4j-reload4j</module>
<module>slf4j-ext</module>
<module>jcl-over-slf4j</module>
<module>jcl-over-slf4j-blackbox</module>
<module>log4j-over-slf4j</module>
<module>log4j-over-slf4j-blackbox</module>
<module>jul-to-slf4j</module>
<module>jul-to-slf4j-blackbox</module>
<module>osgi-over-slf4j</module>
<module>integration</module>
<module>slf4j-migrator</module>
</modules>
<properties>
<central-publishing-maven-plugin.version>0.9.0</central-publishing-maven-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
@ -72,7 +73,7 @@
<artifactId>slf4j-nop</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
@ -85,49 +86,49 @@
<artifactId>slf4j-jdk-platform-logging</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-ext</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>osgi-over-slf4j</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
@ -155,21 +156,13 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>default-cli</id>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
</executions>
<configuration>
<verbose>true</verbose>
<skippedModules>
slf4j-testing,slf4j-jdk-platform-logging,jcl-over-slf4j-blackbox,log4j-over-slf4j-blackbox,jul-to-slf4j-blackbox,slf4j-migrator,osgi-over-slf4j
slf4j-jdk-platform-logging,slf4j-migrator,osgi-over-slf4j
</skippedModules>
<detectLinks>true</detectLinks>
<doctitle>SLF4J project modules 2.1.0-alpha1</doctitle>
<doctitle>SLF4J project modules ${project.version}</doctitle>
<windowtitle>SLF4J javadoc</windowtitle>
<bottom><![CDATA[Copyright &copy; 2005-{currentYear} QOS.CH Sarl. All rights reserved]]></bottom>
<linksource>true</linksource>
@ -230,12 +223,23 @@
</configuration>
</plugin>
</plugins>
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
<version>${central-publishing-maven-plugin.version}</version>
<extensions>true</extensions>
<configuration>
<publishingServerId>central</publishingServerId>
<excludeArtifacts>integration</excludeArtifacts>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>sign-artifacts</id>
<build>
@ -257,7 +261,6 @@
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -4,9 +4,11 @@
#JDK8 - mvn site:site
#rscpSLF4J apidocs/
# mvn -Ddoclint=none -Dmaven.javadoc.skippedModules=slf4j-ext,log4j-over-slf4j,log4j-over-slf4j-blackbox,jul-to-slf4j-blackbox,slf4j-migrator,osgi-over-slf4j javadoc:aggregate
# JDK 11+
# adding the following
#mvn -Ddoclint=none -Dadditionalparam=-Xdoclint:none javadoc:aggregate
#mvn -Ddoclint=none -DXXadditionalparam=-Xdoclint:none -Dmaven.javadoc.skippedModules=osgi-over-slf4j,slf4j-ext,log4j-over-slf4j-blackbox,log4j-over-slf4j javadoc:aggregate
#mvn versions:set -DgenerateBackupPoms=false -DnewVersion=${VERSION_NUMBER}
MVN='/java/maven-3.5.2//bin/mvn'
@ -44,8 +46,9 @@ echoRunAndCheck "$MVN install"
if [ ! -z "$PASS" ]
then
export GPG_TTY=$(tty)
echoRunAndCheck "$MVN deploy -P javadocjar,sign-artifacts"
# WARNING deploying without cleaning may leave stale MANIFEST files
export GPG_TTY=$(tty)
echoRunAndCheck "$MVN deploy -P javadocjar,sign-artifacts"
fi

View File

@ -1,13 +1,13 @@
<?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">
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>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
@ -59,8 +59,7 @@
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Import-Package>org.slf4j.spi;version="${range;[===,+);${version_cleanup;${project.version}}}"
</Import-Package>
<Import-Package>org.slf4j.spi;version="${range;[===,+);${version_cleanup;${project.version}}}"</Import-Package>
<!-- Export the client/user package of slf4j-api version 1 to make the slf4j-api bundle in version 2 usable for bundles that only import slf4j-1.x -->
<_exportcontents><![CDATA[
*,\
@ -75,29 +74,8 @@
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<executions>
<execution>
<id>module-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>${jdk9.version}</release>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/main/java9</compileSourceRoot>
</compileSourceRoots>
<multiReleaseOutput>true</multiReleaseOutput>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -116,9 +116,9 @@ public interface Logger {
}
/**
* <p>Make a new {@link LoggingEventBuilder} instance as appropriate for this logger and the
* Make a new {@link LoggingEventBuilder} instance as appropriate for this logger and the
* desired {@link Level} passed as parameter. If this Logger is disabled for the given Level, then
* a {@link NOPLoggingEventBuilder} is returned. This is the main optimization in the fluent API.</p>
* a {@link NOPLoggingEventBuilder} is returned.
*
*
* @param level desired level for the event builder
@ -243,11 +243,8 @@ public interface Logger {
public boolean isTraceEnabled(Marker marker);
/**
* Entry point for fluent-logging for {@link org.slf4j.event.Level#TRACE} level.
*
* <p>If this logger is disabled for the TRACE level, then a {@link NOPLoggingEventBuilder} instance is returned.
* As the name indicates, this builder does not perform any operations. This is the main optimization in the fluent API.</p>
*
* Entry point for fluent-logging for {@link org.slf4j.event.Level#TRACE} level.
*
* @return LoggingEventBuilder instance as appropriate for level TRACE
* @since 2.0
*/
@ -444,10 +441,7 @@ public interface Logger {
/**
* Entry point for fluent-logging for {@link org.slf4j.event.Level#DEBUG} level.
*
* <p>If this logger is disabled for the DEBUG level, then a {@link NOPLoggingEventBuilder} instance is returned.
* As the name indicates, this builder does not perform any operations. This is the main optimization in the fluent API.</p>
*
*
* @return LoggingEventBuilder instance as appropriate for level DEBUG
* @since 2.0
*/
@ -588,10 +582,7 @@ public interface Logger {
/**
* Entry point for fluent-logging for {@link org.slf4j.event.Level#INFO} level.
*
* <p>If this logger is disabled for the INFO level, then a {@link NOPLoggingEventBuilder} instance is returned.
* As the name indicates, this builder does not perform any operations. This is the main optimization in the fluent API.</p>
*
* @return LoggingEventBuilder instance as appropriate for level INFO
* @since 2.0
*/
@ -732,10 +723,7 @@ public interface Logger {
/**
* Entry point for fluent-logging for {@link org.slf4j.event.Level#WARN} level.
*
* <p>If this logger is disabled for the WARN level, then a {@link NOPLoggingEventBuilder} instance is returned.
* As the name indicates, this builder does not perform any operations. This is the main optimization in the fluent API.</p>
*
*
* @return LoggingEventBuilder instance as appropriate for level WARN
* @since 2.0
*/
@ -877,10 +865,7 @@ public interface Logger {
/**
* Entry point for fluent-logging for {@link org.slf4j.event.Level#ERROR} level.
*
* <p>If this logger is disabled for the ERROR level, then a {@link NOPLoggingEventBuilder} instance is returned.
* As the name indicates, this builder does not perform any operations.</p>
*
*
* @return LoggingEventBuilder instance as appropriate for level ERROR
* @since 2.0
*/

View File

@ -47,6 +47,7 @@ import org.slf4j.helpers.Reporter;
import org.slf4j.helpers.SubstituteLogger;
import org.slf4j.helpers.SubstituteServiceProvider;
import org.slf4j.helpers.Util;
import org.slf4j.spi.MDCAdapter;
import org.slf4j.spi.SLF4JServiceProvider;
/**
@ -195,6 +196,7 @@ public final class LoggerFactory {
reportMultipleBindingAmbiguity(providersList);
if (providersList != null && !providersList.isEmpty()) {
PROVIDER = providersList.get(0);
earlyBindMDCAdapter();
// SLF4JServiceProvider.initialize() is intended to be called here and nowhere else.
PROVIDER.initialize();
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
@ -215,6 +217,19 @@ public final class LoggerFactory {
}
}
/**
* The value of PROVIDER.getMDCAdapter() can be null while PROVIDER has not yet initialized.
*
* However, SLF4JServiceProvider implementations are expected to initialize their internal
* MDCAdapter field in their constructor or on field declaration.
*/
private static void earlyBindMDCAdapter() {
MDCAdapter mdcAdapter = PROVIDER.getMDCAdapter();
if(mdcAdapter != null) {
MDC.setMDCAdapter(mdcAdapter);
}
}
static SLF4JServiceProvider loadExplicitlySpecified(ClassLoader classLoader) {
String explicitlySpecified = System.getProperty(PROVIDER_PROPERTY_KEY);
if (null == explicitlySpecified || explicitlySpecified.isEmpty()) {
@ -406,9 +421,16 @@ public final class LoggerFactory {
}
private static void reportActualBinding(List<SLF4JServiceProvider> providerList) {
if (!providerList.isEmpty()) {
// impossible since a provider has been found
if (providerList.isEmpty()) {
throw new IllegalStateException("No providers were found which is impossible after successful initialization.");
}
if (isAmbiguousProviderList(providerList)) {
Reporter.info("Actual provider is of type [" + providerList.get(0) + "]");
} else {
SLF4JServiceProvider provider = providerList.get(0);
Reporter.info(CONNECTED_WITH_MSG + provider.getClass().getName() + "]");
Reporter.debug(CONNECTED_WITH_MSG + provider.getClass().getName() + "]");
}
}

View File

@ -28,10 +28,7 @@ import java.io.Closeable;
import java.util.Deque;
import java.util.Map;
import org.slf4j.helpers.BasicMDCAdapter;
import org.slf4j.helpers.NOPMDCAdapter;
import org.slf4j.helpers.Reporter;
import org.slf4j.helpers.Util;
import org.slf4j.helpers.*;
import org.slf4j.spi.MDCAdapter;
import org.slf4j.spi.SLF4JServiceProvider;
@ -66,9 +63,9 @@ import org.slf4j.spi.SLF4JServiceProvider;
public class MDC {
static final String NULL_MDCA_URL = "http://www.slf4j.org/codes.html#null_MDCA";
private static final String MDC_APAPTER_CANNOT_BE_NULL_MESSAGE = "MDCAdapter cannot be null. See also " + NULL_MDCA_URL;
private static final String MDC_ADAPTER_CANNOT_BE_NULL_MESSAGE = "MDCAdapter cannot be null. See also " + NULL_MDCA_URL;
static final String NO_STATIC_MDC_BINDER_URL = "http://www.slf4j.org/codes.html#no_static_mdc_binder";
static MDCAdapter mdcAdapter;
static MDCAdapter MDC_ADAPTER;
/**
* An adapter to remove the key when done.
@ -88,14 +85,30 @@ public class MDC {
private MDC() {
}
static {
private static MDCAdapter getMDCAdapterGivenByProvider() {
SLF4JServiceProvider provider = LoggerFactory.getProvider();
if (provider != null) {
mdcAdapter = provider.getMDCAdapter();
if(provider != null) {
// If you wish to change the mdc adapter, setting the MDC.MDCAdapter variable might be insufficient.
// Keep in mind that the provider *might* perform additional internal mdcAdapter assignments that
// you would also need to replicate/adapt.
// obtain and attach the MDCAdapter from the provider
final MDCAdapter anAdapter = provider.getMDCAdapter();
emitTemporaryMDCAdapterWarningIfNeeded(provider);
return anAdapter;
} else {
Reporter.error("Failed to find provider.");
Reporter.error("Defaulting to no-operation MDCAdapter implementation.");
mdcAdapter = new NOPMDCAdapter();
return new NOPMDCAdapter();
}
}
private static void emitTemporaryMDCAdapterWarningIfNeeded(SLF4JServiceProvider provider) {
boolean isSubstitute = provider instanceof SubstituteServiceProvider;
if(isSubstitute) {
Reporter.info("Temporary mdcAdapter given by SubstituteServiceProvider.");
Reporter.info("This mdcAdapter will be replaced after backend initialization has completed.");
}
}
@ -118,10 +131,10 @@ public class MDC {
if (key == null) {
throw new IllegalArgumentException("key parameter cannot be null");
}
if (mdcAdapter == null) {
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
if (getMDCAdapter() == null) {
throw new IllegalStateException(MDC_ADAPTER_CANNOT_BE_NULL_MESSAGE);
}
mdcAdapter.put(key, val);
getMDCAdapter().put(key, val);
}
/**
@ -174,10 +187,8 @@ public class MDC {
throw new IllegalArgumentException("key parameter cannot be null");
}
if (mdcAdapter == null) {
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
}
return mdcAdapter.get(key);
mdcAdapterNullCheck();
return getMDCAdapter().get(key);
}
/**
@ -195,20 +206,16 @@ public class MDC {
throw new IllegalArgumentException("key parameter cannot be null");
}
if (mdcAdapter == null) {
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
}
mdcAdapter.remove(key);
mdcAdapterNullCheck();
getMDCAdapter().remove(key);
}
/**
* Clear all entries in the MDC of the underlying implementation.
*/
public static void clear() {
if (mdcAdapter == null) {
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
}
mdcAdapter.clear();
mdcAdapterNullCheck();
getMDCAdapter().clear();
}
/**
@ -219,10 +226,8 @@ public class MDC {
* @since 1.5.1
*/
public static Map<String, String> getCopyOfContextMap() {
if (mdcAdapter == null) {
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
}
return mdcAdapter.getCopyOfContextMap();
mdcAdapterNullCheck();
return getMDCAdapter().getCopyOfContextMap();
}
/**
@ -237,23 +242,38 @@ public class MDC {
* @since 1.5.1
*/
public static void setContextMap(Map<String, String> contextMap) {
if (mdcAdapter == null) {
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
}
mdcAdapter.setContextMap(contextMap);
mdcAdapterNullCheck();
getMDCAdapter().setContextMap(contextMap);
}
/**
* Returns the MDCAdapter instance currently in use.
*
*
* Since 2.0.17, if the MDCAdapter instance is null, then this method set it to use
* the adapter returned by the SLF4JProvider. However, in the vast majority of cases
* the MDCAdapter will be set earlier (during initialization) by {@link LoggerFactory}.
*
* @return the MDcAdapter instance currently in use.
* @since 1.4.2
*/
public static MDCAdapter getMDCAdapter() {
return mdcAdapter;
if(MDC_ADAPTER == null) {
MDC_ADAPTER = getMDCAdapterGivenByProvider();
}
return MDC_ADAPTER;
}
/**
* Set MDCAdapter instance to use.
*
* @since 2.0.17
*/
static void setMDCAdapter(MDCAdapter anMDCAdapter) {
if(anMDCAdapter == null) {
throw new IllegalStateException(MDC_ADAPTER_CANNOT_BE_NULL_MESSAGE);
}
MDC_ADAPTER = anMDCAdapter;
}
/**
* Push a value into the deque(stack) referenced by 'key'.
@ -263,28 +283,24 @@ public class MDC {
* @since 2.0.0
*/
static public void pushByKey(String key, String value) {
if (mdcAdapter == null) {
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
}
mdcAdapter.pushByKey(key, value);
mdcAdapterNullCheck();
getMDCAdapter().pushByKey(key, value);
}
/**
* Pop the stack referenced by 'key' and return the value possibly null.
* Pop the <b>stack</b> referenced by 'key' and return the value possibly null.
*
* @param key identifies the deque(stack)
* @return the value just popped. May be null/
* @since 2.0.0
*/
static public String popByKey(String key) {
if (mdcAdapter == null) {
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
}
return mdcAdapter.popByKey(key);
mdcAdapterNullCheck();
return getMDCAdapter().popByKey(key);
}
/**
* Returns a copy of the deque(stack) referenced by 'key'. May be null.
* Returns a copy of the <b>deque(stack)</b> referenced by 'key'. May be null.
*
* @param key identifies the stack
* @return copy of stack referenced by 'key'. May be null.
@ -292,9 +308,13 @@ public class MDC {
* @since 2.0.0
*/
public Deque<String> getCopyOfDequeByKey(String key) {
if (mdcAdapter == null) {
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
mdcAdapterNullCheck();
return getMDCAdapter().getCopyOfDequeByKey(key);
}
private static void mdcAdapterNullCheck() {
if (getMDCAdapter() == null) {
throw new IllegalStateException(MDC_ADAPTER_CANNOT_BE_NULL_MESSAGE);
}
return mdcAdapter.getCopyOfDequeByKey(key);
}
}

View File

@ -1,184 +0,0 @@
/**
* Copyright (c) 2004-2023 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 org.slf4j.spi.MDCAdapter;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable;
/**
* <p>This class assists in the creation and removal (aka closing) of {@link org.slf4j.MDC MDC} entries.</p>
*
* <p>Typical Usage example:</p>
*
* <pre>
* MDCAmbit mdca = new MDCAmbit();
* try {
* mdca.put("k0", "v0");
* doSomething();
* } catch (RuntimeException e) {
* // here MDC.get("k0") would return "v0"
* } finally {
* // MDC remove "k0"
* mdca.clear();
* }
* </pre>
*
* <p>It is also possible to chain {@link #put}, {@link #addKeys(String...)} and {@link #addKey(String)}
* invocations.</p>
*
* <p>For example:</p>
* <pre>
* MDCAmbit mdca = new MDCAmbit();
* try {
* // assume "k0" was added to MDC at an earlier stage
* mdca.addKey("k0").put("k1", "v1").put("k2, "v2");
* doSomething();
* } finally {
* // MDC remove "k0", "k1", "k2", clear the set of tracked keys
* mdch.clear();
* }
* </pre>
*
* <p>The {@link #run(Runnable)} and {@link #call(Callable)} methods invoke the run/callable methods of
* objects passed as parameter in a <code>try/finally</code> block, and afterwards invoking {@link #clear()}
* method from within <code>finally</code>.
*
* </p>
*
* <pre>
* DCAmbit mdca = new MDCAmbit();
* Runnable runnable = ...;
* mdca.put("k0", "v0").run(runnable);
* </pre>
*
* @since 2.1.0
*/
public class MDCAmbit {
/**
* Set of keys under management of this instance
*/
Set<String> keySet = new HashSet();
MDCAdapter mdcAdapter;
public MDCAmbit() {
mdcAdapter = MDC.getMDCAdapter();
}
MDCAmbit(MDCAdapter mdcAdapter) {
this.mdcAdapter = mdcAdapter;
}
/**
* Put the key/value couple in the MDC and keep track of the key for later
* removal by a call to {@link #clear()} }.
*
* @param key
* @param value
* @return this instance
*/
public MDCAmbit put(String key, String value) {
mdcAdapter.put(key, value);
keySet.add(key);
return this;
}
/**
* Keep track of a key for later removal by a call to {@link #clear()}.
* .
* @param key
* @return this instance
*/
public MDCAmbit addKey(String key) {
keySet.add(key);
return this;
}
/**
* Keep track of several keys for later removal by a call to {@link #clear()} .
* @param keys
* @return this instance
*/
public MDCAmbit addKeys(String... keys) {
if(keys == null)
return this;
for(String k: keys) {
keySet.add(k);
}
return this;
}
/**
* Run the runnable object passed as parameter within a try/finally block.
*
* <p>Afterwards, the {@link #clear()} method will be called within the `finally` block.
* </p>
* @param runnable
*/
public void run(Runnable runnable) {
try {
runnable.run();
} finally {
clear();
}
}
/**
* Invoke the {@link Callable#call()} method of the callable object passed as parameter within a try/finally block.
*
* <p>Afterwards, the {@link #clear()} method will be invoked within the `finally` block.
* </p>
* @param callable
*/
public <T> T call(Callable<? extends T> callable) throws Exception {
try {
return callable.call();
} finally {
clear();
}
}
/**
* Clear tracked keys by calling {@link MDC#remove} on each key.
*
* <p>In addition, the set of tracked keys is cleared.</p>
*
* <p>This method is usually called from within finally statement of a
* try/catch/finally block</p>
*
*/
public void clear() {
for(String key: keySet) {
mdcAdapter.remove(key);
}
keySet.clear();
}
}

View File

@ -2,11 +2,6 @@ package org.slf4j.event;
import org.slf4j.spi.LocationAwareLogger;
/**
* Various constants used by {@link Level} and {@link org.slf4j.Logger}.
*
*
*/
public class EventConstants {
public static final int ERROR_INT = LocationAwareLogger.ERROR_INT;
public static final int WARN_INT = LocationAwareLogger.WARN_INT;

View File

@ -2,12 +2,6 @@ package org.slf4j.event;
import java.util.Objects;
/**
* Instances of this class store the key value pair passed to a {@link org.slf4j.Logger logger} via
* the {@link org.slf4j.spi.LoggingEventBuilder#addKeyValue(String, Object)} method of the fluent API.
*
* @since 2.0.0
*/
public class KeyValuePair {
public final String key;

View File

@ -7,8 +7,9 @@ import static org.slf4j.event.EventConstants.TRACE_INT;
import static org.slf4j.event.EventConstants.WARN_INT;
/**
* SLF4J's internal representation of a level.
*
* SLF4J's internal representation of Level.
*
*
* @author Ceki G&uuml;lc&uuml;
* @since 1.7.15
*/

View File

@ -23,6 +23,10 @@ public interface LoggingEvent {
Object[] getArgumentArray();
/**
* List of markers in the event, might be null.
* @return markers in the event, might be null.
*/
List<Marker> getMarkers();
List<KeyValuePair> getKeyValuePairs();

View File

@ -7,13 +7,6 @@ import java.util.List;
import org.slf4j.Marker;
import org.slf4j.helpers.SubstituteLogger;
/**
* An implementation of {@link LoggingEvent} used to store logging events generated during logging backend
* initialization.
*
* @author Ceki G&uuml;lc&uuml;
* @since 1.7.15
*/
public class SubstituteLoggingEvent implements LoggingEvent {
Level level;

View File

@ -1,8 +0,0 @@
/**
* SLF4J internal representation of a logging event.
*
* <p>>Most notably, the {@link org.slf4j.event.LoggingEvent} interface, a minimal interface sufficient for
* the restitution of data passed by the user to the SLF4J API.
* </p>
*/
package org.slf4j.event;

View File

@ -3,11 +3,13 @@ package org.slf4j.helpers;
import java.io.PrintStream;
/**
* An internally used class for reporting internal messages generated by SLF4J itself during initialization.
* An internally used class for reporting internal messages generated by SLF4J itself, typically
* during initialization.
*
* <p>
* Internal reporting is performed by calling the {@link #info(String)}, {@link #warn(String)} (String)}
* {@link #error(String)} (String)} and {@link #error(String, Throwable)} methods.
* Internal reporting is performed by calling the {@link #debug(String)}, {@link #info(String)},
* {@link #warn(String)} (String)} {@link #error(String)} (String)} and
* {@link #error(String, Throwable)} methods.
* </p>
* <p>See {@link #SLF4J_INTERNAL_VERBOSITY_KEY} and {@link #SLF4J_INTERNAL_REPORT_STREAM_KEY} for
* configuration options.</p>
@ -23,7 +25,7 @@ public class Reporter {
* this class is used internally by Reporter
*/
private enum Level {
INFO(1), WARN(2), ERROR(3);
DEBUG(0), INFO(1), WARN(2), ERROR(3);
int levelInt;
@ -40,6 +42,7 @@ public class Reporter {
Stderr, Stdout;
}
static final String SLF4J_DEBUG_PREFIX = "SLF4J(D): ";
static final String SLF4J_INFO_PREFIX = "SLF4J(I): ";
static final String SLF4J_WARN_PREFIX = "SLF4J(W): ";
static final String SLF4J_ERROR_PREFIX = "SLF4J(E): ";
@ -62,11 +65,11 @@ public class Reporter {
public static final String SLF4J_INTERNAL_VERBOSITY_KEY = "slf4j.internal.verbosity";
static private final TargetChoice TARGET_CHOICE = initTargetChoice();
static private final TargetChoice TARGET_CHOICE = getTargetChoice();
static private final Level INTERNAL_VERBOSITY = initVerbosity();
static private TargetChoice initTargetChoice() {
static private TargetChoice getTargetChoice() {
String reportStreamStr = System.getProperty(SLF4J_INTERNAL_REPORT_STREAM_KEY);
if(reportStreamStr == null || reportStreamStr.isEmpty()) {
@ -88,6 +91,10 @@ public class Reporter {
return Level.INFO;
}
if(verbosityStr.equalsIgnoreCase("DEBUG")) {
return Level.DEBUG;
}
if(verbosityStr.equalsIgnoreCase("ERROR")) {
return Level.ERROR;
}
@ -97,6 +104,7 @@ public class Reporter {
return Level.WARN;
}
// anything else including verbosityStr.equalsIgnoreCase("INFO")
return Level.INFO;
}
@ -114,13 +122,30 @@ public class Reporter {
}
}
/**
* Report an internal message of level DEBUG. Message text is prefixed with the string "SLF4J(D)",
* with (D) standing as a shorthand for DEBUG.
*
* <p>Messages of level DEBUG are be enabled when the {@link #SLF4J_INTERNAL_VERBOSITY_KEY}
* system property is set to "DEBUG" and disabled when set to "INFO", "WARN" or "ERROR". By default,
* {@link #SLF4J_INTERNAL_VERBOSITY_KEY} is set to "INFO".</p>
*
* @param msg the message text
* @since 2.0.16
*/
public static void debug(String msg) {
if(isEnabledFor(Level.DEBUG)) {
getTarget().println(SLF4J_DEBUG_PREFIX + msg);
}
}
/**
* Report an internal message of level INFO. Message text is prefixed with the string "SLF4J(I)", with
* (I) standing as a shorthand for INFO.
*
* <p>Messages of level INFO are be enabled when the {@link #SLF4J_INTERNAL_VERBOSITY_KEY} system property is
* set to "INFO" and disabled when set to "WARN" or "ERROR". By default, {@link #SLF4J_INTERNAL_VERBOSITY_KEY} is
* set to "INFO".</p>
* set to "DEBUG" or "INFO" and disabled when set to "WARN" or "ERROR". By default,
* {@link #SLF4J_INTERNAL_VERBOSITY_KEY} is set to "INFO".</p>
*
* @param msg the message text
*/
@ -136,8 +161,8 @@ public class Reporter {
* (W) standing as a shorthand for WARN.
*
* <p>Messages of level WARN are be enabled when the {@link #SLF4J_INTERNAL_VERBOSITY_KEY} system property is
* set to "INFO" or "WARN" and disabled when set to "ERROR". By default, {@link #SLF4J_INTERNAL_VERBOSITY_KEY} is
* set to "INFO".</p>
* set to "DEBUG", "INFO" or "WARN" and disabled when set to "ERROR". By default,
* {@link #SLF4J_INTERNAL_VERBOSITY_KEY} is set to "INFO".</p>
*
* @param msg the message text
*/
@ -147,7 +172,6 @@ public class Reporter {
}
}
/**
* Report an internal message of level "ERROR accompanied by a {@link Throwable}.
* Message text is prefixed with the string "SLF4J(E)", with (E) standing as a shorthand for ERROR.
@ -164,10 +188,9 @@ public class Reporter {
t.printStackTrace(getTarget());
}
/**
* Report an internal message of level "ERROR". Message text is prefixed with the string "SLF4J(E)", with
* (E) standing as a shorthand for ERROR.
* Report an internal message of level "ERROR". Message text is prefixed with the string "SLF4J(E)",
* with (E) standing as a shorthand for ERROR.
*
* <p>Messages of level ERROR are always enabled.
*

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2004-2024 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;
/**
* Various utility methods
*
* @since 2.0.14
*/
public class Slf4jEnvUtil {
/**
* Returns the current version of slf4j, or null if data is not available.
*
* @return current version or null if missing version data
* @since 2.0.14
*/
static public String slf4jVersion() {
// String moduleVersion = slf4jVersionByModule();
// if(moduleVersion != null)
// return moduleVersion;
Package pkg = Slf4jEnvUtil.class.getPackage();
if(pkg == null) {
return null;
}
final String pkgVersion = pkg.getImplementationVersion();
return pkgVersion;
}
/**
* Returns the current version of slf4j via class.getModule()
* or null if data is not available.
*
* @return current version or null if missing version data
* @since 2.0.14
*/
// static private String slf4jVersionByModule() {
// Module module = Slf4jEnvUtil.class.getModule();
// if (module == null)
// return null;
//
// ModuleDescriptor md = module.getDescriptor();
// if (md == null)
// return null;
// Optional<String> opt = md.rawVersion();
// return opt.orElse(null);
// }
}

View File

@ -7,8 +7,18 @@ import org.slf4j.spi.SLF4JServiceProvider;
public class SubstituteServiceProvider implements SLF4JServiceProvider {
private final SubstituteLoggerFactory loggerFactory = new SubstituteLoggerFactory();
private final IMarkerFactory markerFactory = new BasicMarkerFactory();
private final MDCAdapter mdcAdapter = new BasicMDCAdapter();
// LoggerFactory expects providers to initialize markerFactory as early as possible.
private final IMarkerFactory markerFactory;
// LoggerFactory expects providers to initialize their MDCAdapter field
// as early as possible, preferably at construction time.
private final MDCAdapter mdcAdapter;
public SubstituteServiceProvider() {
markerFactory = new BasicMarkerFactory();
mdcAdapter = new BasicMDCAdapter();
}
@Override
public ILoggerFactory getLoggerFactory() {
@ -36,6 +46,5 @@ public class SubstituteServiceProvider implements SLF4JServiceProvider {
@Override
public void initialize() {
}
}

View File

@ -117,14 +117,28 @@ public final class Util {
return trace[i + 2];
}
// private static final void report(String msg, Throwable t) {
// System.err.println(msg);
// System.err.println("Reported exception:");
// t.printStackTrace();
// }
//
// static final private void report(String msg) {
// System.err.println("SLF4J: " + msg);
// }
/**
* See {@link Reporter#error(String, Throwable)} class for alternative.
*
* @deprecated replaced by the {@link Reporter#error(String, Throwable)} method.
* @param msg message to print
* @param t throwable to print
*/
static final public void report(String msg, Throwable t) {
System.err.println(msg);
System.err.println("Reported exception:");
t.printStackTrace();
}
/**
* See {@link Reporter} class for alternatives.
*
* @deprecated replaced by one of {@link Reporter#info(String)},
* {@link Reporter#warn(String)} or {@link Reporter#error(String)} methods.
* @param msg message to print
*/
static final public void report(String msg) {
System.err.println("SLF4J: " + msg);
}
}

View File

@ -1,5 +0,0 @@
/**
* Various SLF4J <b>internal</b> utility and helper classes.
*
*/
package org.slf4j.helpers;

View File

@ -0,0 +1,16 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title></title>
</head>
<body>
<p>Helper classes.</p>
<hr/>
</body>
</html>

View File

@ -1,6 +0,0 @@
/**
* Core logging interfaces.
*
* This packages contains the "core", that is client facing, classes and interfaces of the SLF4J API.
*/
package org.slf4j;

View File

@ -0,0 +1,16 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title></title>
</head>
<body>
<p>Core logging interfaces.</p>
<hr>
</body>
</html>

View File

@ -1,7 +1,7 @@
/**
* Copyright (c) 2004-2022 QOS.ch
* All rights reserved.
*
* <p>
* 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
@ -9,10 +9,10 @@
* 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:
*
* <p>
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* <p>
* 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
@ -20,10 +20,10 @@
* 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.spi;
import java.util.List;
import java.util.function.Supplier;
import org.slf4j.Logger;
@ -34,19 +34,15 @@ import org.slf4j.event.Level;
import org.slf4j.event.LoggingEvent;
/**
* Default implementation of {@link LoggingEventBuilder}.
*
* <p>It is assumed that when </p>
*
* @since 2.0.0
* Default implementation of {@link LoggingEventBuilder}
*/
public class DefaultLoggingEventBuilder implements LoggingEventBuilder, CallerBoundaryAware {
// The caller boundary when the log() methods are invoked, is this class itself.
static String DLEB_FQCN = DefaultLoggingEventBuilder.class.getName();
protected DefaultLoggingEvent loggingEvent;
protected Logger logger;
@ -57,7 +53,7 @@ public class DefaultLoggingEventBuilder implements LoggingEventBuilder, CallerBo
/**
* Add a marker to the current logging event being built.
*
* <p>
* It is possible to add multiple markers to the same logging event.
*
* @param marker the marker to add
@ -76,166 +72,16 @@ public class DefaultLoggingEventBuilder implements LoggingEventBuilder, CallerBo
@Override
public LoggingEventBuilder addArgument(Object p) {
loggingEvent.addArgument(p);
this.loggingEvent.addArgument(p);
return this;
}
@Override
public LoggingEventBuilder addArgument(Supplier<?> objectSupplier) {
loggingEvent.addArgument(objectSupplier.get());
this.loggingEvent.addArgument(objectSupplier.get());
return this;
}
@Override
public void setCallerBoundary(String fqcn) {
loggingEvent.setCallerBoundary(fqcn);
}
@Override
public void log() {
log(loggingEvent);
}
@Override
public LoggingEventBuilder setMessage(String message) {
loggingEvent.setMessage(message);
return this;
}
@Override
public LoggingEventBuilder setMessage(Supplier<String> messageSupplier) {
loggingEvent.setMessage(messageSupplier.get());
return this;
}
@Override
public void log(String message) {
loggingEvent.setMessage(message);
log(loggingEvent);
}
@Override
public void log(String message, Object arg) {
loggingEvent.setMessage(message);
loggingEvent.addArgument(arg);
log(loggingEvent);
}
@Override
public void log(String message, Object arg0, Object arg1) {
loggingEvent.setMessage(message);
loggingEvent.addArgument(arg0);
loggingEvent.addArgument(arg1);
log(loggingEvent);
}
@Override
public void log(String message, Object... args) {
loggingEvent.setMessage(message);
loggingEvent.addArguments(args);
log(loggingEvent);
}
@Override
public void log(Supplier<String> messageSupplier) {
if (messageSupplier == null) {
log((String) null);
} else {
log(messageSupplier.get());
}
}
protected void log(LoggingEvent aLoggingEvent) {
setCallerBoundary(DLEB_FQCN);
if (logger instanceof LoggingEventAware) {
((LoggingEventAware) logger).log(aLoggingEvent);
} else {
logViaPublicSLF4JLoggerAPI(aLoggingEvent);
}
}
private void logViaPublicSLF4JLoggerAPI(LoggingEvent aLoggingEvent) {
Object[] argArray = aLoggingEvent.getArgumentArray();
int argLen = argArray == null ? 0 : argArray.length;
Throwable t = aLoggingEvent.getThrowable();
int tLen = t == null ? 0 : 1;
String msg = aLoggingEvent.getMessage();
Object[] combinedArguments = new Object[argLen + tLen];
if (argArray != null) {
System.arraycopy(argArray, 0, combinedArguments, 0, argLen);
}
if (t != null) {
combinedArguments[argLen] = t;
}
msg = mergeMarkersAndKeyValuePairs(aLoggingEvent, msg);
switch (aLoggingEvent.getLevel()) {
case TRACE:
logger.trace(msg, combinedArguments);
break;
case DEBUG:
logger.debug(msg, combinedArguments);
break;
case INFO:
logger.info(msg, combinedArguments);
break;
case WARN:
logger.warn(msg, combinedArguments);
break;
case ERROR:
logger.error(msg, combinedArguments);
break;
}
}
/**
* Prepend markers and key-value pairs to the message.
*
* @param aLoggingEvent
* @param msg
* @return
*/
private String mergeMarkersAndKeyValuePairs(LoggingEvent aLoggingEvent, String msg) {
StringBuilder sb = null;
if (aLoggingEvent.getMarkers() != null) {
sb = new StringBuilder();
for (Marker marker : aLoggingEvent.getMarkers()) {
sb.append(marker);
sb.append(' ');
}
}
if (aLoggingEvent.getKeyValuePairs() != null) {
if (sb == null) {
sb = new StringBuilder();
}
for (KeyValuePair kvp : aLoggingEvent.getKeyValuePairs()) {
sb.append(kvp.key);
sb.append('=');
sb.append(kvp.value);
sb.append(' ');
}
}
if (sb != null) {
sb.append(msg);
return sb.toString();
} else {
return msg;
}
}
@Override
public LoggingEventBuilder addKeyValue(String key, Object value) {
loggingEvent.addKeyValue(key, value);
@ -248,4 +94,184 @@ public class DefaultLoggingEventBuilder implements LoggingEventBuilder, CallerBo
return this;
}
@Override
public void setCallerBoundary(String fqcn) {
this.loggingEvent.setCallerBoundary(fqcn);
}
@Override
public void log() {
log(this.loggingEvent);
}
@Override
public LoggingEventBuilder setMessage(String message) {
this.loggingEvent.setMessage(message);
return this;
}
@Override
public LoggingEventBuilder setMessage(Supplier<String> messageSupplier) {
this.loggingEvent.setMessage(messageSupplier.get());
return this;
}
@Override
public void log(String message) {
this.loggingEvent.setMessage(message);
log(this.loggingEvent);
}
@Override
public void log(String message, Object arg) {
this.loggingEvent.setMessage(message);
this.loggingEvent.addArgument(arg);
log(this.loggingEvent);
}
@Override
public void log(String message, Object arg0, Object arg1) {
this.loggingEvent.setMessage(message);
this.loggingEvent.addArgument(arg0);
this.loggingEvent.addArgument(arg1);
log(this.loggingEvent);
}
@Override
public void log(String message, Object... args) {
this.loggingEvent.setMessage(message);
this.loggingEvent.addArguments(args);
log(this.loggingEvent);
}
@Override
public void log(Supplier<String> messageSupplier) {
if(messageSupplier == null) {
log((String) null);
} else {
log(messageSupplier.get());
}
}
protected void log(LoggingEvent aLoggingEvent) {
if(aLoggingEvent.getCallerBoundary() == null) {
setCallerBoundary(DLEB_FQCN);
}
if(logger instanceof LoggingEventAware) {
((LoggingEventAware) logger).log(aLoggingEvent);
} else if(logger instanceof LocationAwareLogger) {
logViaLocationAwareLoggerAPI((LocationAwareLogger) logger, aLoggingEvent);
} else {
logViaPublicSLF4JLoggerAPI(aLoggingEvent);
}
}
private void logViaLocationAwareLoggerAPI(LocationAwareLogger locationAwareLogger, LoggingEvent aLoggingEvent) {
List<Marker> markerList = aLoggingEvent.getMarkers();
Marker firstMarker = (markerList != null && !markerList.isEmpty()) ? markerList.get(0) : null;
String mergedMessage = mergeMarkersAndKeyValuePairsAndMessage(aLoggingEvent);
locationAwareLogger.log(firstMarker, aLoggingEvent.getCallerBoundary(), aLoggingEvent.getLevel().toInt(),
mergedMessage,
aLoggingEvent.getArgumentArray(), aLoggingEvent.getThrowable());
}
private void logViaPublicSLF4JLoggerAPI(LoggingEvent aLoggingEvent) {
Object[] argArray = aLoggingEvent.getArgumentArray();
int argLen = argArray == null ? 0 : argArray.length;
Throwable t = aLoggingEvent.getThrowable();
int tLen = t == null ? 0 : 1;
Object[] combinedArguments = new Object[argLen + tLen];
if(argArray != null) {
System.arraycopy(argArray, 0, combinedArguments, 0, argLen);
}
if(t != null) {
combinedArguments[argLen] = t;
}
String mergedMessage = mergeMarkersAndKeyValuePairsAndMessage(aLoggingEvent);
switch(aLoggingEvent.getLevel()) {
case TRACE:
logger.trace(mergedMessage, combinedArguments);
break;
case DEBUG:
logger.debug(mergedMessage, combinedArguments);
break;
case INFO:
logger.info(mergedMessage, combinedArguments);
break;
case WARN:
logger.warn(mergedMessage, combinedArguments);
break;
case ERROR:
logger.error(mergedMessage, combinedArguments);
break;
}
}
/**
* Prepend markers and key-value pairs to the message.
*
* @param aLoggingEvent
*
* @return
*/
private String mergeMarkersAndKeyValuePairsAndMessage(LoggingEvent aLoggingEvent) {
StringBuilder sb = mergeMarkers(aLoggingEvent.getMarkers(), null);
sb = mergeKeyValuePairs(aLoggingEvent.getKeyValuePairs(), sb);
final String mergedMessage = mergeMessage(aLoggingEvent.getMessage(), sb);
return mergedMessage;
}
private StringBuilder mergeMarkers(List<Marker> markerList, StringBuilder sb) {
if(markerList == null || markerList.isEmpty())
return sb;
if(sb == null)
sb = new StringBuilder();
for(Marker marker : markerList) {
sb.append(marker);
sb.append(' ');
}
return sb;
}
private StringBuilder mergeKeyValuePairs(List<KeyValuePair> keyValuePairList, StringBuilder sb) {
if(keyValuePairList == null || keyValuePairList.isEmpty())
return sb;
if(sb == null)
sb = new StringBuilder();
for(KeyValuePair kvp : keyValuePairList) {
sb.append(kvp.key);
sb.append('=');
sb.append(kvp.value);
sb.append(' ');
}
return sb;
}
private String mergeMessage(String msg, StringBuilder sb) {
if(sb != null) {
sb.append(msg);
return sb.toString();
} else {
return msg;
}
}
}

View File

@ -34,18 +34,6 @@ import org.slf4j.Marker;
* which need to provide hints so that the underlying logging system can extract
* the correct location information (method name, line number).
*
* <p></p>
*
* <p>In response to <a href="https://jira.qos.ch/browse/SLF4J-118">SLF4J-118</a>,
* the {@link #log(Marker, String, int, String, Object[], Throwable) log()} method was modified to accept
* an additional <code>Object[]</code> parameter.
* This Object[] represents arguments of the log request. Due to this modification, slf4j-api
* version 1.6.x no longer work with bindings shipping with SLF4J 1.5.x, instead
* bindings shipping with 1.6.x or later are required. See also
* <a href="https://github.com/qos-ch/slf4j/commit/6dd2bd58cff">commit 6dd2</a> dated
* April 9th, 2010.
* </p>
*
* @author Ceki G&uuml;lc&uuml;
* @since 1.3
*/

View File

@ -0,0 +1,58 @@
/**
* 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.spi;
import org.slf4j.ILoggerFactory;
/**
* An internal interface which helps the static {@link org.slf4j.LoggerFactory}
* class bind with the appropriate {@link ILoggerFactory} instance.
*
* @author Ceki G&uuml;lc&uuml;
* @deprecated
*/
public interface LoggerFactoryBinder {
/**
* Return the instance of {@link ILoggerFactory} that
* {@link org.slf4j.LoggerFactory} class should bind to.
*
* @return the instance of {@link ILoggerFactory} that
* {@link org.slf4j.LoggerFactory} class should bind to.
*/
public ILoggerFactory getLoggerFactory();
/**
* The String form of the {@link ILoggerFactory} object that this
* <code>LoggerFactoryBinder</code> instance is <em>intended</em> to return.
*
* <p>This method allows the developer to interrogate this binder's intention
* which may be different from the {@link ILoggerFactory} instance it is able to
* yield in practice. The discrepancy should only occur in case of errors.
*
* @return the class name of the intended {@link ILoggerFactory} instance
*/
public String getLoggerFactoryClassStr();
}

View File

@ -31,10 +31,9 @@ import org.slf4j.Marker;
import org.slf4j.helpers.CheckReturnValue;
/**
* This is the central interface in slf4j's fluent API for creating
* This is the main interface in slf4j's fluent API for creating
* {@link org.slf4j.event.LoggingEvent logging events}.
*
*
*
* @author Ceki G&uuml;lc&uuml;
* @since 2.0.0
*/
@ -43,7 +42,7 @@ public interface LoggingEventBuilder {
/**
* Set the cause for the logging event being built.
* @param cause a throwable
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @return a LoggingEventBuilder, usually <b>this</b>.
*/
@CheckReturnValue
LoggingEventBuilder setCause(Throwable cause);
@ -52,383 +51,54 @@ public interface LoggingEventBuilder {
* A {@link Marker marker} to the event being built.
*
* @param marker a Marker instance to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @return a LoggingEventBuilder, usually <b>this</b>.
*/
@CheckReturnValue
LoggingEventBuilder addMarker(Marker marker);
/**
* Add an argument to the event being built.
* Synonymous with {@link #arg(Object)} method.
*
* @param p an Object to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @return a LoggingEventBuilder, usually <b>this</b>.
*/
@CheckReturnValue
LoggingEventBuilder addArgument(Object p);
/**
* Add an argument to the event being built.
* Synonymous with {@link #addArgument(Object)} method.
* Add an argument supplier to the event being built.
*
* @param p an Object to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @since 2.1.0
*/
@CheckReturnValue
default LoggingEventBuilder arg(Object p) {
return addArgument(p);
}
/**
* <p>Add an argument supplier to the event being built.
* Synonymous with {@link #arg(Supplier)} method.
* </p>
* @param objectSupplier an Object supplier to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @return a LoggingEventBuilder, usually <b>this</b>.
*/
@CheckReturnValue
LoggingEventBuilder addArgument(Supplier<?> objectSupplier);
/**
* <p>Add an argument supplier to the event being built.
* Synonymous with {@link #addArgument(Supplier)} method.
* </p>
*
* @param objectSupplier an Object supplier to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @since 2.1.0
*/
@CheckReturnValue
default LoggingEventBuilder arg(Supplier<?> objectSupplier) {
return addArgument(objectSupplier);
}
/**
* Add a value of type <code>boolean</code> to the event being built.
*
* <p>The default implementation simply casts to <code>Boolean</code>. However, the NOP implementation, i.e.
* {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param b a value of type <code>boolean</code> value to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @since 2.1.0
*/
default public LoggingEventBuilder arg(boolean b) {
return addArgument((Boolean) b);
}
/**
* Add a value of type <code>char</code> to the event being built.
*
* <p>The default implementation simply casts to <code>Character</code>. However, the NOP implementation, i.e.
* {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param c a value of type <code>char</code> value to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @since 2.1.0
*/
default public LoggingEventBuilder arg(char c) {
return addArgument((Character) c);
}
/**
* Add a value of type <code>byte</code> to the event being built.
*
* <p>The default implementation simply casts to <code>Byte</code>. However, the NOP implementation, i.e.
* {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param b a value of type <code>byte</code> value to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @since 2.1.0
*/
default public LoggingEventBuilder arg(byte b) {
return addArgument((Byte) b);
}
/**
* Add a value of type <code>short</code> to the event being built.
*
* <p>The default implementation simply casts to <code>Short</code>. However, the NOP implementation, i.e.
* {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param s a value of type <code>short</code> value to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @since 2.1.0
*/
default public LoggingEventBuilder arg(short s) {
return addArgument((Short) s);
}
/**
* Add a value of type <code>int</code> to the event being built.
*
* <p>The default implementation simply casts to <code>Integer</code>. However, the NOP implementation, i.e.
* {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param i a value of type <code>int</code> value to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @since 2.1.0
*/
default public LoggingEventBuilder arg(int i) {
return addArgument((Integer) i);
}
/**
* Add a value of type <code>long</code> to the event being built.
*
* <p>The default implementation simply casts to <code>Long</code>. However, the NOP implementation, i.e.
* {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param l a value of type <code>long</code> value to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @since 2.1.0
*/
default public LoggingEventBuilder arg(long l) {
return addArgument((Long) l);
}
/**
* Add a value of type <code>float</code> to the event being built.
*
* <p>The default implementation simply casts to <code>Float</code>. However, the NOP implementation, i.e.
* {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param f a value of type <code>float</code> value to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @since 2.1.0
*/
default public LoggingEventBuilder arg(float f) {
return addArgument((Float) f);
}
/**
* Add a value of type <code>double</code> to the event being built.
*
* <p>The default implementation simply casts to <code>Double</code>. However, the NOP implementation skips the cast.</p>
*
* @param d a value of type <code>double</code> value to add.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @since 2.1.0
*/
default LoggingEventBuilder arg(double d) {
return arg((Double) d);
}
/**
* Add a {@link org.slf4j.event.KeyValuePair key value pair} to the event being built.
*
* @param key the key of the key value pair.
* @param value the value of the key value pair.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @return a LoggingEventBuilder, usually <b>this</b>.
*/
@CheckReturnValue
LoggingEventBuilder addKeyValue(String key, Object value);
/**
* Add a {@link org.slf4j.event.KeyValuePair key value pair} to the event being built.
* Synonymous with {@link #addKeyValue(String, Object)} method.
*
* @param key the key of the key value pair.
* @param value the value of the key value pair.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
*
* @since 2.1.0
*/
@CheckReturnValue
default LoggingEventBuilder kv(String key, Object value) {
return addKeyValue(key,value);
}
/**
* Add a {@link org.slf4j.event.KeyValuePair key value pair} to the event being built.
*
* @param key the key of the key value pair.
* @param valueSupplier a supplier of a value for the key value pair.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @return a LoggingEventBuilder, usually <b>this</b>.
*/
@CheckReturnValue
LoggingEventBuilder addKeyValue(String key, Supplier<Object> valueSupplier);
/**
* Add a {@link org.slf4j.event.KeyValuePair key value pair} to the event being built.
* Synonymous with {@link #addKeyValue(String, Supplier)} method.
*
* @param key the key of the key value pair.
* @param valueSupplier a supplier of a value for the key value pair.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
*
* @since 2.1.0
*/
@CheckReturnValue
default LoggingEventBuilder kv(String key, Supplier<Object> valueSupplier) {
return addKeyValue(key, valueSupplier);
}
/**
* <p>Add a {@link org.slf4j.event.KeyValuePair key value pair} to the event being built, with the value part being
* of type <code>boolean</code>.
* </p>
* <p></p>
* <p>The default implementation simply casts to value part to <code>Boolean</code> before calling
* {@link #addKeyValue(String, Object)}. However, the
* NOP implementation, i.e {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param key the key of the key value pair.
* @param b the value of type <code>boolean</code> of the key value pair.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
*
* @since 2.1.0
*/
default public LoggingEventBuilder kv(String key, boolean b) {
return addKeyValue(key, (Boolean) b);
}
/**
* <p>Add a {@link org.slf4j.event.KeyValuePair key value pair} to the event being built, with the value part being
* of type <code>char</code>.
* </p>
* <p></p>
* <p>The default implementation simply casts to value part to <code>Character</code> before calling
* {@link #addKeyValue(String, Object)}. However, the
* NOP implementation, i.e {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param key the key of the key value pair.
* @param c the value of type <code>char</code> of the key value pair.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
*
* @since 2.1.0
*/
default public LoggingEventBuilder kv(String key, char c) {
return addKeyValue(key, (Character) c);
}
/**
* <p>Add a {@link org.slf4j.event.KeyValuePair key value pair} to the event being built, with the value part being
* of type <code>byte</code>.
* </p>
* <p></p>
* <p>The default implementation simply casts to value part to <code>Byte</code> before calling
* {@link #addKeyValue(String, Object)}. However, the
* NOP implementation, i.e {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param key the key of the key value pair.
* @param b the value of type <code>byte</code> of the key value pair.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
*
* @since 2.1.0
*/
default public LoggingEventBuilder kv(String key, byte b) {
return addKeyValue(key, (Byte) b);
}
/**
* <p>Add a {@link org.slf4j.event.KeyValuePair key value pair} to the event being built, with the value part being
* of type <code>short</code>.
* </p>
* <p></p>
* <p>The default implementation simply casts to value part to <code>Short</code> before calling
* {@link #addKeyValue(String, Object)}. However, the
* NOP implementation, i.e {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param key the key of the key value pair.
* @param s the value of type <code>short</code> of the key value pair.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
*
* @since 2.1.0
*/
default public LoggingEventBuilder kv(String key, short s) {
return addKeyValue(key, (Short) s);
}
/**
* <p>Add a {@link org.slf4j.event.KeyValuePair key value pair} to the event being built, with the value part being
* of type <code>int</code>.
* </p>
* <p></p>
* <p>The default implementation simply casts to value part to <code>Integer</code> before calling
* {@link #addKeyValue(String, Object)}. However, the
* NOP implementation, i.e {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param key the key of the key value pair.
* @param i the value of type <code>int</code> of the key value pair.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
*
* @since 2.1.0
*/
default public LoggingEventBuilder kv(String key, int i) {
return addKeyValue(key, (Integer) i);
}
/**
* <p>Add a {@link org.slf4j.event.KeyValuePair key value pair} to the event being built, with the value part being
* of type <code>long</code>.
* </p>
* <p></p>
* <p>The default implementation simply casts to value part to <code>Integer</code> before calling
* {@link #addKeyValue(String, Object)}. However, the
* NOP implementation, i.e {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param key the key of the key value pair.
* @param l the value of type <code>long</code> of the key value pair.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
*
* @since 2.1.0
*/
default public LoggingEventBuilder kv(String key, long l) {
return addKeyValue(key, (Long) l);
}
/**
* <p>Add a {@link org.slf4j.event.KeyValuePair key value pair} to the event being built, with the value part being
* of type <code>float</code>.
* </p>
* <p></p>
* <p>The default implementation simply casts to value part to <code>Float</code> before calling
* {@link #addKeyValue(String, Object)}. However, the
* NOP implementation, i.e {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param key the key of the key value pair.
* @param f the value of type <code>float</code> of the key value pair.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
*
* @since 2.1.0
*/
default public LoggingEventBuilder kv(String key, float f) {
return addKeyValue(key, (Float) f);
}
/**
* <p>Add a {@link org.slf4j.event.KeyValuePair key value pair} to the event being built, with the value part being
* of type <code>double</code>.
* </p>
* <p></p>
* <p>The default implementation simply casts to value part to <code>Double</code> before calling
* {@link #addKeyValue(String, Object)}. However, the
* NOP implementation, i.e {@link NOPLoggingEventBuilder}, skips the cast.</p>
*
* @param key the key of the key value pair.
* @param f the value of type <code>double</code> of the key value pair.
* @return a LoggingEventBuilder instance, usually <b>this</b>.
*
* @since 2.1.0
*/
default public LoggingEventBuilder kv(String key, double f) {
return addKeyValue(key, (Double) f);
}
/**
* Sets the message of the logging event.
*
* @param message the message of the event
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @since 2.0.0
* @since 2.0.0-beta0
*/
@CheckReturnValue
LoggingEventBuilder setMessage(String message);
@ -437,7 +107,6 @@ public interface LoggingEventBuilder {
* Sets the message of the event via a message supplier.
*
* @param messageSupplier supplies a String to be used as the message for the event
* @return a LoggingEventBuilder instance, usually <b>this</b>.
* @since 2.0.0-beta0
*/
@CheckReturnValue

View File

@ -93,7 +93,7 @@ public interface MDCAdapter {
public void setContextMap(Map<String, String> contextMap);
/**
* Push a value into the deque(stack) referenced by 'key'.
* Push a value into the <b>deque(stack)</b> referenced by 'key'.
*
* @param key identifies the appropriate stack
* @param value the value to push into the stack
@ -102,7 +102,7 @@ public interface MDCAdapter {
public void pushByKey(String key, String value);
/**
* Pop the stack referenced by 'key' and return the value possibly null.
* Pop the <b>stack</b> referenced by 'key' and return the value possibly null.
*
* @param key identifies the deque(stack)
* @return the value just popped. May be null/
@ -111,7 +111,7 @@ public interface MDCAdapter {
public String popByKey(String key);
/**
* Returns a copy of the deque(stack) referenced by 'key'. May be null.
* Returns a copy of the <b>deque(stack)</b> referenced by 'key'. May be null.
*
* @param key identifies the stack
* @return copy of stack referenced by 'key'. May be null.
@ -122,7 +122,7 @@ public interface MDCAdapter {
/**
* Clear the deque(stack) referenced by 'key'.
* Clear the <b>deque(stack)</b> referenced by 'key'.
*
* @param key identifies the stack
*

View File

@ -0,0 +1,58 @@
/**
* 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.spi;
import org.slf4j.IMarkerFactory;
/**
* An internal interface which helps the static {@link org.slf4j.MarkerFactory}
* class bind with the appropriate {@link IMarkerFactory} instance.
*
* @author Ceki G&uuml;lc&uuml;
* @deprecated
*/
public interface MarkerFactoryBinder {
/**
* Return the instance of {@link IMarkerFactory} that
* {@link org.slf4j.MarkerFactory} class should bind to.
*
* @return the instance of {@link IMarkerFactory} that
* {@link org.slf4j.MarkerFactory} class should bind to.
*/
public IMarkerFactory getMarkerFactory();
/**
* The String form of the {@link IMarkerFactory} object that this
* <code>MarkerFactoryBinder</code> instance is <em>intended</em> to return.
*
* <p>This method allows the developer to interrogate this binder's intention
* which may be different from the {@link IMarkerFactory} instance it is able to
* return. Such a discrepancy should only occur in case of errors.
*
* @return the class name of the intended {@link IMarkerFactory} instance
*/
public String getMarkerFactoryClassStr();
}

View File

@ -2,20 +2,15 @@ package org.slf4j.spi;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.event.Level;
/**
* <p>A no-operation implementation of {@link LoggingEventBuilder}.</p>
* <p></p>
* <p>As the name indicates, the methods in this class do nothing. In case a return value is expected, a singleton,
* i.e. the unique instance of this class, is returned.
* </p>
* <p></p>
* <p>Note that the default implementations of {@link Logger#atTrace()}, {@link Logger#atDebug()} , {@link Logger#atInfo()},
* {@link Logger#atWarn()} and {@link Logger#atError()}, return an instance of {@link NOPLoggingEventBuilder}
* when the relevant level is disabled for current logger. This is the core optimization in the SLF4J fluent API.</p>
*
* <p>As the name indicates, the method in this class do nothing, except when a return value is expected
* in which case a singleton, i.e. the unique instance of this class is returned.
* </p
*
* @author Ceki G&uuml;lc&uuml;
* @since 2.0.0
@ -38,379 +33,68 @@ public class NOPLoggingEventBuilder implements LoggingEventBuilder {
return SINGLETON;
}
/**
* <p>NOP implementation that does nothing.</p>
*
* @param marker a Marker instance to add.
* @return
*/
@Override
public LoggingEventBuilder addMarker(Marker marker) {
return this;
return singleton();
}
/**
* <p>NOP implementation that does nothing.</p>
*
* @param p
* @return a LoggingEventBuilder, usually <b>this</b>.
* @since 2.1.0
*/
@Override
public LoggingEventBuilder addArgument(Object p) {
return this;
return singleton();
}
/**
* <p>NOP implementation that does nothing and thus skips calling get() call on the object supplier.</p>
*
* @param objectSupplier
* @return a LoggingEventBuilder, usually <b>this</b>.
* @since 2.1.0
*/
@Override
public LoggingEventBuilder addArgument(Supplier<?> objectSupplier) {
return this;
return singleton();
}
/**
* <p>NOP implementation that does nothing and thus skips calling get() call on the object supplier.</p>
*
* @param objectSupplier
* @return a LoggingEventBuilder, usually <b>this</b>.
* @since 2.1.0
*/
@Override
public LoggingEventBuilder arg(Supplier<?> objectSupplier) {
return this;
}
/**
* <p>NOP implementation that does nothing and thus skips the type cast.</p>
*
* @param b a value of type <code>boolean</code> value to add.
* @return a LoggingEventBuilder, usually <b>this</b>.
* @since 2.1.0
*/
public LoggingEventBuilder arg(boolean b) {
return this;
}
/**
* <p>NOP implementation that does nothing and thus skips the type cast.</p>
*
* @param c a value of type <code>char</code> value to add.
* @return a LoggingEventBuilder, usually <b>this</b>.
* @since 2.1.0
*/
@Override
public LoggingEventBuilder arg(char c) {
return this;
}
/**
* <p>NOP implementation that does nothing and thus skips the type cast.</p>
*
* @param b a value of type <code>byte</code> value to add.
* @return a LoggingEventBuilder, usually <b>this</b>.
* @since 2.1.0
*/
@Override
public LoggingEventBuilder arg(byte b) {
return this;
}
/**
* <p>NOP implementation that does nothing and thus skips the type cast.</p>
*
* @param s a value of type <code>short</code> value to add.
* @return a LoggingEventBuilder, usually <b>this</b>.
* @since 2.1.0
*/
public LoggingEventBuilder arg(short s) {
return this;
}
/**
* <p>NOP implementation that does nothing and thus skips the type cast.</p>
*
* @param i a value of type <code>int</code> value to add.
* @return a LoggingEventBuilder, usually <b>this</b>.
* @since 2.1.0
*/
@Override
public LoggingEventBuilder arg(int i) {
return this;
}
/**
* <p>NOP implementation that does nothing and thus skips the type cast.</p>
*
* @param l a value of type <code>long</code> value to add.
* @return a LoggingEventBuilder, usually <b>this</b>.
* @since 2.1.0
*/
@Override
public LoggingEventBuilder arg(long l) {
return this;
}
/**
* <p>NOP implementation that does nothing and thus skips the type cast.</p>
*
* @param f a value of type <code>float</code> value to add.
* @return a LoggingEventBuilder, usually <b>this</b>.
* @since 2.1.0
*/
@Override
public LoggingEventBuilder arg(float f) {
return this;
}
/**
* <p>NOP implementation that does nothing and thus skips the type cast.</p>
*
* @param d a value of type <code>float</code> value to add.
* @return a LoggingEventBuilder, usually <b>this</b>.
* @since 2.1.0
*/
@Override
public LoggingEventBuilder arg(double d) {
return this;
}
/**
* NOP implementation that does nothing.
*
* @param key the key of the key value pair.
* @param value the value of the key value pair.
* @return a LoggingEventBuilder, usually <b>this</b>.
*/
@Override
public LoggingEventBuilder addKeyValue(String key, Object value) {
return this;
return singleton();
}
/**
* NOP implementation that doesnothing.
*
* @param key the key of the key value pair.
* @param value the value of the key value pair.
* @return a LoggingEventBuilder, usually <b>this</b>.
*/
@Override
public LoggingEventBuilder kv(String key, Object value) {
return this;
}
/**
* NOP implementation that doesnothing.
*
* @param key the key of the key value pair.
* @param value a supplier of a value for the key value pair.
* @return a LoggingEventBuilder, usually <b>this</b>.
*/
@Override
public LoggingEventBuilder addKeyValue(String key, Supplier<Object> value) {
return this;
return singleton();
}
/**
* NOP implementation that doesnothing.
*
* @param key the key of the key value pair.
* @param value a supplier of a value for the key value pair.
* @return a LoggingEventBuilder, usually <b>this</b>.
*/
@Override
public LoggingEventBuilder kv(String key, Supplier<Object> value) {
return this;
}
/**
* NOP implementation that does nothing.
*
* @param key the key of the key value pair.
* @param b the value of type <code>boolean</code> of the key value pair.
* @return a LoggingEventBuilder, usually <b>this</b>.
*/
@Override
public LoggingEventBuilder kv(String key, boolean b) {
return this;
}
/**
* NOP implementation that does nothing.
*
* @param key the key of the key value pair.
* @param c the value of type <code>char</code> of the key value pair.
* @return
*/
@Override
public LoggingEventBuilder kv(String key, char c) {
return this;
}
/**
* NOP implementation that does nothing.
*
* @param key the key of the key value pair.
* @param b the value of type <code>byte</code> of the key value pair.
* @return
*/
@Override
public LoggingEventBuilder kv(String key, byte b) {
return this;
}
/**
* NOP implementation that does nothing.
*
* @param key the key of the key value pair.
* @param s the value of type <code>short</code> of the key value pair.
* @return
*/
@Override
public LoggingEventBuilder kv(String key, short s) {
return this;
}
/**
* NOP implementation that does nothing.
*
* @param key the key of the key value pair.
* @param i the value of type <code>int</code> of the key value pair.
* @return
*/
@Override
public LoggingEventBuilder kv(String key, int i) {
return this;
}
/**
* NOP implementation that does nothing.
*
* @param key the key of the key value pair.
* @param l the value of type <code>long</code> of the key value pair.
* @return
*/
@Override
public LoggingEventBuilder kv(String key, long l) {
return this;
}
/**
* NOP implementation that does nothing.
*
* @param key the key of the key value pair.
* @param f the value of type <code>float</code> of the key value pair.
* @return
*/
@Override
public LoggingEventBuilder kv(String key, float f) {
return this;
}
/**
* NOP implementation that does nothing.
*
* @param key the key of the key value pair.
* @param d the value of type <code>double</code> of the key value pair.
* @return
*/
@Override
public LoggingEventBuilder kv(String key, double d) {
return this;
}
/**
* NOP implementation that does nothing.
*
* @param cause a throwable
* @return
*/
@Override
public LoggingEventBuilder setCause(Throwable cause) {
return this;
return singleton();
}
/**
*
*/
@Override
public void log() {
}
/**
* NOP implementation that does nothing.
*
* @param message the message of the event
* @return
*/
@Override
public LoggingEventBuilder setMessage(String message) {
return this;
}
/**
* NOP implementation that does nothing.
*
* @param messageSupplier supplies a String to be used as the message for the event
* @return
*/
@Override
public LoggingEventBuilder setMessage(Supplier<String> messageSupplier) {
return this;
}
/**
* NOP implementation that does nothing.
*
* @param message the message to log
*/
@Override
public void log(String message) {
}
/**
* NOP implementation that does nothing.
*
* @param messageSupplier a Supplier returning a message of type String
*/
@Override
public void log(Supplier<String> messageSupplier) {
}
/**
* NOP implementation that does nothing.
*
* @param message the message to log
* @param arg an argument to be used with the message to log
*/
@Override
public void log(String message, Object arg) {
}
/**
* NOP implementation that does nothing.
*
* @param message the message to log
* @param arg0 first argument to be used with the message to log
* @param arg1 second argument to be used with the message to log
*/
@Override
public void log(String message, Object arg0, Object arg1) {
}
/**
* NOP implementation that does nothing.
*
* @param message the message to log
* @param args a list (actually an array) of arguments to be used with the message to log
*/
@Override
public void log(String message, Object... args) {
}
}

View File

@ -1,10 +0,0 @@
/**
* Contains classes and interfaces which are intended for logging backends.
*
* <p>
* Logging back-ends wishing to interact with SLF4J must provide a {@link org.slf4j.spi.SLF4JServiceProvider}
* implementation in order to be picked up by SLF4J at initialization time.
* </p>
*
*/
package org.slf4j.spi;

View File

@ -0,0 +1,8 @@
<body>
Classes and interfaces which are internal to SLF4J. Under most
circumstances SLF4J users should be oblivious even to the existence of
this package.
</body>

16
slf4j-api/src/main/java9/module-info.java Normal file → Executable file
View File

@ -1,20 +1,8 @@
/**
* <p>This module defines the client-facing SLF4J API. </p>
*
* <p>More specifically, the {@link org.slf4j} package contains client-facing classes and interfaces.</p>
*
* <p>The {@link org.slf4j.spi} package contains classes which are intended for logging backends. In particular, </p>
* ogging back-ends must provide a {@link org.slf4j.spi.SLF4JServiceProvider} implementation in order to be picked
* up by SLF4J at initialization time.
* </p>
*
* @moduleGraph
*/
module org.slf4j {
module org.slf4j {
exports org.slf4j;
exports org.slf4j.spi;
exports org.slf4j.event;
exports org.slf4j.helpers;
uses org.slf4j.spi.SLF4JServiceProvider;
requires java.base;
requires java.base;
}

View File

@ -22,10 +22,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.slf4j.testing;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
package org.slf4j;
import java.util.List;
import java.util.concurrent.CyclicBarrier;

View File

@ -1,115 +0,0 @@
/**
* Copyright (c) 2004-2023 QOS.ch
* All rights reserved.
* <p>
* 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:
* <p>
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* <p>
* 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 org.junit.Test;
import org.slf4j.helpers.BasicMDCAdapter;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
public class MDCAmbitTest {
BasicMDCAdapter mdcAdapter = new BasicMDCAdapter();
MDCAmbit mdca = new MDCAmbit(mdcAdapter);
String k0 = "k0";
String v0 = "v0";
String k1 = "k1";
String v1 = "v0";
String k2 = "k2";
String v2 = "v2";
String kUnused = "kUnused";
void throwRuntimeException() {
throw new RuntimeException();
}
@Test
public void smoke() {
try {
mdca.put(k0, v0);
assertEquals(v0, mdcAdapter.get(k0));
assertNull(mdcAdapter.get(kUnused));
throwRuntimeException();
} catch (RuntimeException e) {
assertEquals(v0, mdcAdapter.get(k0));
} finally {
mdca.clear();
}
assertNull(mdcAdapter.get(k0));
}
@Test
public void empty() {
try {
assertNull(mdcAdapter.get(kUnused));
} finally {
mdca.clear();
}
assertNull(mdcAdapter.get(k0));
}
@Test
public void addKeyTest() {
mdcAdapter.put(k0, v0);
try {
mdca.addKey(k0);
assertEquals(v0, mdcAdapter.get(k0));
assertNull(mdcAdapter.get(kUnused));
throwRuntimeException();
} catch (RuntimeException e) {
assertEquals(v0, mdcAdapter.get(k0));
} finally {
mdca.clear();
}
assertNull(mdcAdapter.get(k0));
}
@Test
public void combinedPut_addKeyTest() {
mdcAdapter.put(k0, v0);
try {
mdca.addKey(k0).put(k1, v1).put(k2, v2);
assertEquals(v0, mdcAdapter.get(k0));
assertEquals(v1, mdcAdapter.get(k1));
assertEquals(v2, mdcAdapter.get(k2));
assertNull(mdcAdapter.get(kUnused));
throwRuntimeException();
} catch (RuntimeException e) {
assertEquals(v0, mdcAdapter.get(k0));
assertEquals(v1, mdcAdapter.get(k1));
assertEquals(v2, mdcAdapter.get(k2));
} finally {
mdca.clear();
}
assertNull(mdcAdapter.get(k0));
assertNull(mdcAdapter.get(k1));
assertNull(mdcAdapter.get(k2));
}
}

View File

@ -22,12 +22,12 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.slf4j.testing;
package org.slf4j.basicTests;
import org.junit.After;
import org.junit.Before;
import org.slf4j.LoggerFactoryFriend;
import org.slf4j.testing.MultithreadedInitializationTest;
import org.slf4j.testHarness.MultithreadedInitializationTest;
/**
* Checks that when no binding is present, proper clean up is performed by LoggerFactory.

View File

@ -29,6 +29,8 @@ import static org.junit.Assert.assertTrue;
import java.util.Random;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -37,11 +39,21 @@ import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import org.slf4j.helpers.BasicMarker;
import org.slf4j.helpers.NOPLogger;
import org.slf4j.helpers.Reporter;
public class NoBindingTest {
int diff = new Random().nextInt(10000);
@Before
public void setUp() throws Exception {
System.setProperty(Reporter.SLF4J_INTERNAL_VERBOSITY_KEY, "debug");
}
@After
public void tearDown() throws Exception {
System.clearProperty(Reporter.SLF4J_INTERNAL_VERBOSITY_KEY);
}
@Test
public void testLogger() {
Logger logger = LoggerFactory.getLogger(NoBindingTest.class);

View File

@ -1,4 +1,4 @@
package org.slf4j.testing;
package org.slf4j.helpers;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;

View File

@ -22,7 +22,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.slf4j.testing;
package org.slf4j.helpers;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@ -34,7 +34,6 @@ import java.util.Map;
import org.junit.After;
import org.junit.Test;
import org.slf4j.helpers.BasicMDCAdapter;
import org.slf4j.spi.MDCAdapter;
/**

View File

@ -22,7 +22,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.slf4j.simple;
package org.slf4j.helpers;
import java.io.PrintStream;
import java.util.ArrayList;

View File

@ -1,4 +1,4 @@
package org.slf4j.testing;
package org.slf4j.testHarness;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@ -12,6 +12,7 @@ import java.util.concurrent.atomic.AtomicLong;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerAccessingThread;
import org.slf4j.LoggerFactory;
import org.slf4j.event.EventRecordingLogger;
import org.slf4j.helpers.SubstituteLogger;
@ -35,16 +36,15 @@ abstract public class MultithreadedInitializationTest {
assertAllSubstLoggersAreFixed();
long recordedEventCount = getRecordedEventCount();
int LENIENCY_COUNT = 21;
int LENIENCY_COUNT = 30;
long expectedEventCount = eventCount.get() + extraLogEvents();
//assertTrue(expectedEventCount + " >= " + recordedEventCount, expectedEventCount >= recordedEventCount);
//assertTrue(expectedEventCount + " < " + recordedEventCount + "+" + LENIENCY_COUNT, expectedEventCount < recordedEventCount + LENIENCY_COUNT);
}
assertTrue("unmet condition: " + expectedEventCount + " >= " + recordedEventCount, expectedEventCount >= recordedEventCount);
assertTrue("unmet condition: " + expectedEventCount + " < " + recordedEventCount + "+" + LENIENCY_COUNT, expectedEventCount < (recordedEventCount + LENIENCY_COUNT)); }
abstract protected long getRecordedEventCount();
protected int extraLogEvents() {
return 0;
}

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
@ -67,7 +67,6 @@
<configuration>
<archive>
<manifestEntries>
<!-- <Automatic-Module-Name>org.slf4j.ext</Automatic-Module-Name>-->
<Premain-Class>org.slf4j.agent.AgentPremain</Premain-Class>
<!-- what is the proper way to specify the maven full name? /ravn -->
<Boot-Class-Path>../../../../javassist/javassist/3.4.GA/javassist-3.4.GA.jar javassist-3.4.GA.jar javassist.jar</Boot-Class-Path>

View File

@ -8,7 +8,7 @@
<parent>
<artifactId>slf4j-parent</artifactId>
<groupId>org.slf4j</groupId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
@ -19,10 +19,6 @@
<url>https://www.slf4j.org</url>
<properties>
<jdk.version>${jdk9.version}</jdk.version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
@ -40,35 +36,35 @@
<build>
<plugins>
<!-- target Java 9+ -->
<!-- <plugin>-->
<!-- <groupId>org.apache.maven.plugins</groupId>-->
<!-- <artifactId>maven-compiler-plugin</artifactId>-->
<!-- <version>${maven-compiler-plugin.version}</version>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <id>default-compile</id>-->
<!-- <goals>-->
<!-- <goal>compile</goal>-->
<!-- </goals>-->
<!-- <configuration>-->
<!-- <source>9</source>-->
<!-- <target>9</target>-->
<!-- <release>9</release>-->
<!-- </configuration> -->
<!-- </execution>-->
<!-- <execution>-->
<!-- <id>default-testCompile</id>-->
<!-- <goals>-->
<!-- <goal>testCompile</goal> -->
<!-- </goals>-->
<!-- <configuration>-->
<!-- <source>9</source>-->
<!-- <target>9</target>-->
<!-- <release>9</release>-->
<!-- </configuration> -->
<!-- </execution> -->
<!-- </executions> -->
<!-- </plugin>-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<executions>
<execution>
<id>default-compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<source>9</source>
<target>9</target>
<release>9</release>
</configuration>
</execution>
<execution>
<id>default-testCompile</id>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<source>9</source>
<target>9</target>
<release>9</release>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -22,13 +22,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/**
* Implementation of {@link System.Logger} interface relaying events to SLF4J.
*
* @since 2.0.0
*/
module org.slf4j.jdk.platform.logging {
requires org.slf4j;
exports org.slf4j.jdk.platform.logging;
provides java.lang.System.LoggerFinder with org.slf4j.jdk.platform.logging.SLF4JSystemLoggerFinder;
}
}

View File

@ -36,8 +36,7 @@ import org.slf4j.spi.CallerBoundaryAware;
import org.slf4j.spi.LoggingEventBuilder;
/**
* Implements {@link System.Logger} by forwarding logging events to the appropriate {@link org.slf4j.Logger} instance.
*
* Adapts {@link Logger} to {@link System.Logger}.
* @since 2.0.0
*/
class SLF4JPlatformLogger implements System.Logger {
@ -116,16 +115,11 @@ class SLF4JPlatformLogger implements System.Logger {
* @param thrown
* @param params
*/
private void log(Level jplLevel, ResourceBundle bundle, String msg, Throwable thrown, Object... params) {
if (jplLevel == Level.OFF)
return;
private void log(final Level jplLevel, final ResourceBundle bundle, final String msg, final Throwable thrown, final Object... params) {
if (jplLevel == Level.ALL) {
performLog(org.slf4j.event.Level.TRACE, bundle, msg, thrown, params);
return;
}
final Level jplLevelReduced = fixExtremeLevels(jplLevel);
org.slf4j.event.Level slf4jLevel = jplLevelToSLF4JLevel(jplLevel);
org.slf4j.event.Level slf4jLevel = jplLevelToSLF4JLevel(jplLevelReduced);
boolean isEnabled = slf4jLogger.isEnabledForLevel(slf4jLevel);
if (isEnabled) {
@ -133,6 +127,27 @@ class SLF4JPlatformLogger implements System.Logger {
}
}
/**
* <p>Level.OFF and Level.ALL levels are not supposed to be used when calling log printing methods.
* </p>
*
* <p>We compensate for such incorrect usage by transforming Level.OFF as Level.ERROR and
* Level.ALL as Level.TRACE.
* </p>
*
* @param jplLevel
* @return
*/
private Level fixExtremeLevels(Level jplLevel) {
if (jplLevel == Level.OFF)
return Level.ERROR;
if (jplLevel == Level.ALL)
return Level.TRACE;
return jplLevel;
}
private void performLog(org.slf4j.event.Level slf4jLevel, ResourceBundle bundle, String msg, Throwable thrown, Object... params) {
String message = getResourceStringOrMessage(bundle, msg);
LoggingEventBuilder leb = slf4jLogger.makeLoggingEventBuilder(slf4jLevel);

View File

@ -1,5 +0,0 @@
/**
* JDK platform logging
*
*/
package org.slf4j.jdk.platform.logging;

View File

@ -106,18 +106,30 @@ public class SLF4JPlatformLoggingTest {
systemLogger.log(Level.INFO, "we have a problem", new Exception());
List<String> results = SPS.stringList;
// SLF4J(I): Actual provider is of type [org.slf4j.simple.SimpleServiceProvider@67c27493]
// INFO throwTest - a problem
// java.lang.Exception
//INFO throwTest - a problem
//java.lang.Exception
// at org.slf4j.jdk.platform.logging/org.slf4j.jdk.platform.logging.SLF4JPlatformLoggingTest.throwTest(SLF4JPlatformLoggingTest.java:92)
String firstLine = results.get(0);
assertTrue(firstLine.startsWith("SLF4J(I): Connected with provider of type [org.slf4j.simple.SimpleServiceProvider"));
assertEquals("INFO throwTest - we have a problem", results.get(1));
assertEquals(Exception.class.getName(), results.get(2));
assertTrue(results.get(3).contains("at "));
assertTrue(results.get(3).contains(this.getClass().getName()));
int line = 0;
//assertTrue(results.get(0).startsWith("SLF4J(I): Connected with provider of type ["));
assertEquals("INFO throwTest - we have a problem", results.get(line++));
assertEquals(Exception.class.getName(), results.get(line++));
assertTrue(results.get(line).contains("at "));
assertTrue(results.get(line++).contains(this.getClass().getName()));
}
@Test
public void extremeLevels() throws IOException {
LoggerFinder finder = System.LoggerFinder.getLoggerFinder();
assertEquals(EXPECTED_FINDER_CLASS, finder.getClass().getName());
Logger systemLogger = finder.getLogger("extremeLevels", null);
systemLogger.log(Level.OFF, "hello");
systemLogger.log(Level.ALL, "world");
List<String> results = SPS.stringList;
assertEquals(1, results.size());
assertEquals("ERROR extremeLevels - hello", results.get(0));
}
}

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
@ -31,40 +31,11 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-testing</artifactId>
<artifactId>slf4j-api</artifactId>
<type>test-jar</type>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<executions>
<execution>
<id>module-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>${jdk9.version}</release>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/main/java9</compileSourceRoot>
</compileSourceRoots>
<multiReleaseOutput>true</multiReleaseOutput>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -55,6 +55,8 @@ public final class JDK14LoggerAdapter extends LegacyAbstractLogger implements Lo
transient final java.util.logging.Logger logger;
static int NOT_FOUND = -1;
// WARN: JDK14LoggerAdapter constructor should have only package access so
// that only JDK14LoggerFactory be able to create one.
JDK14LoggerAdapter(java.util.logging.Logger logger) {
@ -181,26 +183,10 @@ public final class JDK14LoggerAdapter extends LegacyAbstractLogger implements Lo
final private void fillCallerData(String callerFQCN, LogRecord record) {
StackTraceElement[] steArray = new Throwable().getStackTrace();
int selfIndex = -1;
for (int i = 0; i < steArray.length; i++) {
final String className = steArray[i].getClassName();
int furthestIndex = findFurthestIndex(callerFQCN, steArray);
if (barrierMatch(callerFQCN, className)) {
selfIndex = i;
break;
}
}
int found = -1;
for (int i = selfIndex + 1; i < steArray.length; i++) {
final String className = steArray[i].getClassName();
if (!(barrierMatch(callerFQCN, className))) {
found = i;
break;
}
}
if (found != -1) {
if (furthestIndex != NOT_FOUND) {
int found = furthestIndex+1;
StackTraceElement ste = steArray[found];
// setting the class name has the side effect of setting
// the needToInferCaller variable to false.
@ -209,7 +195,24 @@ public final class JDK14LoggerAdapter extends LegacyAbstractLogger implements Lo
}
}
static String SELF = JDK14LoggerAdapter.class.getName();
// find the furthest index which matches any of the barrier classes
// We assume that the actual caller is at most MAX_SEARCH_DEPTH calls away
private int findFurthestIndex(String callerFQCN, StackTraceElement[] steArray) {
final int maxIndex = Math.min(MAX_SEARCH_DEPTH, steArray.length);
int furthestIndex = NOT_FOUND;
for (int i = 0; i < maxIndex; i++) {
final String className = steArray[i].getClassName();
if (barrierMatch(callerFQCN, className)) {
furthestIndex = i;
}
}
return furthestIndex;
}
static final int MAX_SEARCH_DEPTH = 12;
static String SELF = JDK14LoggerAdapter.class.getName();
static String SUPER = LegacyAbstractLogger.class.getName();
static String SUPER_OF_SUPER = AbstractLogger.class.getName();

View File

@ -17,8 +17,16 @@ public class JULServiceProvider implements SLF4JServiceProvider {
public static String REQUESTED_API_VERSION = "2.0.99"; // !final
private ILoggerFactory loggerFactory;
private IMarkerFactory markerFactory;
private MDCAdapter mdcAdapter;
// LoggerFactory expects providers to initialize markerFactory as early as possible.
private final IMarkerFactory markerFactory;
// LoggerFactory expects providers to initialize their MDCAdapter field
// as early as possible, preferably at construction time.
private final MDCAdapter mdcAdapter;
public JULServiceProvider() {
markerFactory = new BasicMarkerFactory();
mdcAdapter = new BasicMDCAdapter();
}
@Override
public ILoggerFactory getLoggerFactory() {
@ -42,7 +50,5 @@ public class JULServiceProvider implements SLF4JServiceProvider {
@Override
public void initialize() {
loggerFactory = new JDK14LoggerFactory();
markerFactory = new BasicMarkerFactory();
mdcAdapter = new BasicMDCAdapter();
}
}

7
slf4j-jdk14/src/main/java9/module-info.java Normal file → Executable file
View File

@ -1,12 +1,9 @@
/**
* This module implements an SLF4J adapter for the java.logging package.
*/
module org.slf4j.jul {
module org.slf4j.jul {
requires org.slf4j;
requires java.logging;
provides org.slf4j.spi.SLF4JServiceProvider with org.slf4j.jul.JULServiceProvider;
opens org.slf4j.jul to org.slf4j;
exports org.slf4j.jul;
opens org.slf4j.jul to org.slf4j;
}

View File

@ -18,8 +18,9 @@ import org.slf4j.event.EventConstants;
import org.slf4j.event.SubstituteLoggingEvent;
import org.slf4j.helpers.SubstituteLogger;
import org.slf4j.helpers.SubstituteServiceProvider;
import org.slf4j.jul.JDK14LoggerAdapter;
import org.slf4j.jul.ListHandler;
import org.slf4j.spi.CallerBoundaryAware;
import org.slf4j.spi.LoggingEventBuilder;
public class CallerInfoTest {
Level oldLevel;
@ -78,6 +79,22 @@ public class CallerInfoTest {
assertEquals(this.getClass().getName(), logRecod.getSourceClassName());
}
@Test
public void testCallerInfoWithFluentAPIAndAWrapper() {
Logger logger = LoggerFactory.getLogger("bla");
LoggingWrapper wrappedLogger = new LoggingWrapper(logger);
wrappedLogger.logWithEvent("hello");
List<LogRecord> recordList = listHandler.recordList;
assertEquals(1, recordList.size());
LogRecord logRecod = recordList.get(0);
assertEquals(this.getClass().getName(), logRecod.getSourceClassName());
}
@Test
public void testPostInitializationCallerInfoWithSubstituteLogger() {
Logger logger = LoggerFactory.getLogger("bla");
@ -104,7 +121,6 @@ public class CallerInfoTest {
substituteLogger.debug("jello");
Logger logger = LoggerFactory.getLogger(loggerName);
assertTrue(logger instanceof JDK14LoggerAdapter);
substituteLogger.setDelegate(logger);
final LinkedBlockingQueue<SubstituteLoggingEvent> queue = substituteServiceProvider.getSubstituteLoggerFactory().getEventQueue();
@ -121,4 +137,22 @@ public class CallerInfoTest {
assertEquals(EventConstants.NA_SUBST, logRecod.getSourceClassName());
}
static class LoggingWrapper {
Logger underlyingLogger;
LoggingWrapper(Logger aLogger) {
this.underlyingLogger = aLogger;
}
public void logWithEvent(String msg) {
LoggingEventBuilder lev = underlyingLogger.atInfo();
// setting the caller boundary to LoggingWrapper
if(lev instanceof CallerBoundaryAware) {
// builder is CallerBoundaryAware
((CallerBoundaryAware) lev).setCallerBoundary(LoggingWrapper.class.getName());
}
lev.log(msg);
}
}
}

View File

@ -30,7 +30,7 @@ import java.util.logging.Handler;
import org.junit.After;
import org.junit.Before;
import org.slf4j.testing.MultithreadedInitializationTest;
import org.slf4j.testHarness.MultithreadedInitializationTest;
public class JDK14MultithreadedInitializationTest extends MultithreadedInitializationTest {

View File

@ -8,7 +8,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
@ -24,7 +24,7 @@
<relocation>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.18</version>
</relocation>
</distributionManagement>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>

View File

@ -1,3 +0,0 @@
module slf4j.migrator {
requires java.desktop;
}

View File

@ -7,7 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.1.0-alpha1</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
@ -32,36 +32,11 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-testing</artifactId>
<artifactId>slf4j-api</artifactId>
<type>test-jar</type>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<executions>
<execution>
<id>module-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>${jdk9.version}</release>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/main/java9</compileSourceRoot>
</compileSourceRoots>
<multiReleaseOutput>true</multiReleaseOutput>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -8,11 +8,6 @@ import org.slf4j.helpers.NOPMDCAdapter;
import org.slf4j.spi.MDCAdapter;
import org.slf4j.spi.SLF4JServiceProvider;
/**
* As the name indicates, this {#link SLF4JServiceProvider} implementation git sdiscards all events.
*
* @author Ceki G&uuml;lc&uuml;
*/
public class NOPServiceProvider implements SLF4JServiceProvider {
/**
@ -23,9 +18,18 @@ public class NOPServiceProvider implements SLF4JServiceProvider {
public static String REQUESTED_API_VERSION = "2.0.99"; // !final
private final ILoggerFactory loggerFactory = new NOPLoggerFactory();
private final IMarkerFactory markerFactory = new BasicMarkerFactory();
private final MDCAdapter mdcAdapter = new NOPMDCAdapter();
// LoggerFactory expects providers to initialize markerFactory as early as possible.
private final IMarkerFactory markerFactory;
// LoggerFactory expects providers to initialize their MDCAdapter field
// as early as possible, preferably at construction time.
private final MDCAdapter mdcAdapter;
public NOPServiceProvider() {
markerFactory = new BasicMarkerFactory();
mdcAdapter = new NOPMDCAdapter();
}
public ILoggerFactory getLoggerFactory() {
return loggerFactory;
}
@ -44,7 +48,6 @@ public class NOPServiceProvider implements SLF4JServiceProvider {
}
public void initialize() {
}

Some files were not shown because too many files have changed in this diff Show More