Compare commits

..

No commits in common. "master" and "v_2.0.0-alpha4" have entirely different histories.

289 changed files with 11159 additions and 3862 deletions

2
.github/FUNDING.yml vendored
View File

@ -1,2 +0,0 @@
tidelift: maven/org.slf4j:slf4j-api
github: qos-ch

View File

@ -1,47 +0,0 @@
name: CI
on:
push:
branches:
- '*'
pull_request:
branches:
- '*'
# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/software-installed-on-github-hosted-runners
concurrency:
# On master/release, we don't want any jobs cancelled so the sha is used to name the group
# On PR branches, we cancel the job if new commits are pushed
# More info: https://stackoverflow.com/a/68422069/253468
group: ${{ (github.ref == 'refs/heads/branch_1.2.18' || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/release' ) && format('ci-main-{0}', github.sha) || format('ci-main-{0}', github.ref) }}
cancel-in-progress: true
permissions:
contents: read
jobs:
Test:
name: JDK ${{ matrix.jdk }}, ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
jdk: [11, 17, 19]
os: [ubuntu-latest, windows-latest, macos-latest]
fail-fast: true
max-parallel: 4
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 50
- name: Set up Java ${{ matrix.jdk }}
if: ${{ matrix.jdk != '8' }}
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: ${{ matrix.jdk }}
- name: Install
# download dependencies, etc, so test log looks better
run: mvn -B install

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF8"?>
<toolchains>
<toolchain>
<type>jdk</type>
<provides>
<version>1.8</version>
</provides>
<configuration>
<jdkHome>${env.JAVA_HOME_8}</jdkHome>
</configuration>
</toolchain>
</toolchains>

View File

@ -13,9 +13,4 @@ install: /bin/true
script:
- mvn clean
- mvn install
cache:
directories:
- $HOME/.m2
- mvn install

View File

@ -1 +0,0 @@
github: qos-ch

View File

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

View File

@ -1,40 +1,16 @@
# About SLF4J
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, logevents, penna, rainbowgum, tinylog)
allowing the end user to plug in the desired logging framework at
deployment time.
The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks (e.g. java.util.logging, logback, log4j) 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://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](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.
# How to build SLF4J
SLF4J uses Maven as its build tool.
SLF4J version 2.0.x will run under Java 8 but requires Java 9 or later to build.
All versions upto and including 1.7.x require Java 5 or later to
build. SLF4J version 2.0.x requires Java 9 or later.
# How to contribute pull requests
@ -45,25 +21,28 @@ 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](https://github.com/qos-ch/slf4j/issues) on github to initiate the
discussion.
report](http://www.slf4j.org/bug-reporting.html) to initiatite the
discussion. Note that we ask pull requests to be linked to a [Jira
ticket](https://jira.qos.ch/).
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 created in Step 2. Be
3. Make your changes on the branch you hopefuly 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.
4. All commits must have signed off by the contributor attesting to
[Developer Certificate of Origin
(DCO)](https://developercertificate.org/). Commits without sign off
will be automatically rejected by the [DCO GitHub
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
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
later.
6. Submit a pull request to SLF4J from your commit page on GitHub.
6. Submit a pull request to SLF4J from 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

@ -1,69 +0,0 @@
## Reporting security issues
Please report security issues related to the SLF4J project to the
following email address:
support(at)qos.ch
## Verifying contents
All SLF4J project artifacts published on Maven central are signed. For
each artifact, there is an associated signature file with the .asc
suffix.
### After 2022-08-08
To verify the signature use [this public key](https://www.slf4j.org/public-keys/60200AC4AE761F1614D6C46766D68DAA073BE985.gpg). Here is its fingerprint:
```
pub nistp521 2022-08-08 [SC]
60200AC4AE761F1614D6C46766D68DAA073BE985
uid Ceki Gulcu <ceki@qos.ch>
sub nistp521 2022-08-08 [E]
```
A copy of this key is stored on the
[keys.openpgp.org](https://keys.openpgp.org) keyserver. To add it to
your public key ring use the following command:
```
> FINGER_PRINT=60200AC4AE761F1614D6C46766D68DAA073BE985
> gpg --keyserver hkps://keys.openpgp.org --recv-keys $FINGER_PRINT
```
### Before 2022-08-08
To verify the signature use [this public key](https://www.slf4j.org/public-keys/ceki-public-key.pgp). Here is its fingerprint:
```
pub 2048R/A511E325 2012-04-26
Key fingerprint = 475F 3B8E 59E6 E63A A780 6748 2C7B 12F2 A511 E325
uid Ceki Gulcu <ceki@qos.ch>
sub 2048R/7FBFA159 2012-04-26
```
A copy of this key is stored on the
[keys.openpgp.org](https://keys.openpgp.org) keyserver. To add it to
your public key ring use the following command:
```
> FINGER_PRINT=475F3B8E59E6E63AA78067482C7B12F2A511E325
> gpg --keyserver hkps://keys.openpgp.org --recv-keys $FINGER_PRINT
```
## Preventing commit history overwrite
In order to prevent loss of commit history, developers of the project
are highly encouraged to deny branch deletions or history overwrites
by invoking the following two commands on their local copy of the
repository.
```
git config receive.denyDelete true
git config receive.denyNonFastForwards true
```

View File

@ -82,12 +82,12 @@
</target>
<target name="testAll" depends="init,
testNoProvider150,
testNoProvider150,
testMismatch,
testMatch,
testMultiBinding,
testFuture_16Series"
>
testMultiBinding,
testFuture_16Series,
testActiveSecurityManager">
</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

@ -66,7 +66,7 @@
<!-- for some reason if mvn is invoked from the parent directory, junit gets
invoked from the parent dir, which messes up these tests. Hence, the
invoked from the parent dir, which messes up theses tests. Hence, the
fork="yes" dir="${basedir}" -->
<!--
@ -107,4 +107,4 @@
</junit>
</target>
</project>
</project>

View File

@ -7,8 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
<version>2.0.0-alpha4</version>
</parent>
<artifactId>integration</artifactId>

View File

@ -27,7 +27,6 @@ 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;
@ -44,13 +43,11 @@ 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);
}
@ -59,13 +56,9 @@ public class CompatibilityAssertionTest {
Logger logger = LoggerFactory.getLogger(this.getClass());
String msg = "hello world " + diff;
logger.info(msg);
assertEquals(2, sps.stringList.size());
assertEquals(1, sps.stringList.size());
String s0 = (String) sps.stringList.get(0);
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));
assertTrue(s0.contains(msg));
}
}

View File

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

View File

@ -28,12 +28,12 @@ public class OutputVerifier {
}
{
String s = (String) sps.stringList.get(2);
assertTrue(s.contains("See https://www.slf4j.org/codes.html#noProviders for further details."));
assertTrue(s.contains("SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details."));
}
{
String s = (String) sps.stringList.get(3);
assertTrue(s.contains("Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier."));
assertTrue(s.contains("SLF4J: Class path contains SLF4J bindings targeting slf4j-api versions prior to 1.8."));
}
{
@ -42,7 +42,7 @@ public class OutputVerifier {
}
{
String s = (String) sps.stringList.get(5);
assertTrue(s.contains("See https://www.slf4j.org/codes.html#ignoredBindings for an explanation"));
assertTrue(s.contains("See http://www.slf4j.org/codes.html#ignoredBindings for an explanation"));
}
}

View File

@ -32,7 +32,7 @@ public class StringPrintStream extends PrintStream {
public static final String LINE_SEP = System.getProperty("line.separator");
PrintStream other;
List<String> stringList = new ArrayList<>();
List<String> stringList = new ArrayList<String>();
public StringPrintStream(PrintStream ps) {
super(ps);

View File

@ -7,7 +7,7 @@ import junit.framework.TestCase;
public class Issue324Test extends TestCase {
public void testLoggerCreationInPresenceOfSecurityManager() {
public void testLoggerCreationInPresenseOfSecurityManager() {
String currentDir = System.getProperty("user.dir");
System.out.println("currentDir:" + currentDir);
Logger logger = LoggerFactory.getLogger(Issue324Test.class);

View File

@ -33,7 +33,7 @@ import org.osgi.framework.BundleListener;
public class CheckingBundleListener implements BundleListener {
List<BundleEvent> eventList = new ArrayList<>();
List<BundleEvent> eventList = new ArrayList<BundleEvent>();
public void bundleChanged(BundleEvent be) {
eventList.add(be);
@ -45,14 +45,16 @@ public class CheckingBundleListener implements BundleListener {
}
public void dumpAll() {
for (BundleEvent fe : eventList) {
for (int i = 0; i < eventList.size(); i++) {
BundleEvent fe = (BundleEvent) eventList.get(i);
dump(fe);
}
}
boolean exists(String bundleName) {
for (BundleEvent bundleEvent : eventList) {
Bundle b = bundleEvent.getBundle();
for (int i = 0; i < eventList.size(); i++) {
BundleEvent fe = (BundleEvent) eventList.get(i);
Bundle b = fe.getBundle();
System.out.println("===[" + b + "]");
if (bundleName.equals(b.getSymbolicName())) {
return true;

View File

@ -75,7 +75,7 @@ public class FelixHost {
try {
// Create host activator;
List<Object> list = new ArrayList<>();
List<Object> list = new ArrayList<Object>();
// list.add(new HostActivator());
configMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "org.xml.sax, org.xml.sax.helpers, javax.xml.parsers, javax.naming");

View File

@ -32,9 +32,8 @@ import org.osgi.framework.FrameworkListener;
public class FrameworkErrorListener implements FrameworkListener {
public List<FrameworkEvent> errorList = new ArrayList<>();
public List<FrameworkEvent> errorList = new ArrayList<FrameworkEvent>();
@Override
public void frameworkEvent(FrameworkEvent fe) {
if (fe.getType() == FrameworkEvent.ERROR) {
errorList.add(fe);
@ -55,8 +54,9 @@ public class FrameworkErrorListener implements FrameworkListener {
}
public void dumpAll() {
for (FrameworkEvent frameworkEvent : errorList) {
dump(frameworkEvent);
for (int i = 0; i < errorList.size(); i++) {
FrameworkEvent fe = (FrameworkEvent) errorList.get(i);
dump(fe);
}
}
}

View File

@ -5,8 +5,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
<version>2.0.0-alpha4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -19,7 +18,7 @@
<licenses>
<license>
<name>Apache-2.0</name>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
@ -28,7 +27,7 @@
<properties>
<module-name>org.apache.commons.logging</module-name>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
@ -40,19 +39,5 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<_exportcontents>org.apache.commons.logging*;version=${jcl.version};-noimport:=true</_exportcontents>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -43,7 +43,7 @@ public class SLF4JLocationAwareLog implements Log, Serializable {
// in both Log4jLogger and Jdk14Logger classes in the original JCL, the
// logger instance is transient
private final transient LocationAwareLogger logger;
private transient LocationAwareLogger logger;
private static final String FQCN = SLF4JLocationAwareLog.class.getName();

View File

@ -42,7 +42,7 @@ public class SLF4JLog implements Log, Serializable {
// in both Log4jLogger and Jdk14Logger classes in the original JCL, the
// logger instance is transient
private final transient Logger logger;
private transient Logger logger;
public SLF4JLog(Logger logger) {
this.logger = logger;

View File

@ -64,7 +64,7 @@ public class SLF4JLogFactory extends LogFactory {
* Public no-arguments constructor required by the lookup mechanism.
*/
public SLF4JLogFactory() {
loggerMap = new ConcurrentHashMap<>();
loggerMap = new ConcurrentHashMap<String, Log>();
}
// ----------------------------------------------------- Manifest Constants
@ -105,12 +105,12 @@ public class SLF4JLogFactory extends LogFactory {
@SuppressWarnings("unchecked")
public String[] getAttributeNames() {
List<String> names = new ArrayList<>();
List<String> names = new ArrayList<String>();
Enumeration<String> keys = attributes.keys();
while (keys.hasMoreElements()) {
names.add((String) keys.nextElement());
}
String[] results = new String[names.size()];
String results[] = new String[names.size()];
for (int i = 0; i < results.length; i++) {
results[i] = (String) names.get(i);
}
@ -173,10 +173,12 @@ public class SLF4JLogFactory extends LogFactory {
public void release() {
// This method is never called by jcl-over-slf4j classes. However,
// in certain deployment scenarios, in particular if jcl-over-slf4j.jar
// is in the web-app class loader and the official commons-logging.jar
// is deployed in some parent class loader (e.g. commons/lib), then it
// is possible for the parent class loader to mask the classes shipping
// in jcl-over-slf4j.jar.
// is
// in the the web-app class loader and the official commons-logging.jar is
// deployed in some parent class loader (e.g. commons/lib), then it is
// possible
// for the parent class loader to mask the classes shipping in
// jcl-over-slf4j.jar.
System.out.println("WARN: The method " + SLF4JLogFactory.class + "#release() was invoked.");
System.out.println("WARN: Please see http://www.slf4j.org/codes.html#release for an explanation.");
System.out.flush();
@ -214,4 +216,4 @@ public class SLF4JLogFactory extends LogFactory {
}
}
}
}

View File

@ -673,13 +673,15 @@ public class SimpleLog implements Log, Serializable {
}
private static InputStream getResourceAsStream(final String name) {
return AccessController.doPrivileged((PrivilegedAction<InputStream>) () -> {
ClassLoader threadCL = getContextClassLoader();
return AccessController.doPrivileged(new PrivilegedAction<InputStream>() {
public InputStream run() {
ClassLoader threadCL = getContextClassLoader();
if (threadCL != null) {
return threadCL.getResourceAsStream(name);
} else {
return ClassLoader.getSystemResourceAsStream(name);
if (threadCL != null) {
return threadCL.getResourceAsStream(name);
} else {
return ClassLoader.getSystemResourceAsStream(name);
}
}
});
}

View File

@ -31,7 +31,7 @@ replacement for the original JCL version 1.0.4.
<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,
covers. As as such, all the logging systems that SLF4J supports,
e.g. NOP, Simple, JDK14, nlog4j are supported by this version of JCL.
</p>

View File

@ -0,0 +1,9 @@
Implementation-Title: jcl-over-slf4j
Bundle-ManifestVersion: 2
Bundle-SymbolicName: jcl.over.slf4j
Bundle-Name: jcl-over-slf4j
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.apache.commons.logging;version=1.2,
org.apache.commons.logging.impl;version=1.2
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion}, org.slf4j.spi;version=${parsedVersion.osgiVersion}

View File

@ -1,24 +0,0 @@
Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland)
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -7,8 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
<version>2.0.0-alpha4</version>
</parent>
<artifactId>jul-to-slf4j</artifactId>
@ -26,15 +25,10 @@
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
<artifactId>slf4j-log4j12</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
</plugins>
</build>
</project>
</project>

View File

@ -79,12 +79,12 @@ import org.slf4j.spi.LocationAwareLogger;
* SLF4J translation can seriously increase the cost of disabled logging
* statements (60 fold or 6000% increase) and measurably impact the performance of enabled log
* statements (20% overall increase).</b> Please note that as of logback-version 0.9.25,
* it is possible to completely eliminate the 60-fold translation overhead for disabled
* it is possible to completely eliminate the 60 fold translation overhead for disabled
* log statements with the help of <a href="http://logback.qos.ch/manual/configuration.html#LevelChangePropagator">LevelChangePropagator</a>.
*
*
* <p>If you are concerned about application performance, then use of <code>SLF4JBridgeHandler</code>
* is appropriate only if any of the following conditions is true:
* is appropriate only if any one the following two conditions is true:
* <ol>
* <li>few j.u.l. logging statements are in play</li>
* <li>LevelChangePropagator has been installed</li>
@ -93,7 +93,7 @@ import org.slf4j.spi.LocationAwareLogger;
* <h2>As a Java 9/Jigsaw module</h2>
*
* <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
* the MAFIFEST.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).
@ -143,9 +143,9 @@ public class SLF4JBridgeHandler extends Handler {
public static void uninstall() throws SecurityException {
java.util.logging.Logger rootLogger = getRootLogger();
Handler[] handlers = rootLogger.getHandlers();
for (Handler handler : handlers) {
if (handler instanceof SLF4JBridgeHandler) {
rootLogger.removeHandler(handler);
for (int i = 0; i < handlers.length; i++) {
if (handlers[i] instanceof SLF4JBridgeHandler) {
rootLogger.removeHandler(handlers[i]);
}
}
}
@ -153,14 +153,14 @@ public class SLF4JBridgeHandler extends Handler {
/**
* Returns true if SLF4JBridgeHandler has been previously installed, returns false otherwise.
*
* @return true if SLF4JBridgeHandler is already installed, false otherwise
* @return true if SLF4JBridgeHandler is already installed, false other wise
*
*/
public static boolean isInstalled() {
java.util.logging.Logger rootLogger = getRootLogger();
Handler[] handlers = rootLogger.getHandlers();
for (Handler handler : handlers) {
if (handler instanceof SLF4JBridgeHandler) {
for (int i = 0; i < handlers.length; i++) {
if (handlers[i] instanceof SLF4JBridgeHandler) {
return true;
}
}
@ -174,8 +174,8 @@ public class SLF4JBridgeHandler extends Handler {
public static void removeHandlersForRootLogger() {
java.util.logging.Logger rootLogger = getRootLogger();
java.util.logging.Handler[] handlers = rootLogger.getHandlers();
for (Handler handler : handlers) {
rootLogger.removeHandler(handler);
for (int i = 0; i < handlers.length; i++) {
rootLogger.removeHandler(handlers[i]);
}
}

View File

@ -1,7 +0,0 @@
module jul.to.slf4j {
requires org.slf4j;
requires java.logging;
exports org.slf4j.bridge;
}

View File

@ -0,0 +1,8 @@
Bundle-ManifestVersion: 2
Bundle-SymbolicName: jul.to.slf4j
Bundle-Name: jul-to-slf4j
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.slf4j.bridge;version=${parsedVersion.osgiVersion};uses:="org.slf4j,org.slf4j.spi"
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion},org.slf4j.spi;version=${parsedVersion.osgiVersion}
Automatic-Module-Name: jul.to.slf4j

View File

@ -32,7 +32,7 @@ import org.apache.log4j.spi.LoggingEvent;
public class ListAppender extends AppenderSkeleton {
public List<LoggingEvent> list = new ArrayList<>();
public List<LoggingEvent> list = new ArrayList<LoggingEvent>();
public boolean extractLocationInfo = false;

View File

@ -56,8 +56,8 @@ public class SLF4JBridgeHandlerPerfTest {
fileAppender = new FileAppender(new PatternLayout("%r [%t] %p %c %x - %m%n"), "target/test-output/toto.log");
existingHandlers = julRootLogger.getHandlers();
for (Handler existingHandler : existingHandlers) {
julRootLogger.removeHandler(existingHandler);
for (int i = 0; i < existingHandlers.length; i++) {
julRootLogger.removeHandler(existingHandlers[i]);
}
log4jRoot = org.apache.log4j.Logger.getRootLogger();
log4jRoot.addAppender(fileAppender);
@ -68,8 +68,8 @@ public class SLF4JBridgeHandlerPerfTest {
SLF4JBridgeHandler.uninstall();
fileAppender.close();
log4jRoot.getLoggerRepository().resetConfiguration();
for (Handler existingHandler : existingHandlers) {
julRootLogger.addHandler(existingHandler);
for (int i = 0; i < existingHandlers.length; i++) {
julRootLogger.addHandler(existingHandlers[i]);
}
}

View File

@ -42,16 +42,14 @@ public class SLF4JBridgeHandlerTest {
ListAppender listAppender = new ListAppender();
org.apache.log4j.Logger log4jRoot;
java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger(LOGGER_NAME);
java.util.logging.Logger julRootLogger = java.util.logging.Logger.getLogger("");
java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger("yay");
@Before
public void setUp() throws Exception {
listAppender.extractLocationInfo = true;
log4jRoot = org.apache.log4j.Logger.getRootLogger();
log4jRoot.addAppender(listAppender);
log4jRoot.setLevel(org.apache.log4j.Level.TRACE);
julRootLogger.setLevel(Level.FINEST);
}
@After
@ -63,7 +61,6 @@ public class SLF4JBridgeHandlerTest {
@Test
public void testSmoke() {
SLF4JBridgeHandler.install();
String msg = "msg";
julLogger.info(msg);
assertEquals(1, listAppender.list.size());
@ -80,19 +77,6 @@ public class SLF4JBridgeHandlerTest {
assertEquals("SLF4JBridgeHandlerTest.java", li.getFileName());
assertEquals("testSmoke", li.getMethodName());
}
@Test
public void LOGBACK_1612() {
SLF4JBridgeHandler.install();
String msg = "LOGBACK_1612";
julLogger.finer(msg);
assertEquals(1, listAppender.list.size());
LoggingEvent le = (LoggingEvent) listAppender.list.get(0);
assertEquals(LOGGER_NAME, le.getLoggerName());
assertEquals(msg, le.getMessage());
}
@Test
public void testLevels() {
@ -117,8 +101,6 @@ public class SLF4JBridgeHandlerTest {
assertLevel(i++, org.apache.log4j.Level.ERROR);
}
@Test
public void testLogWithResourceBundle() {
SLF4JBridgeHandler.install();
@ -133,7 +115,7 @@ public class SLF4JBridgeHandlerTest {
julResourceBundleLogger.info(msg);
assertEquals(1, listAppender.list.size());
LoggingEvent le = listAppender.list.get(0);
LoggingEvent le = (LoggingEvent) listAppender.list.get(0);
assertEquals(LOGGER_NAME, le.getLoggerName());
assertEquals(expectedMsg, le.getMessage());
}
@ -167,19 +149,19 @@ public class SLF4JBridgeHandlerTest {
LoggingEvent le = null;
le = listAppender.list.get(0);
le = (LoggingEvent) listAppender.list.get(0);
assertEquals("foo", le.getLoggerName());
assertEquals(expectedMsg1, le.getMessage());
le = listAppender.list.get(1);
le = (LoggingEvent) listAppender.list.get(1);
assertEquals("foo", le.getLoggerName());
assertEquals(expectedMsg2, le.getMessage());
le = listAppender.list.get(2);
le = (LoggingEvent) listAppender.list.get(2);
assertEquals("foo", le.getLoggerName());
assertEquals(expectedMsg3, le.getMessage());
le = listAppender.list.get(3);
le = (LoggingEvent) listAppender.list.get(3);
assertEquals("yay", le.getLoggerName());
assertEquals(expectedMsg3, le.getMessage());
}
@ -191,7 +173,7 @@ public class SLF4JBridgeHandlerTest {
julLogger.logp(Level.INFO, "SLF4JBridgeHandlerTest", "testLogWithPlaceholderNoParameters", msg, new Object[0]);
assertEquals(1, listAppender.list.size());
LoggingEvent le = listAppender.list.get(0);
LoggingEvent le = (LoggingEvent) listAppender.list.get(0);
assertEquals(LOGGER_NAME, le.getLoggerName());
assertEquals(msg, le.getMessage());
}
@ -205,7 +187,7 @@ public class SLF4JBridgeHandlerTest {
julLogger.log(Level.INFO, msg, "ignored parameter due to IllegalArgumentException");
assertEquals(1, listAppender.list.size());
LoggingEvent le = listAppender.list.get(0);
LoggingEvent le = (LoggingEvent) listAppender.list.get(0);
assertEquals(msg, le.getMessage());
}
@ -215,12 +197,12 @@ public class SLF4JBridgeHandlerTest {
String msg = null;
julLogger.log(Level.INFO, msg);
assertEquals(1, listAppender.list.size());
LoggingEvent le = listAppender.list.get(0);
LoggingEvent le = (LoggingEvent) listAppender.list.get(0);
assertEquals("", le.getMessage());
}
void assertLevel(int index, org.apache.log4j.Level expectedLevel) {
LoggingEvent le = listAppender.list.get(index);
LoggingEvent le = (LoggingEvent) listAppender.list.get(index);
assertEquals(expectedLevel, le.getLevel());
}
}

View File

@ -1,176 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -0,0 +1,137 @@
<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 scpript:
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>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,17 @@
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 runs 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

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

View File

@ -0,0 +1,39 @@
/**
* 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

@ -0,0 +1,46 @@
/**
* 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

@ -0,0 +1,169 @@
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,8 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
<version>2.0.0-alpha4</version>
</parent>
@ -21,8 +20,8 @@
<licenses>
<license>
<name>Apache-2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
<name>Apache Software Licenses</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
@ -42,20 +41,4 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<_exportcontents>org.apache.log4j*;version=${reload4j.version};-noimport:=true</_exportcontents>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -114,7 +114,7 @@ public interface Appender {
* Configurators call this method to determine if the appender
* requires a layout. If this method returns <code>true</code>,
* meaning that layout is required, then the configurator will
* configure a layout using the configuration information at its
* configure an layout using the configuration information at its
* disposal. If this method returns <code>false</code>, meaning that
* a layout is not required, then layout configuration will be
* skipped even if there is available layout configuration

View File

@ -45,12 +45,12 @@ public class Category {
private static final String CATEGORY_FQCN = Category.class.getName();
private final String name;
private String name;
protected org.slf4j.Logger slf4jLogger;
private org.slf4j.spi.LocationAwareLogger locationAwareLogger;
private static final Marker FATAL_MARKER = MarkerFactory.getMarker("FATAL");
private static Marker FATAL_MARKER = MarkerFactory.getMarker("FATAL");
Category(String name) {
this.name = name;

View File

@ -33,7 +33,7 @@ import java.util.concurrent.ConcurrentMap;
class Log4jLoggerFactory {
// String, Logger
private static final ConcurrentMap<String, Logger> log4jLoggers = new ConcurrentHashMap<>();
private static ConcurrentMap<String, Logger> log4jLoggers = new ConcurrentHashMap<String, Logger>();
public static Logger getLogger(String name) {
org.apache.log4j.Logger instance = log4jLoggers.get(name);

View File

@ -187,7 +187,7 @@ public class Priority {
*
* @param val an integer value
* @param defaultPriority a default priority value
* @return corresponding Priority value
* @return correspoding Priority value
*/
@Deprecated
public static Priority toPriority(int val, Priority defaultPriority) {
@ -204,4 +204,4 @@ public class Priority {
public static Priority toPriority(String sArg, Priority defaultPriority) {
return Level.toLevel(sArg, (Level) defaultPriority);
}
}
}

View File

@ -23,7 +23,7 @@ import org.apache.log4j.spi.Configurator;
import org.apache.log4j.spi.LoggerRepository;
/**
* A no-op implementation of PropertyConfigurator.
* An nop implementation of PropertyConfigurator.
*/
public class PropertyConfigurator implements Configurator {
public static void configure(Properties properties) {

View File

@ -25,7 +25,7 @@ package org.apache.log4j.helpers;
<b>log4j.configDebug</b> variable.
<p>All log4j internal debug calls go to <code>System.out</code>
whereas internal error messages are sent to
where as internal error messages are sent to
<code>System.err</code>. All internal messages are prepended with
the string "log4j: ".
@ -40,7 +40,7 @@ public class LogLog {
<p> The value of this string is <b>log4j.debug</b>.
<p>Note that the search for all option names is case-sensitive. */
<p>Note that the search for all option names is case sensitive. */
public static final String DEBUG_KEY = "log4j.debug";
/**
@ -49,7 +49,7 @@ public class LogLog {
<p> The value of this string is <b>log4j.configDebug</b>.
<p>Note that the search for all option names is case-sensitive.
<p>Note that the search for all option names is case sensitive.
@deprecated Use {@link #DEBUG_KEY} instead.
*/

View File

@ -21,7 +21,7 @@ import org.apache.log4j.Logger;
/**
Implement this interface to create new instances of Logger or
a subclass of Logger.
a sub-class of Logger.
<p>See <code>examples/subclass/MyLogger.java</code> for an example.

View File

@ -0,0 +1,13 @@
Implementation-Title: log4j-over-slf4j
Bundle-ManifestVersion: 2
Bundle-SymbolicName: log4j.over.slf4j
Bundle-Name: log4j-over-slf4j
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.apache.log4j;version=${log4j.version},
org.apache.log4j.helpers;version=${log4j.version},
org.apache.log4j.spi;version=${log4j.version},
org.apache.log4j.xml;version=${log4j.version}
Import-Package: org.slf4j;version=${slf4j.api.minimum.compatible.version},
org.slf4j.helpers;version=${slf4j.api.minimum.compatible.version},
org.slf4j.spi;version=${slf4j.api.minimum.compatible.version}

View File

@ -31,7 +31,7 @@ import java.util.logging.LogRecord;
public class ListHandler extends Handler {
List<LogRecord> list = new ArrayList<>();
List<LogRecord> list = new ArrayList<LogRecord>();
public void close() throws SecurityException {

View File

@ -1,24 +0,0 @@
Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland)
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -7,8 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
<version>2.0.0-alpha4</version>
</parent>
<artifactId>osgi-over-slf4j</artifactId>
@ -38,27 +37,8 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<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" />
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,8 @@
Implementation-Title: osgi-over-slf4j
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.slf4j.osgi-over-slf4j
Bundle-Name: OSGi LogService implemented over SLF4J
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-Activator: org.slf4j.osgi.logservice.impl.Activator
Bundle-Category: osgi
Import-Package: org.osgi.framework;version="[1.5,2)",org.osgi.service.log;version="[1.3,2)",org.slf4j;version=${parsedVersion.osgiVersion}

View File

@ -1,397 +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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-bom</artifactId>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>slf4j-parent</artifactId>
<packaging>pom</packaging>
<name>SLF4J Parent POM</name>
<description>SLF4J project parent pom.xml file</description>
<organization>
<name>QOS.ch</name>
<url>http://www.qos.ch</url>
</organization>
<inceptionYear>2005</inceptionYear>
<properties>
<!-- yyyy-MM-dd'T'HH:mm:ss'Z' -->
<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>
<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.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.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.1.1</maven-jxr-plugin.version>
<maven-bundle-plugin.version>5.1.9</maven-bundle-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
<version>${reload4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.cal10n</groupId>
<artifactId>cal10n-api</artifactId>
<version>${cal10n.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.10</version>
</extension>
</extensions>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>..</directory>
<targetPath>META-INF</targetPath>
<includes>
<include>LICENSE.txt</include>
</includes>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.14</version>
<configuration>
<signature>
<groupId>org.codehaus.mojo.signature</groupId>
<artifactId>java16</artifactId>
<version>1.0</version>
</signature>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>${maven-deploy-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<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>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</execution>
<execution>
<id>module-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>9</release>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/main/java9</compileSourceRoot>
</compileSourceRoots>
<multiReleaseOutput>true</multiReleaseOutput>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<executions>
<!-- Repeated in slf4j-api/pom.xml -->
<execution>
<id>default-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
<skipIfEmpty>true</skipIfEmpty>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${maven-bundle-plugin.version}</version>
<configuration>
<supportIncrementalBuild>true</supportIncrementalBuild>
<!-- populated by the plugin itself -->
<instructions>
<Bundle-SymbolicName>${replacestring;${project.artifactId};-;.}</Bundle-SymbolicName>
<Bundle-Vendor>SLF4J.ORG</Bundle-Vendor>
<_snapshot/>
<_exportcontents>!META-INF.versions.9,*;-noimport:=true</_exportcontents>
<Bundle-Description>${project.description}</Bundle-Description>
<Bundle-DocURL>${project.url}</Bundle-DocURL>
<X-Compile-Source-JDK>${maven.compiler.source}</X-Compile-Source-JDK>
<X-Compile-Target-JDK>${maven.compiler.target}</X-Compile-Target-JDK>
<Implementation-Version>${project.version}</Implementation-Version>
<Implementation-Title>${project.artifactId}</Implementation-Title>
<Multi-Release>true</Multi-Release>
<_removeheaders>Private-Package,Bundle-SCM, Bundle-Developers, Include-Resource</_removeheaders>
</instructions>
</configuration>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
<reportFormat>plain</reportFormat>
<trimStackTrace>false</trimStackTrace>
<excludes>
<exclude>**/AllTest.java</exclude>
<exclude>**/PackageTest.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven-source-plugin.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-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>
<profiles>
<profile>
<id>skipTests</id>
<properties>
<maven.test.skip>true</maven.test.skip>
</properties>
</profile>
<profile>
<id>javadocjar</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
<failOnError>false</failOnError>
<sourceFileExcludes>
<sourceFileExclude>**/module-info.java</sourceFileExclude>
</sourceFileExcludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>license</id>
<build>
<plugins>
<plugin>
<groupId>com.google.code.maven-license-plugin</groupId>
<artifactId>maven-license-plugin</artifactId>
<configuration>
<header>src/main/licenseHeader.txt</header>
<quiet>false</quiet>
<failIfMissing>true</failIfMissing>
<aggregate>true</aggregate>
<includes>
<include>src/**/*.java</include>
</includes>
<useDefaultExcludes>true</useDefaultExcludes>
<useDefaultMapping>true</useDefaultMapping>
<properties>
<year>1999</year>
</properties>
<headerDefinitions>
<headerDefinition>src/main/javadocHeaders.xml</headerDefinition>
</headerDefinitions>
</configuration>
</plugin>
</plugins>
</build>
<pluginRepositories>
</pluginRepositories>
</profile>
<profile>
<id>generate-osgi-service-loader-mediator-entries</id>
<activation>
<file>
<exists>src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider</exists>
</file>
</activation>
<build>
<!-- Add the OSGi Service Loader Mediator Specification Manifest entries for each module that has a SLF4JServiceProvider Service-Loader file.-->
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability><![CDATA[
osgi.service;objectClass:List<String>="org.slf4j.spi.SLF4JServiceProvider";type=${slf4j.provider.type};effective:=active,
osgi.serviceloader;osgi.serviceloader="org.slf4j.spi.SLF4JServiceProvider";register:="${slf4j.provider.implementation}";type=${slf4j.provider.type}
]]></Provide-Capability>
<Require-Capability><![CDATA[
osgi.extender;filter:="(&(osgi.extender=osgi.serviceloader.registrar)(version>=1.0.0)(!(version>=2.0.0)))"
]]></Require-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</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>
</project>

535
pom.xml
View File

@ -5,53 +5,94 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-bom</artifactId>
<version>2.0.19-SNAPSHOT</version>
<packaging>pom</packaging>
<artifactId>slf4j-parent</artifactId>
<version>2.0.0-alpha4</version>
<packaging>pom</packaging>
<name>SLF4J</name>
<description>Top SLF4J project pom.xml file</description>
<url>http://www.slf4j.org</url>
<name>SLF4J BOM</name>
<description>SLF4J project BOM</description>
<organization>
<name>QOS.ch</name>
<url>http://www.qos.ch</url>
</organization>
<inceptionYear>2005</inceptionYear>
<licenses>
<license>
<name>MIT</name>
<url>https://opensource.org/license/mit</url>
<name>MIT License</name>
<url>http://www.opensource.org/licenses/mit-license.php</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>
<properties>
<latest.stable.version>1.7.32</latest.stable.version>
<!-- java.util.ServiceLoader requires Java 6 -->
<jdk.version>8</jdk.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 -->
<slf4j.api.minimum.compatible.version>1.6.0</slf4j.api.minimum.compatible.version>
<cal10n.version>0.8.1</cal10n.version>
<log4j.version>1.2.17</log4j.version>
<logback.version>1.2.3</logback.version>
<junit.version>4.12</junit.version>
<maven-site-plugin.version>3.7.1</maven-site-plugin.version>
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
<maven-javadoc-plugin.version>3.1.0</maven-javadoc-plugin.version>
<maven-source-plugin.version>3.2.0</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.1.1</maven-jxr-plugin.version>
<build-helper-maven-plugin.version>3.2.0</build-helper-maven-plugin.version>
</properties>
<developers>
<developer>
<id>ceki</id>
<name>Ceki Gulcu</name>
<email>ceki@qos.ch</email>
</developer>
</developers>
<!-- 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-simple</module>
<module>slf4j-nop</module>
<module>slf4j-jdk14</module>
<module>slf4j-jdk-platform-logging</module>
<module>slf4j-log4j12</module>
<module>slf4j-reload4j</module>
<module>slf4j-ext</module>
<module>jcl-over-slf4j</module>
<module>log4j-over-slf4j</module>
<module>jul-to-slf4j</module>
<module>osgi-over-slf4j</module>
<module>integration</module>
<module>slf4j-site</module>
<module>slf4j-migrator</module>
</modules>
<properties>
<central-publishing-maven-plugin.version>0.9.0</central-publishing-maven-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
@ -62,183 +103,344 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk-platform-logging</artifactId>
<artifactId>slf4j-simple</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${project.version}</version>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
<version>${project.version}</version>
<groupId>ch.qos.cal10n</groupId>
<artifactId>cal10n-api</artifactId>
<version>${cal10n.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>
<distributionManagement>
<repository>
<id>sonatype-nexus-staging</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<developers>
<developer>
<id>ceki</id>
<name>Ceki Gulcu</name>
<email>ceki@qos.ch</email>
</developer>
</developers>
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.10</version>
</extension>
</extensions>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.14</version>
<configuration>
<signature>
<groupId>org.codehaus.mojo.signature</groupId>
<artifactId>java16</artifactId>
<version>1.0</version>
</signature>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>${maven-deploy-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<executions>
<execution>
<id>default-compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</execution>
<execution>
<id>module-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>9</release>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/main/java9</compileSourceRoot>
</compileSourceRoots>
<multiReleaseOutput>true</multiReleaseOutput>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<executions>
<execution>
<id>default-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<archive>
<manifestEntries>
<Bundle-Version>${parsedVersion.osgiVersion}</Bundle-Version>
<Bundle-Description>${project.description}</Bundle-Description>
<X-Compile-Source-JDK>${maven.compiler.source}</X-Compile-Source-JDK>
<X-Compile-Target-JDK>${maven.compiler.target}</X-Compile-Target-JDK>
<Implementation-Version>${project.version}</Implementation-Version>
<Multi-Release>true</Multi-Release>
</manifestEntries>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
<skipIfEmpty>true</skipIfEmpty>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<verbose>true</verbose>
<skippedModules>
slf4j-jdk-platform-logging,slf4j-migrator,osgi-over-slf4j
</skippedModules>
<detectLinks>true</detectLinks>
<doctitle>SLF4J project modules ${project.version}</doctitle>
<windowtitle>SLF4J javadoc</windowtitle>
<bottom><![CDATA[Copyright &copy; 2005-{currentYear} QOS.CH Sarl. All rights reserved]]></bottom>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
<reportFormat>plain</reportFormat>
<trimStackTrace>false</trimStackTrace>
<excludes>
<exclude>**/AllTest.java</exclude>
<exclude>**/PackageTest.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven-source-plugin.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- as suggested in http://jira.qos.ch/browse/SLF4J-143 -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>${build-helper-maven-plugin.version}</version>
<executions>
<execution>
<id>parse-version</id>
<goals>
<goal>parse-version</goal>
</goals>
</execution>
</executions>
</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>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>${maven-jxr-plugin.version}</version>
<configuration>
<aggregate>true</aggregate>
<javadocDir>target/site/apidocs/</javadocDir>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version>
<configuration>
<linkJavadoc>true</linkJavadoc>
<linksource>true</linksource>
<aggregate>true</aggregate>
<additionalOptions>
<additionalOption>-Xdoclint:none</additionalOption>
</additionalOptions>
<excludePackageNames>org.slf4j.migrator:org.slf4j.migrator.*</excludePackageNames>
<sourceFileExcludes>
<sourceFileExclude>**/module-info.java</sourceFileExclude>
</sourceFileExcludes>
<groups>
<group>
<title>SLF4J API packages</title>
<packages>org.slf4j:org.slf4j.spi:org.slf4j.event:org.slf4j.helpers</packages>
<title>SLF4J packages</title>
<packages>org.slf4j:org.slf4j.*</packages>
</group>
<group>
<title>slf4j-simple package</title>
<packages>org.slf4j.simple</packages>
</group>
<group>
<title>slf4j-nop package</title>
<packages>org.slf4j.nop</packages>
</group>
<group>
<title>slf4j-jdk14 package</title>
<packages>org.slf4j.jul</packages>
</group>
<group>
<title>slf4j-reload4j package</title>
<packages>org.slf4j.reload4j</packages>
</group>
<group>
<title>SLF4J extensions</title>
<packages>
org.slf4j.cal10n:org.slf4j.profiler:org.slf4j.ext:org.slf4j.instrumentation:org.slf4j.agent
</packages>
</group>
<group>
<title>Jakarta Commons Logging packages</title>
<packages>org.apache.commons.*</packages>
</group>
<group>
<title>java.util.logging (JUL) to SLF4J bridge</title>
<packages>org.slf4j.bridge</packages>
</group>
<group>
<title>log4j-over-slf4j redirection</title>
<title>Apache log4j</title>
<packages>org.apache.log4j:org.apache.log4j.*</packages>
</group>
</groups>
</configuration>
</plugin>
<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>
</reporting>
<profiles>
<profile>
<id>skipTests</id>
<properties>
<maven.test.skip>true</maven.test.skip>
</properties>
</profile>
<profile>
<id>javadocjar</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
<failOnError>false</failOnError>
<sourceFileExcludes>
<sourceFileExclude>**/module-info.java</sourceFileExclude>
</sourceFileExcludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>license</id>
<build>
<plugins>
<plugin>
<groupId>com.google.code.maven-license-plugin</groupId>
<artifactId>maven-license-plugin</artifactId>
<configuration>
<header>src/main/licenseHeader.txt</header>
<quiet>false</quiet>
<failIfMissing>true</failIfMissing>
<aggregate>true</aggregate>
<includes>
<include>src/**/*.java</include>
</includes>
<useDefaultExcludes>true</useDefaultExcludes>
<useDefaultMapping>true</useDefaultMapping>
<properties>
<year>1999</year>
</properties>
<headerDefinitions>
<headerDefinition>src/main/javadocHeaders.xml</headerDefinition>
</headerDefinitions>
</configuration>
</plugin>
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>mc-release</id>
<name>Local Maven repository of releases</name>
<url>http://mc-repo.googlecode.com/svn/maven2/releases</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
</profile>
<profile>
<id>sign-artifacts</id>
@ -261,6 +463,63 @@
</plugins>
</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>
<pluginRepositories>
<pluginRepository>
<id>apache-snapshot-repo</id>
<name>apache-snapshot-repo</name>
<url>https://repository.apache.org/content/groups/snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<distributionManagement>
<site>
<id>qos_ch</id>
<url>scp://yvo.qos.ch/var/www/www.slf4j.org/htdocs/</url>
</site>
<repository>
<!--<id>pixie</id>-->
<!--<url>scp://pixie.qos.ch/var/mvnrepo/</url>-->
<id>sonatype-nexus-staging</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</project>

View File

@ -1,18 +1,10 @@
# Javadoc
#JDK8 - mvn site:site
#rscpSLF4J apidocs/
# JDK 11+
# adding the following
#mvn -Ddoclint=none -Dadditionalparam=-Xdoclint:none javadoc:aggregate
#mvn versions:set -DgenerateBackupPoms=false -DnewVersion=${VERSION_NUMBER}
MVN='/java/maven-3.5.2//bin/mvn'
PASS=$1
echo $PASS
function checkExit(){
if test "$?" != "0"; then
echo Command $1 exited with abnormal status
@ -29,7 +21,7 @@ function echoRunAndCheck () { # echo and then run the command
then
echo Failed command: $1
exit 1;
else echo Successful run: $1
else echo Succussful run: $1
fi
}
@ -39,24 +31,25 @@ echoRunAndCheck "$MVN install"
#echoRunAndCheck "$MVN site:site"
#echoRunAndCheck "$MVN javadoc:aggregate"
echoRunAndCheck "$MVN javadoc:aggregate"
#echoRunAndCheck "$MVN jxr:aggregate"
echoRunAndCheck "$MVN jxr:aggregate"
echoRunAndCheck "$MVN assembly:single"
if [ ! -z "$PASS" ]
then
# WARNING deploying without cleaning may leave stale MANIFEST files
export GPG_TTY=$(tty)
echoRunAndCheck "$MVN deploy -P javadocjar,sign-artifacts"
echoRunAndCheck "$MVN deploy -P javadocjar,sign-artifacts -Dgpg.passphrase=$PASS"
fi
#$MVN site:deploy -N # with Java 8!!!
#checkExit "mvn site:deploy -N"
git tag -m "tagging" -a v_${VERSION_NUMBER}
git push --tags
#Update release version and add next version on jira
#git tag -m "tagging" -a v_${VERSION_NUMBER}
#git push --tags
#release version and add next version on jira
# for 1.7.x series, scp slf4j-1.7.*.tar.gz yvo.qos.ch:/var/www/www.slf4j.org/htdocs/dist/
echo Full Success

View File

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

View File

@ -7,8 +7,7 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
<version>2.0.0-alpha4</version>
</parent>
<artifactId>slf4j-api</artifactId>
@ -22,7 +21,7 @@
<properties>
<module-name>org.slf4j</module-name>
</properties>
<build>
<plugins>
<plugin>
@ -42,7 +41,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<executions>
<execution>
<id>bundle-test-jar</id>
@ -53,27 +51,6 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<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[
*,\
org.slf4j;version="${latest.1.version}",\
org.slf4j.helpers;version="${latest.1.version}"
]]></_exportcontents>
<Require-Capability><![CDATA[
osgi.extender;filter:="(&(osgi.extender=osgi.serviceloader.processor)(version>=1.0.0)(!(version>=2.0.0)))",
osgi.serviceloader;filter:="(osgi.serviceloader=org.slf4j.spi.SLF4JServiceProvider)";osgi.serviceloader="org.slf4j.spi.SLF4JServiceProvider"
]]></Require-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2004-2022 QOS.ch
* Copyright (c) 2004-2021 QOS.ch
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
@ -37,7 +37,6 @@ import static org.slf4j.event.Level.TRACE;
import static org.slf4j.event.Level.WARN;
import org.slf4j.event.Level;
import org.slf4j.helpers.CheckReturnValue;
import org.slf4j.spi.DefaultLoggingEventBuilder;
import org.slf4j.spi.LoggingEventBuilder;
import org.slf4j.spi.NOPLoggingEventBuilder;
@ -62,7 +61,7 @@ import org.slf4j.spi.NOPLoggingEventBuilder;
* oldT = t;
* t = temperature;
* <span style="color:green">logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);</span>
* if (temperature.intValue() &gt; 50) {
* if(temperature.intValue() &gt; 50) {
* <span style="color:green">logger.info("Temperature has risen above 50 degrees.");</span>
* }
* }
@ -84,7 +83,7 @@ import org.slf4j.spi.NOPLoggingEventBuilder;
public interface Logger {
/**
* Case-insensitive String constant used to retrieve the name of the root logger.
* Case insensitive String constant used to retrieve the name of the root logger.
*
* @since 1.3
*/
@ -97,45 +96,23 @@ public interface Logger {
public String getName();
/**
* <p>Make a new {@link LoggingEventBuilder} instance as appropriate for this logger implementation.
* This default implementation always returns a new instance of {@link DefaultLoggingEventBuilder}.</p>
* <p></p>
* <p>This method is intended to be used by logging systems implementing the SLF4J API and <b>not</b>
* by end users.</p>
* <p></p>
* <p>Also note that a {@link LoggingEventBuilder} instance should be built for all levels,
* independently of the level argument. In other words, this method is an <b>unconditional</b>
* constructor for the {@link LoggingEventBuilder} appropriate for this logger implementation.</p>
* <p></p>
* @param level desired level for the event builder
* @return a new {@link LoggingEventBuilder} instance as appropriate for <b>this</b> logger
* @since 2.0
*/
default public LoggingEventBuilder makeLoggingEventBuilder(Level level) {
return new DefaultLoggingEventBuilder(this, level);
}
/**
* 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
* 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.
*
*
*
*
* @param level desired level for the event builder
* @return a new {@link LoggingEventBuilder} instance as appropriate for this logger
* @since 2.0
*/
@CheckReturnValue
default public LoggingEventBuilder atLevel(Level level) {
if (isEnabledForLevel(level)) {
return makeLoggingEventBuilder(level);
default public LoggingEventBuilder makeLoggingEventBuilder(Level level) {
if(isEnabledForLevel(level)) {
return new DefaultLoggingEventBuilder(this, level);
} else {
return NOPLoggingEventBuilder.singleton();
}
}
/**
* Returns whether this Logger is enabled for a given {@link Level}.
*
@ -248,7 +225,6 @@ public interface Logger {
* @return LoggingEventBuilder instance as appropriate for level TRACE
* @since 2.0
*/
@CheckReturnValue
default public LoggingEventBuilder atTrace() {
if (isTraceEnabled()) {
return makeLoggingEventBuilder(TRACE);
@ -445,7 +421,6 @@ public interface Logger {
* @return LoggingEventBuilder instance as appropriate for level DEBUG
* @since 2.0
*/
@CheckReturnValue
default public LoggingEventBuilder atDebug() {
if (isDebugEnabled()) {
return makeLoggingEventBuilder(DEBUG);
@ -524,8 +499,7 @@ public interface Logger {
* data is also taken into consideration.
*
* @param marker The marker data to take into consideration
* @return true if this Logger is enabled for the INFO level,
* false otherwise.
* @return true if this logger is warn enabled, false otherwise
*/
public boolean isInfoEnabled(Marker marker);
@ -586,7 +560,6 @@ public interface Logger {
* @return LoggingEventBuilder instance as appropriate for level INFO
* @since 2.0
*/
@CheckReturnValue
default public LoggingEventBuilder atInfo() {
if (isInfoEnabled()) {
return makeLoggingEventBuilder(INFO);
@ -727,7 +700,6 @@ public interface Logger {
* @return LoggingEventBuilder instance as appropriate for level WARN
* @since 2.0
*/
@CheckReturnValue
default public LoggingEventBuilder atWarn() {
if (isWarnEnabled()) {
return makeLoggingEventBuilder(WARN);
@ -869,7 +841,6 @@ public interface Logger {
* @return LoggingEventBuilder instance as appropriate for level ERROR
* @since 2.0
*/
@CheckReturnValue
default public LoggingEventBuilder atError() {
if (isErrorEnabled()) {
return makeLoggingEventBuilder(ERROR);

View File

@ -25,56 +25,53 @@
package org.slf4j;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.event.SubstituteLoggingEvent;
import org.slf4j.helpers.NOPLoggerFactory;
import org.slf4j.helpers.NOP_FallbackServiceProvider;
import org.slf4j.helpers.Reporter;
import org.slf4j.helpers.SubstituteLogger;
import org.slf4j.helpers.SubstituteServiceProvider;
import org.slf4j.helpers.SubstituteLogger;
import org.slf4j.helpers.Util;
import org.slf4j.spi.MDCAdapter;
import org.slf4j.spi.SLF4JServiceProvider;
/**
* The <code>LoggerFactory</code> is a utility class producing Loggers for
* various logging APIs, e.g. logback, reload4j, log4j and JDK 1.4 logging.
* various logging APIs, most notably for log4j, logback and JDK 1.4 logging.
* Other implementations such as {@link org.slf4j.helpers.NOPLogger NOPLogger} and
* SimpleLogger are also supported.
*
* <p><code>LoggerFactory</code> is essentially a wrapper around an
* {@link ILoggerFactory} instance provided by a {@link SLF4JServiceProvider}.
*
*
* <p><code>LoggerFactory</code> is essentially a wrapper around an
* {@link ILoggerFactory} instance bound with <code>LoggerFactory</code> at
* compile time.
*
* <p>
* Please note that all methods in <code>LoggerFactory</code> are static.
*
*
* @author Alexander Dorokhine
* @author Robert Elliot
* @author Ceki G&uuml;lc&uuml;
*
*
*/
public final class LoggerFactory {
static final String CODES_PREFIX = "https://www.slf4j.org/codes.html";
static final String CODES_PREFIX = "http://www.slf4j.org/codes.html";
static final String NO_PROVIDERS_URL = CODES_PREFIX + "#noProviders";
static final String IGNORED_BINDINGS_URL = CODES_PREFIX + "#ignoredBindings";
static final String NO_STATICLOGGERBINDER_URL = CODES_PREFIX + "#StaticLoggerBinder";
static final String MULTIPLE_BINDINGS_URL = CODES_PREFIX + "#multiple_bindings";
static final String NULL_LF_URL = CODES_PREFIX + "#null_LF";
static final String VERSION_MISMATCH = CODES_PREFIX + "#version_mismatch";
static final String SUBSTITUTE_LOGGER_URL = CODES_PREFIX + "#substituteLogger";
static final String LOGGER_NAME_MISMATCH_URL = CODES_PREFIX + "#loggerNameMismatch";
@ -84,16 +81,6 @@ public final class LoggerFactory {
static final String UNSUCCESSFUL_INIT_MSG = "org.slf4j.LoggerFactory in failed state. Original exception was thrown EARLIER. See also "
+ UNSUCCESSFUL_INIT_URL;
static final String CONNECTED_WITH_MSG = "Connected with provider of type [";
/**
* System property for explicitly setting the provider class. If set and the provider could be instantiated,
* then the service loading mechanism will be bypassed.
*
* @since 2.0.9
*/
static final public String PROVIDER_PROPERTY_KEY = "slf4j.provider";
static final int UNINITIALIZED = 0;
static final int ONGOING_INITIALIZATION = 1;
static final int FAILED_INITIALIZATION = 2;
@ -112,55 +99,21 @@ public final class LoggerFactory {
static volatile SLF4JServiceProvider PROVIDER;
// Package access for tests
static List<SLF4JServiceProvider> findServiceProviders() {
List<SLF4JServiceProvider> providerList = new ArrayList<>();
// retain behaviour similar to that of 1.7 series and earlier. More specifically, use the class loader that
// loaded the present class to search for services
final ClassLoader classLoaderOfLoggerFactory = LoggerFactory.class.getClassLoader();
SLF4JServiceProvider explicitProvider = loadExplicitlySpecified(classLoaderOfLoggerFactory);
if(explicitProvider != null) {
providerList.add(explicitProvider);
return providerList;
}
ServiceLoader<SLF4JServiceProvider> serviceLoader = getServiceLoader(classLoaderOfLoggerFactory);
Iterator<SLF4JServiceProvider> iterator = serviceLoader.iterator();
while (iterator.hasNext()) {
safelyInstantiate(providerList, iterator);
private static List<SLF4JServiceProvider> findServiceProviders() {
ServiceLoader<SLF4JServiceProvider> serviceLoader = ServiceLoader.load(SLF4JServiceProvider.class);
List<SLF4JServiceProvider> providerList = new ArrayList<SLF4JServiceProvider>();
for (SLF4JServiceProvider provider : serviceLoader) {
providerList.add(provider);
}
return providerList;
}
private static ServiceLoader<SLF4JServiceProvider> getServiceLoader(final ClassLoader classLoaderOfLoggerFactory) {
ServiceLoader<SLF4JServiceProvider> serviceLoader;
SecurityManager securityManager = System.getSecurityManager();
if(securityManager == null) {
serviceLoader = ServiceLoader.load(SLF4JServiceProvider.class, classLoaderOfLoggerFactory);
} else {
final PrivilegedAction<ServiceLoader<SLF4JServiceProvider>> action = () -> ServiceLoader.load(SLF4JServiceProvider.class, classLoaderOfLoggerFactory);
serviceLoader = AccessController.doPrivileged(action);
}
return serviceLoader;
}
private static void safelyInstantiate(List<SLF4JServiceProvider> providerList, Iterator<SLF4JServiceProvider> iterator) {
try {
SLF4JServiceProvider provider = iterator.next();
providerList.add(provider);
} catch (ServiceConfigurationError e) {
Reporter.error("A service provider failed to instantiate:\n" + e.getMessage());
}
}
/**
* It is LoggerFactory's responsibility to track version changes and manage
* the compatibility list.
* <p>
* <p>
* It is assumed that all versions in the 1.6 are mutually compatible.
*/
static private final String[] API_COMPATIBILITY_LIST = new String[] { "2.0" };
@ -196,16 +149,15 @@ 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;
reportActualBinding(providersList);
} else {
INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;
Reporter.warn("No SLF4J providers were found.");
Reporter.warn("Defaulting to no-operation (NOP) logger implementation");
Reporter.warn("See " + NO_PROVIDERS_URL + " for further details.");
Util.report("No SLF4J providers were found.");
Util.report("Defaulting to no-operation (NOP) logger implementation");
Util.report("See " + NO_PROVIDERS_URL + " for further details.");
Set<URL> staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
reportIgnoredStaticLoggerBinders(staticLoggerBinderPathSet);
@ -217,64 +169,27 @@ 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()) {
return null;
}
try {
String message = String.format("Attempting to load provider \"%s\" specified via \"%s\" system property", explicitlySpecified, PROVIDER_PROPERTY_KEY);
Reporter.info(message);
Class<?> clazz = classLoader.loadClass(explicitlySpecified);
Constructor<?> constructor = clazz.getConstructor();
Object provider = constructor.newInstance();
return (SLF4JServiceProvider) provider;
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
String message = String.format("Failed to instantiate the specified SLF4JServiceProvider (%s)", explicitlySpecified);
Reporter.error(message, e);
return null;
} catch (ClassCastException e) {
String message = String.format("Specified SLF4JServiceProvider (%s) does not implement SLF4JServiceProvider interface", explicitlySpecified);
Reporter.error(message, e);
return null;
}
}
private static void reportIgnoredStaticLoggerBinders(Set<URL> staticLoggerBinderPathSet) {
if (staticLoggerBinderPathSet.isEmpty()) {
return;
}
Reporter.warn("Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier.");
Util.report("Class path contains SLF4J bindings targeting slf4j-api versions prior to 1.8.");
for (URL path : staticLoggerBinderPathSet) {
Reporter.warn("Ignoring binding found at [" + path + "]");
Util.report("Ignoring binding found at [" + path + "]");
}
Reporter.warn("See " + IGNORED_BINDINGS_URL + " for an explanation.");
Util.report("See " + IGNORED_BINDINGS_URL + " for an explanation.");
}
// We need to use the name of the StaticLoggerBinder class, but we can't
// reference the class itself.
private static final String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";
private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";
static Set<URL> findPossibleStaticLoggerBinderPathSet() {
// use Set instead of list in order to deal with bug #138
// LinkedHashSet appropriate here because it preserves insertion order
// during iteration
Set<URL> staticLoggerBinderPathSet = new LinkedHashSet<>();
Set<URL> staticLoggerBinderPathSet = new LinkedHashSet<URL>();
try {
ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader();
Enumeration<URL> paths;
@ -288,7 +203,7 @@ public final class LoggerFactory {
staticLoggerBinderPathSet.add(path);
}
} catch (IOException ioe) {
Reporter.error("Error getting resources from path", ioe);
Util.report("Error getting resources from path", ioe);
}
return staticLoggerBinderPathSet;
}
@ -313,7 +228,7 @@ public final class LoggerFactory {
static void failedBinding(Throwable t) {
INITIALIZATION_STATE = FAILED_INITIALIZATION;
Reporter.error("Failed to instantiate SLF4J LoggerFactory", t);
Util.report("Failed to instantiate SLF4J LoggerFactory", t);
}
private static void replayEvents() {
@ -321,7 +236,7 @@ public final class LoggerFactory {
final int queueSize = queue.size();
int count = 0;
final int maxDrain = 128;
List<SubstituteLoggingEvent> eventList = new ArrayList<>(maxDrain);
List<SubstituteLoggingEvent> eventList = new ArrayList<SubstituteLoggingEvent>(maxDrain);
while (true) {
int numDrained = queue.drainTo(eventList, maxDrain);
if (numDrained == 0)
@ -358,26 +273,24 @@ public final class LoggerFactory {
if (substLogger.isDelegateNOP()) {
// nothing to do
} else if (substLogger.isDelegateEventAware()) {
if(substLogger.isEnabledForLevel(event.getLevel())) {
substLogger.log(event);
}
substLogger.log(event);
} else {
Reporter.warn(loggerName);
Util.report(loggerName);
}
}
private static void emitSubstitutionWarning() {
Reporter.warn("The following set of substitute loggers may have been accessed");
Reporter.warn("during the initialization phase. Logging calls during this");
Reporter.warn("phase were not honored. However, subsequent logging calls to these");
Reporter.warn("loggers will work as normally expected.");
Reporter.warn("See also " + SUBSTITUTE_LOGGER_URL);
Util.report("The following set of substitute loggers may have been accessed");
Util.report("during the initialization phase. Logging calls during this");
Util.report("phase were not honored. However, subsequent logging calls to these");
Util.report("loggers will work as normally expected.");
Util.report("See also " + SUBSTITUTE_LOGGER_URL);
}
private static void emitReplayWarning(int eventCount) {
Reporter.warn("A number (" + eventCount + ") of logging calls during the initialization phase have been intercepted and are");
Reporter.warn("now being replayed. These are subject to the filtering rules of the underlying logging system.");
Reporter.warn("See also " + REPLAY_URL);
Util.report("A number (" + eventCount + ") of logging calls during the initialization phase have been intercepted and are");
Util.report("now being replayed. These are subject to the filtering rules of the underlying logging system.");
Util.report("See also " + REPLAY_URL);
}
private final static void versionSanityCheck() {
@ -391,13 +304,18 @@ public final class LoggerFactory {
}
}
if (!match) {
Reporter.warn("The requested version " + requested + " by your slf4j provider is not compatible with "
Util.report("The requested version " + requested + " by your slf4j binding is not compatible with "
+ Arrays.asList(API_COMPATIBILITY_LIST).toString());
Reporter.warn("See " + VERSION_MISMATCH + " for further details.");
Util.report("See " + VERSION_MISMATCH + " for further details.");
}
} catch (java.lang.NoSuchFieldError nsfe) {
// given our large user base and SLF4J's commitment to backward
// compatibility, we cannot cry here. Only for implementations
// which willingly declare a REQUESTED_API_VERSION field do we
// emit compatibility warnings.
} catch (Throwable e) {
// we should never reach here
Reporter.error("Unexpected problem occurred during version sanity check", e);
Util.report("Unexpected problem occured during version sanity check", e);
}
}
@ -408,36 +326,29 @@ public final class LoggerFactory {
/**
* Prints a warning message on the console if multiple bindings were found
* on the class path. No reporting is done otherwise.
*
*
*/
private static void reportMultipleBindingAmbiguity(List<SLF4JServiceProvider> providerList) {
if (isAmbiguousProviderList(providerList)) {
Reporter.warn("Class path contains multiple SLF4J providers.");
Util.report("Class path contains multiple SLF4J providers.");
for (SLF4JServiceProvider provider : providerList) {
Reporter.warn("Found provider [" + provider + "]");
Util.report("Found provider [" + provider + "]");
}
Reporter.warn("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");
Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");
}
}
private static void reportActualBinding(List<SLF4JServiceProvider> providerList) {
// 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.debug(CONNECTED_WITH_MSG + provider.getClass().getName() + "]");
// binderPathSet can be null under Android
if (!providerList.isEmpty() && isAmbiguousProviderList(providerList)) {
Util.report("Actual provider is of type [" + providerList.get(0) + "]");
}
}
/**
* Return a logger named according to the name parameter using the
* statically bound {@link ILoggerFactory} instance.
*
*
* @param name
* The name of the logger.
* @return logger
@ -450,20 +361,20 @@ public final class LoggerFactory {
/**
* Return a logger named corresponding to the class passed as parameter,
* using the statically bound {@link ILoggerFactory} instance.
*
*
* <p>
* In case the <code>clazz</code> parameter differs from the name of the
* In case the the <code>clazz</code> parameter differs from the name of the
* caller as computed internally by SLF4J, a logger name mismatch warning
* will be printed but only if the
* <code>slf4j.detectLoggerNameMismatch</code> system property is set to
* true. By default, this property is not set and no warnings will be
* printed even in case of a logger name mismatch.
*
*
* @param clazz
* the returned logger will be named after clazz
* @return logger
*
*
*
*
* @see <a
* href="http://www.slf4j.org/codes.html#loggerNameMismatch">Detected
* logger name mismatch</a>
@ -473,9 +384,9 @@ public final class LoggerFactory {
if (DETECT_LOGGER_NAME_MISMATCH) {
Class<?> autoComputedCallingClass = Util.getCallingClass();
if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
Reporter.warn(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(),
Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(),
autoComputedCallingClass.getName()));
Reporter.warn("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation");
Util.report("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation");
}
}
return logger;
@ -490,7 +401,7 @@ public final class LoggerFactory {
* <p>
* <p>
* ILoggerFactory instance is bound with this class at compile time.
*
*
* @return the ILoggerFactory instance in use
*/
public static ILoggerFactory getILoggerFactory() {
@ -499,7 +410,7 @@ public final class LoggerFactory {
/**
* Return the {@link SLF4JServiceProvider} in use.
* @return provider in use
* @since 1.8.0
*/

View File

@ -27,7 +27,7 @@ package org.slf4j;
/**
* All methods in this class are reserved for internal use, for testing purposes.
*
* <p>They can be modified, renamed or removed at any time without notice.
* <p>They can can be modified, renamed or removed at any time without notice.
*
* <p>You are strongly discouraged calling any of the methods of this class.
*

View File

@ -25,10 +25,11 @@
package org.slf4j;
import java.io.Closeable;
import java.util.Deque;
import java.util.Map;
import org.slf4j.helpers.*;
import org.slf4j.helpers.BasicMDCAdapter;
import org.slf4j.helpers.NOPMDCAdapter;
import org.slf4j.helpers.Util;
import org.slf4j.spi.MDCAdapter;
import org.slf4j.spi.SLF4JServiceProvider;
@ -63,9 +64,8 @@ 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_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 MDC_ADAPTER;
static MDCAdapter mdcAdapter;
/**
* An adapter to remove the key when done.
@ -85,30 +85,14 @@ public class MDC {
private MDC() {
}
private static MDCAdapter getMDCAdapterGivenByProvider() {
static {
SLF4JServiceProvider provider = LoggerFactory.getProvider();
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;
if (provider != null) {
mdcAdapter = provider.getMDCAdapter();
} else {
Reporter.error("Failed to find provider.");
Reporter.error("Defaulting to no-operation MDCAdapter implementation.");
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.");
Util.report("Failed to find provider.");
Util.report("Defaulting to no-operation MDCAdapter implementation.");
mdcAdapter = new NOPMDCAdapter();
}
}
@ -131,10 +115,10 @@ public class MDC {
if (key == null) {
throw new IllegalArgumentException("key parameter cannot be null");
}
if (getMDCAdapter() == null) {
throw new IllegalStateException(MDC_ADAPTER_CANNOT_BE_NULL_MESSAGE);
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
}
getMDCAdapter().put(key, val);
mdcAdapter.put(key, val);
}
/**
@ -187,8 +171,10 @@ public class MDC {
throw new IllegalArgumentException("key parameter cannot be null");
}
mdcAdapterNullCheck();
return getMDCAdapter().get(key);
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
}
return mdcAdapter.get(key);
}
/**
@ -206,16 +192,20 @@ public class MDC {
throw new IllegalArgumentException("key parameter cannot be null");
}
mdcAdapterNullCheck();
getMDCAdapter().remove(key);
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
}
mdcAdapter.remove(key);
}
/**
* Clear all entries in the MDC of the underlying implementation.
*/
public static void clear() {
mdcAdapterNullCheck();
getMDCAdapter().clear();
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
}
mdcAdapter.clear();
}
/**
@ -226,8 +216,10 @@ public class MDC {
* @since 1.5.1
*/
public static Map<String, String> getCopyOfContextMap() {
mdcAdapterNullCheck();
return getMDCAdapter().getCopyOfContextMap();
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
}
return mdcAdapter.getCopyOfContextMap();
}
/**
@ -242,79 +234,20 @@ public class MDC {
* @since 1.5.1
*/
public static void setContextMap(Map<String, String> contextMap) {
mdcAdapterNullCheck();
getMDCAdapter().setContextMap(contextMap);
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
}
mdcAdapter.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() {
if(MDC_ADAPTER == null) {
MDC_ADAPTER = getMDCAdapterGivenByProvider();
}
return MDC_ADAPTER;
return mdcAdapter;
}
/**
* 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'.
*
* @param key identifies the appropriate stack
* @param value the value to push into the stack
* @since 2.0.0
*/
static public void pushByKey(String key, String value) {
mdcAdapterNullCheck();
getMDCAdapter().pushByKey(key, value);
}
/**
* 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) {
mdcAdapterNullCheck();
return getMDCAdapter().popByKey(key);
}
/**
* 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.
*
* @since 2.0.0
*/
public Deque<String> getCopyOfDequeByKey(String key) {
mdcAdapterNullCheck();
return getMDCAdapter().getCopyOfDequeByKey(key);
}
private static void mdcAdapterNullCheck() {
if (getMDCAdapter() == null) {
throw new IllegalStateException(MDC_ADAPTER_CANNOT_BE_NULL_MESSAGE);
}
}
}

View File

@ -29,16 +29,14 @@ import java.util.Iterator;
/**
* Markers are named objects used to enrich log statements. Conforming logging
* system implementations of SLF4J should determine how information conveyed by
* any markers are used, if at all. Many conforming logging systems ignore marker
* data entirely.
*
* <p>Markers can contain references to nested markers, which in turn may
* contain references of their own. Note that the fluent API (new in 2.0) allows adding
* multiple markers to a logging statement. It is often preferable to use
* multiple markers instead of nested markers.
* </p>
*
* system Implementations of SLF4J determine how information conveyed by markers
* are used, if at all. In particular, many conforming logging systems ignore
* marker data.
*
* <p>
* Markers can contain references to other markers, which in turn may contain
* references of their own.
*
* @author Ceki G&uuml;lc&uuml;
*/
public interface Marker extends Serializable {
@ -62,11 +60,7 @@ public interface Marker extends Serializable {
/**
* Add a reference to another Marker.
*
* <p>Note that the fluent API allows adding multiple markers to a logging statement.
* It is often preferable to use multiple markers instead of nested markers.
* </p>
*
*
* @param reference
* a reference to another marker
* @throws IllegalArgumentException

View File

@ -25,7 +25,6 @@
package org.slf4j;
import org.slf4j.helpers.BasicMarkerFactory;
import org.slf4j.helpers.Reporter;
import org.slf4j.helpers.Util;
import org.slf4j.spi.SLF4JServiceProvider;
@ -54,8 +53,8 @@ public class MarkerFactory {
if (provider != null) {
MARKER_FACTORY = provider.getMarkerFactory();
} else {
Reporter.error("Failed to find provider");
Reporter.error("Defaulting to BasicMarkerFactory.");
Util.report("Failed to find provider");
Util.report("Defaulting to BasicMarkerFactory.");
MARKER_FACTORY = new BasicMarkerFactory();
}
}

View File

@ -126,10 +126,6 @@ public class DefaultLoggingEvent implements LoggingEvent {
return timeStamp;
}
public void setTimeStamp(long timeStamp) {
this.timeStamp = timeStamp;
}
public void setCallerBoundary(String fqcn) {
this.callerBoundary = fqcn;
}

View File

@ -16,7 +16,7 @@ import org.slf4j.helpers.SubstituteLogger;
* @author Wessel van Norel
*
*/
public class EventRecordingLogger extends LegacyAbstractLogger {
public class EventRecodingLogger extends LegacyAbstractLogger {
private static final long serialVersionUID = -176083308134819629L;
@ -27,7 +27,7 @@ public class EventRecordingLogger extends LegacyAbstractLogger {
// as an event recording logger we have no choice but to record all events
final static boolean RECORD_ALL_EVENTS = true;
public EventRecordingLogger(SubstituteLogger logger, Queue<SubstituteLoggingEvent> eventQueue) {
public EventRecodingLogger(SubstituteLogger logger, Queue<SubstituteLoggingEvent> eventQueue) {
this.logger = logger;
this.name = logger.getName();
this.eventQueue = eventQueue;

View File

@ -1,7 +1,5 @@
package org.slf4j.event;
import java.util.Objects;
public class KeyValuePair {
public final String key;
@ -16,17 +14,4 @@ public class KeyValuePair {
public String toString() {
return String.valueOf(key) + "=\"" + String.valueOf(value) +"\"";
}
@Override
public boolean equals(Object o) {
if(this == o) return true;
if(o == null || getClass() != o.getClass()) return false;
KeyValuePair that = (KeyValuePair) o;
return Objects.equals(key, that.key) && Objects.equals(value, that.value);
}
@Override
public int hashCode() {
return Objects.hash(key, value);
}
}

View File

@ -17,8 +17,8 @@ public enum Level {
ERROR(ERROR_INT, "ERROR"), WARN(WARN_INT, "WARN"), INFO(INFO_INT, "INFO"), DEBUG(DEBUG_INT, "DEBUG"), TRACE(TRACE_INT, "TRACE");
private final int levelInt;
private final String levelStr;
private int levelInt;
private String levelStr;
Level(int i, String s) {
levelInt = i;

View File

@ -23,10 +23,6 @@ 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

@ -407,17 +407,17 @@ public abstract class AbstractLogger implements Logger, Serializable {
abstract protected String getFullyQualifiedCallerName();
/**
* Given various arguments passed as parameters, perform actual logging.
* Given various arguments passed as parameters perform actual logging.
*
* <p>This method assumes that the separation of the args array into actual
* objects and a throwable has been already operated.
*
* @param level the SLF4J level for this event
* @param marker The marker to be used for this event, may be null.
* @param messagePattern The message pattern which will be parsed and formatted
* @param arguments the array of arguments to be formatted, may be null
* @param throwable The exception whose stack trace should be logged, may be null
* @param level
* @param marker
* @param msg
* @param arguments
* @param throwable
*/
abstract protected void handleNormalizedLoggingCall(Level level, Marker marker, String messagePattern, Object[] arguments, Throwable throwable);
abstract protected void handleNormalizedLoggingCall(Level level, Marker marker, String msg, Object[] arguments, Throwable throwable);
}

View File

@ -27,6 +27,7 @@ package org.slf4j.helpers;
import org.slf4j.spi.MDCAdapter;
import java.util.*;
import java.util.Map;
/**
* Basic MDC implementation, which can be used with logging systems that lack
@ -43,15 +44,13 @@ import java.util.*;
*/
public class BasicMDCAdapter implements MDCAdapter {
private final ThreadLocalMapOfStacks threadLocalMapOfDeques = new ThreadLocalMapOfStacks();
private final InheritableThreadLocal<Map<String, String>> inheritableThreadLocalMap = new InheritableThreadLocal<Map<String, String>>() {
private InheritableThreadLocal<Map<String, String>> inheritableThreadLocal = new InheritableThreadLocal<Map<String, String>>() {
@Override
protected Map<String, String> childValue(Map<String, String> parentValue) {
if (parentValue == null) {
return null;
}
return new HashMap<>(parentValue);
return new HashMap<String, String>(parentValue);
}
};
@ -71,10 +70,10 @@ public class BasicMDCAdapter implements MDCAdapter {
if (key == null) {
throw new IllegalArgumentException("key cannot be null");
}
Map<String, String> map = inheritableThreadLocalMap.get();
Map<String, String> map = inheritableThreadLocal.get();
if (map == null) {
map = new HashMap<>();
inheritableThreadLocalMap.set(map);
map = new HashMap<String, String>();
inheritableThreadLocal.set(map);
}
map.put(key, val);
}
@ -83,7 +82,7 @@ public class BasicMDCAdapter implements MDCAdapter {
* Get the context identified by the <code>key</code> parameter.
*/
public String get(String key) {
Map<String, String> map = inheritableThreadLocalMap.get();
Map<String, String> map = inheritableThreadLocal.get();
if ((map != null) && (key != null)) {
return map.get(key);
} else {
@ -92,10 +91,10 @@ public class BasicMDCAdapter implements MDCAdapter {
}
/**
* Remove the context identified by the <code>key</code> parameter.
* Remove the the context identified by the <code>key</code> parameter.
*/
public void remove(String key) {
Map<String, String> map = inheritableThreadLocalMap.get();
Map<String, String> map = inheritableThreadLocal.get();
if (map != null) {
map.remove(key);
}
@ -105,10 +104,10 @@ public class BasicMDCAdapter implements MDCAdapter {
* Clear all entries in the MDC.
*/
public void clear() {
Map<String, String> map = inheritableThreadLocalMap.get();
Map<String, String> map = inheritableThreadLocal.get();
if (map != null) {
map.clear();
inheritableThreadLocalMap.remove();
inheritableThreadLocal.remove();
}
}
@ -119,7 +118,7 @@ public class BasicMDCAdapter implements MDCAdapter {
* @return the keys in the MDC
*/
public Set<String> getKeys() {
Map<String, String> map = inheritableThreadLocalMap.get();
Map<String, String> map = inheritableThreadLocal.get();
if (map != null) {
return map.keySet();
} else {
@ -133,9 +132,9 @@ public class BasicMDCAdapter implements MDCAdapter {
*
*/
public Map<String, String> getCopyOfContextMap() {
Map<String, String> oldMap = inheritableThreadLocalMap.get();
Map<String, String> oldMap = inheritableThreadLocal.get();
if (oldMap != null) {
return new HashMap<>(oldMap);
return new HashMap<String, String>(oldMap);
} else {
return null;
}
@ -143,28 +142,9 @@ public class BasicMDCAdapter implements MDCAdapter {
public void setContextMap(Map<String, String> contextMap) {
Map<String, String> copy = null;
if (contextMap != null) {
copy = new HashMap<>(contextMap);
if(contextMap != null) {
copy = new HashMap<String, String>(contextMap);
}
inheritableThreadLocalMap.set(copy);
}
@Override
public void pushByKey(String key, String value) {
threadLocalMapOfDeques.pushByKey(key, value);
}
@Override
public String popByKey(String key) {
return threadLocalMapOfDeques.popByKey(key);
}
@Override
public Deque<String> getCopyOfDequeByKey(String key) {
return threadLocalMapOfDeques.getCopyOfDequeByKey(key);
}
@Override
public void clearDequeByKey(String key) {
threadLocalMapOfDeques.clearDequeByKey(key);
inheritableThreadLocal.set(copy);
}
}

View File

@ -40,7 +40,7 @@ public class BasicMarker implements Marker {
private static final long serialVersionUID = -2849567615646933777L;
private final String name;
private final List<Marker> referenceList = new CopyOnWriteArrayList<>();
private List<Marker> referenceList = new CopyOnWriteArrayList<Marker>();
BasicMarker(String name) {
if (name == null) {
@ -128,9 +128,9 @@ public class BasicMarker implements Marker {
return false;
}
private static final String OPEN = "[ ";
private static final String CLOSE = " ]";
private static final String SEP = ", ";
private static String OPEN = "[ ";
private static String CLOSE = " ]";
private static String SEP = ", ";
public boolean equals(Object obj) {
if (this == obj)

View File

@ -41,7 +41,7 @@ import org.slf4j.Marker;
*/
public class BasicMarkerFactory implements IMarkerFactory {
private final ConcurrentMap<String, Marker> markerMap = new ConcurrentHashMap<>();
private final ConcurrentMap<String, Marker> markerMap = new ConcurrentHashMap<String, Marker>();
/**
* Regular users should <em>not</em> create

View File

@ -1,30 +0,0 @@
package org.slf4j.helpers;
import org.slf4j.Marker;
import java.lang.annotation.*;
/**
* <p>Used to annotate methods in the {@link org.slf4j.spi.LoggingEventBuilder} interface
* which return an instance of LoggingEventBuilder (usually as <code>this</code>). Such
* methods should be followed by one of the terminating <code>log()</code> methods returning
* <code>void</code>.</p>
* <p></p>
* <p>IntelliJ IDEA supports a check for annotations named as <code>CheckReturnValue</code>
* regardless of the containing package. For more information on this feature in IntelliJ IDEA,
* select File &#8594; Setting &#8594; Editor &#8594; Inspections and then Java &#8594; Probable Bugs &#8594;
* Result of method call ignored. </p>
* <p></p>
*
* <p>As for Eclipse, this feature has been requested in
* <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=572496">bug 572496</a></p>
*
* @author Ceki G&uuml;lc&uuml;
* @since 2.0.0-beta1
*/
@Documented
@Target( { ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckReturnValue {
}

View File

@ -33,9 +33,9 @@ public class FormattingTuple {
static public FormattingTuple NULL = new FormattingTuple(null);
private final String message;
private final Throwable throwable;
private final Object[] argArray;
private String message;
private Throwable throwable;
private Object[] argArray;
public FormattingTuple(String message) {
this(message, null, null);

View File

@ -81,7 +81,7 @@ import java.util.Map;
* will return the string "File name is C:\file.zip".
*
* <p>
* The formatting conventions are different from those of {@link MessageFormat}
* The formatting conventions are different than those of {@link MessageFormat}
* which ships with the Java platform. This is justified by the fact that
* SLF4J's implementation is 10 times faster than that of {@link MessageFormat}.
* This local performance difference is both measurable and significant in the
@ -216,13 +216,13 @@ final public class MessageFormatter {
// itself escaped: "abc x:\\{}"
// we have to consume one backward slash
sbuf.append(messagePattern, i, j - 1);
deeplyAppendParameter(sbuf, argArray[L], new HashMap<>());
deeplyAppendParameter(sbuf, argArray[L], new HashMap<Object[], Object>());
i = j + 2;
}
} else {
// normal case
sbuf.append(messagePattern, i, j);
deeplyAppendParameter(sbuf, argArray[L], new HashMap<>());
deeplyAppendParameter(sbuf, argArray[L], new HashMap<Object[], Object>());
i = j + 2;
}
}
@ -291,7 +291,7 @@ final public class MessageFormatter {
String oAsString = o.toString();
sbuf.append(oAsString);
} catch (Throwable t) {
Reporter.error("Failed toString() invocation on an object of type [" + o.getClass().getName() + "]", t);
Util.report("SLF4J: Failed toString() invocation on an object of type [" + o.getClass().getName() + "]", t);
sbuf.append("[FAILED toString()]");
}

View File

@ -28,7 +28,7 @@ import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
/**
* NOPLoggerFactory is a trivial implementation of {@link
* NOPLoggerFactory is an trivial implementation of {@link
* ILoggerFactory} which always returns the unique instance of
* NOPLogger.
*

View File

@ -24,7 +24,6 @@
*/
package org.slf4j.helpers;
import java.util.Deque;
import java.util.Map;
import org.slf4j.spi.MDCAdapter;
@ -61,21 +60,4 @@ public class NOPMDCAdapter implements MDCAdapter {
// NOP
}
@Override
public void pushByKey(String key, String value) {
}
@Override
public String popByKey(String key) {
return null;
}
@Override
public Deque<String> getCopyOfDequeByKey(String key) {
return null;
}
public void clearDequeByKey(String key) {
}
}

View File

@ -14,9 +14,9 @@ public class NOP_FallbackServiceProvider implements SLF4JServiceProvider {
// to avoid constant folding by the compiler, this field must *not* be final
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();
private ILoggerFactory loggerFactory = new NOPLoggerFactory();
private IMarkerFactory markerFactory = new BasicMarkerFactory();
private MDCAdapter mdcAdapter = new NOPMDCAdapter();
@Override

View File

@ -3,7 +3,7 @@ package org.slf4j.helpers;
import org.slf4j.event.LoggingEvent;
/**
* Holds normalized call parameters.
* Holds normalized calling call parameters.
*
* Includes utility methods such as {@link #normalize(String, Object[], Throwable)} to help the normalization of parameters.
*

View File

@ -1,204 +0,0 @@
package org.slf4j.helpers;
import java.io.PrintStream;
/**
* An internally used class for reporting internal messages generated by SLF4J itself, typically
* during initialization.
*
* <p>
* 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>
* <p>
* <p>
* Note that this system is independent of the logging back-end in use.
*
* @since 2.0.10
*/
public class Reporter {
/**
* this class is used internally by Reporter
*/
private enum Level {
DEBUG(0), INFO(1), WARN(2), ERROR(3);
int levelInt;
private Level(int levelInt) {
this.levelInt = levelInt;
}
private int getLevelInt() {
return levelInt;
}
}
private enum TargetChoice {
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): ";
/**
* This system property controls the target for internal reports output by SLF4J.
* Recognized values for this key are "System.out", "stdout", "sysout", "System.err",
* "stderr" and "syserr".
*
* <p>By default, output is directed to "stderr".</p>
*/
public static final String SLF4J_INTERNAL_REPORT_STREAM_KEY = "slf4j.internal.report.stream";
static private final String[] SYSOUT_KEYS = {"System.out", "stdout", "sysout"};
/**
* This system property controls the internal level of chattiness
* of SLF4J. Recognized settings are "INFO", "WARN" and "ERROR". The default value is "INFO".
*/
public static final String SLF4J_INTERNAL_VERBOSITY_KEY = "slf4j.internal.verbosity";
static private final TargetChoice TARGET_CHOICE = getTargetChoice();
static private final Level INTERNAL_VERBOSITY = initVerbosity();
static private TargetChoice getTargetChoice() {
String reportStreamStr = System.getProperty(SLF4J_INTERNAL_REPORT_STREAM_KEY);
if(reportStreamStr == null || reportStreamStr.isEmpty()) {
return TargetChoice.Stderr;
}
for(String s : SYSOUT_KEYS) {
if(s.equalsIgnoreCase(reportStreamStr))
return TargetChoice.Stdout;
}
return TargetChoice.Stderr;
}
static private Level initVerbosity() {
String verbosityStr = System.getProperty(SLF4J_INTERNAL_VERBOSITY_KEY);
if(verbosityStr == null || verbosityStr.isEmpty()) {
return Level.INFO;
}
if(verbosityStr.equalsIgnoreCase("DEBUG")) {
return Level.DEBUG;
}
if(verbosityStr.equalsIgnoreCase("ERROR")) {
return Level.ERROR;
}
if(verbosityStr.equalsIgnoreCase("WARN")) {
return Level.WARN;
}
// anything else including verbosityStr.equalsIgnoreCase("INFO")
return Level.INFO;
}
static boolean isEnabledFor(Level level) {
return (level.levelInt >= INTERNAL_VERBOSITY.levelInt);
}
static private PrintStream getTarget() {
switch(TARGET_CHOICE) {
case Stdout:
return System.out;
case Stderr:
default:
return System.err;
}
}
/**
* 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 "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
*/
public static void info(String msg) {
if(isEnabledFor(Level.INFO)) {
getTarget().println(SLF4J_INFO_PREFIX + msg);
}
}
/**
* Report an internal message of level "WARN". Message text is prefixed with the string "SLF4J(W)", with
* (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 "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
*/
static final public void warn(String msg) {
if(isEnabledFor(Level.WARN)) {
getTarget().println(SLF4J_WARN_PREFIX + msg);
}
}
/**
* 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.
*
* <p>Messages of level ERROR are always enabled.
*
* @param msg the message text
* @param t a Throwable
*/
static final public void error(String msg, Throwable t) {
// error cannot be disabled
getTarget().println(SLF4J_ERROR_PREFIX + msg);
getTarget().println(SLF4J_ERROR_PREFIX + "Reported exception:");
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.
*
* <p>Messages of level ERROR are always enabled.
*
* @param msg the message text
*/
static final public void error(String msg) {
// error cannot be disabled
getTarget().println(SLF4J_ERROR_PREFIX + msg);
}
}

View File

@ -1,73 +0,0 @@
/*
* 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

@ -30,7 +30,7 @@ import java.util.Queue;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.event.EventRecordingLogger;
import org.slf4j.event.EventRecodingLogger;
import org.slf4j.event.Level;
import org.slf4j.event.LoggingEvent;
import org.slf4j.event.SubstituteLoggingEvent;
@ -52,8 +52,8 @@ public class SubstituteLogger implements Logger {
private volatile Logger _delegate;
private Boolean delegateEventAware;
private Method logMethodCache;
private EventRecordingLogger eventRecordingLogger;
private final Queue<SubstituteLoggingEvent> eventQueue;
private EventRecodingLogger eventRecodingLogger;
private Queue<SubstituteLoggingEvent> eventQueue;
public final boolean createdPostInitialization;
@ -72,11 +72,6 @@ public class SubstituteLogger implements Logger {
public LoggingEventBuilder makeLoggingEventBuilder(Level level) {
return delegate().makeLoggingEventBuilder(level);
}
@Override
public LoggingEventBuilder atLevel(Level level) {
return delegate().atLevel(level);
}
@Override
public boolean isEnabledForLevel(Level level) {
@ -445,10 +440,10 @@ public class SubstituteLogger implements Logger {
}
private Logger getEventRecordingLogger() {
if (eventRecordingLogger == null) {
eventRecordingLogger = new EventRecordingLogger(this, eventQueue);
if (eventRecodingLogger == null) {
eventRecodingLogger = new EventRecodingLogger(this, eventQueue);
}
return eventRecordingLogger;
return eventRecodingLogger;
}
/**

View File

@ -44,9 +44,9 @@ public class SubstituteLoggerFactory implements ILoggerFactory {
volatile boolean postInitialization = false;
final Map<String, SubstituteLogger> loggers = new ConcurrentHashMap<>();
final Map<String, SubstituteLogger> loggers = new ConcurrentHashMap<String, SubstituteLogger>();
final LinkedBlockingQueue<SubstituteLoggingEvent> eventQueue = new LinkedBlockingQueue<>();
final LinkedBlockingQueue<SubstituteLoggingEvent> eventQueue = new LinkedBlockingQueue<SubstituteLoggingEvent>();
synchronized public Logger getLogger(String name) {
SubstituteLogger logger = loggers.get(name);
@ -58,11 +58,11 @@ public class SubstituteLoggerFactory implements ILoggerFactory {
}
public List<String> getLoggerNames() {
return new ArrayList<>(loggers.keySet());
return new ArrayList<String>(loggers.keySet());
}
public List<SubstituteLogger> getLoggers() {
return new ArrayList<>(loggers.values());
return new ArrayList<SubstituteLogger>(loggers.values());
}
public LinkedBlockingQueue<SubstituteLoggingEvent> getEventQueue() {

View File

@ -6,19 +6,9 @@ import org.slf4j.spi.MDCAdapter;
import org.slf4j.spi.SLF4JServiceProvider;
public class SubstituteServiceProvider implements SLF4JServiceProvider {
private final SubstituteLoggerFactory loggerFactory = new SubstituteLoggerFactory();
// 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();
}
private SubstituteLoggerFactory loggerFactory = new SubstituteLoggerFactory();
private IMarkerFactory markerFactory = new BasicMarkerFactory();
private MDCAdapter mdcAdapter = new BasicMDCAdapter();
@Override
public ILoggerFactory getLoggerFactory() {
@ -46,5 +36,6 @@ public class SubstituteServiceProvider implements SLF4JServiceProvider {
@Override
public void initialize() {
}
}

View File

@ -1,89 +0,0 @@
package org.slf4j.helpers;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
/**
* A simple implementation of ThreadLocal backed Map containing values of type
* Deque<String>.
*
* @author Ceki Guuml;c&uuml;
* @since 2.0.0
*/
public class ThreadLocalMapOfStacks {
// BEWARE: Keys or values placed in a ThreadLocal should not be of a type/class
// not included in the JDK. See also https://jira.qos.ch/browse/LOGBACK-450
final ThreadLocal<Map<String, Deque<String>>> tlMapOfStacks = new ThreadLocal<>();
public void pushByKey(String key, String value) {
if (key == null)
return;
Map<String, Deque<String>> map = tlMapOfStacks.get();
if (map == null) {
map = new HashMap<>();
tlMapOfStacks.set(map);
}
Deque<String> deque = map.get(key);
if (deque == null) {
deque = new ArrayDeque<>();
}
deque.push(value);
map.put(key, deque);
}
public String popByKey(String key) {
if (key == null)
return null;
Map<String, Deque<String>> map = tlMapOfStacks.get();
if (map == null)
return null;
Deque<String> deque = map.get(key);
if (deque == null)
return null;
return deque.pop();
}
public Deque<String> getCopyOfDequeByKey(String key) {
if (key == null)
return null;
Map<String, Deque<String>> map = tlMapOfStacks.get();
if (map == null)
return null;
Deque<String> deque = map.get(key);
if (deque == null)
return null;
return new ArrayDeque<String>(deque);
}
/**
* Clear the deque(stack) referenced by 'key'.
*
* @param key identifies the stack
*
* @since 2.0.0
*/
public void clearDequeByKey(String key) {
if (key == null)
return;
Map<String, Deque<String>> map = tlMapOfStacks.get();
if (map == null)
return;
Deque<String> deque = map.get(key);
if (deque == null)
return;
deque.clear();
}
}

View File

@ -117,26 +117,12 @@ public final class Util {
return trace[i + 2];
}
/**
* 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,12 +1,10 @@
package org.slf4j.spi;
import org.slf4j.event.LoggingEvent;
/**
* Additional interface to {@link LoggingEventBuilder} and
* {@link org.slf4j.event.LoggingEvent LoggingEvent}.
* {@link org.slf4j.event.LoggingEvent LoggingEvent}.
*
* Implementations of {@link LoggingEventBuilder} and {@link LoggingEvent} may optionally
* Implementations of {@link LoggingEventBuilder} and {@link LoggingEvent} may optionally
* implement {@link CallerBoundaryAware} in order to support caller info extraction.
*
* This interface is intended for use by logging backends or logging bridges.

View File

@ -1,29 +1,5 @@
/**
* 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
* 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.spi;
import java.util.List;
import java.util.function.Supplier;
import org.slf4j.Logger;
@ -33,16 +9,8 @@ import org.slf4j.event.KeyValuePair;
import org.slf4j.event.Level;
import org.slf4j.event.LoggingEvent;
/**
* 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;
@ -53,7 +21,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
@ -72,16 +40,146 @@ public class DefaultLoggingEventBuilder implements LoggingEventBuilder, CallerBo
@Override
public LoggingEventBuilder addArgument(Object p) {
this.loggingEvent.addArgument(p);
loggingEvent.addArgument(p);
return this;
}
@Override
public LoggingEventBuilder addArgument(Supplier<?> objectSupplier) {
this.loggingEvent.addArgument(objectSupplier.get());
loggingEvent.addArgument(objectSupplier.get());
return this;
}
@Override
public void setCallerBoundary(String fqcn) {
loggingEvent.setCallerBoundary(fqcn);
}
@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);
}
protected void log(LoggingEvent logggingEvent) {
if (logger instanceof LoggingEventAware) {
((LoggingEventAware) logger).log(logggingEvent);
} else {
logViaPublicSLF4JLoggerAPI(logggingEvent);
}
}
private void logViaPublicSLF4JLoggerAPI(LoggingEvent logggingEvent) {
Object[] argArray = logggingEvent.getArgumentArray();
int argLen = argArray == null ? 0 : argArray.length;
Throwable t = logggingEvent.getThrowable();
int tLen = t == null ? 0 : 1;
String msg = logggingEvent.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(logggingEvent, msg);
switch (logggingEvent.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 logggingEvent
* @param msg
* @return
*/
private String mergeMarkersAndKeyValuePairs(LoggingEvent logggingEvent, String msg) {
StringBuilder sb = null;
if (loggingEvent.getMarkers() != null) {
sb = new StringBuilder();
for (Marker marker : logggingEvent.getMarkers()) {
sb.append(marker);
sb.append(' ');
}
}
if (logggingEvent.getKeyValuePairs() != null) {
if (sb == null) {
sb = new StringBuilder();
}
for (KeyValuePair kvp : logggingEvent.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 void log(Supplier<String> messageSupplier) {
if (messageSupplier == null) {
log((String) null);
} else {
log(messageSupplier.get());
}
}
@Override
public LoggingEventBuilder addKeyValue(String key, Object value) {
loggingEvent.addKeyValue(key, value);
@ -94,184 +192,8 @@ 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

@ -31,7 +31,6 @@ import org.slf4j.ILoggerFactory;
* class bind with the appropriate {@link ILoggerFactory} instance.
*
* @author Ceki G&uuml;lc&uuml;
* @deprecated
*/
public interface LoggerFactoryBinder {

View File

@ -4,17 +4,7 @@ import org.slf4j.event.LoggingEvent;
/**
* A logger capable of logging from org.slf4j.event.LoggingEvent implements this interface.
*
* <p>Please note that when the {@link #log(LoggingEvent)} method assumes that
* the event was filtered beforehand and no further filtering needs to occur by the method itself.
* <p>
*
* <p>Implementations of this interface <b>may</b> apply further filtering but they are not
* required to do so. In other words, {@link #log(LoggingEvent)} method is free to assume that
* the event was filtered beforehand and no further filtering needs to occur in the method itself.</p>
*
* See also https://jira.qos.ch/browse/SLF4J-575
*
*
* @author Ceki Gulcu
* @since 2.0.0
*/

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