Compare commits

...

112 Commits

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

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

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

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

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

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

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

This PR:

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

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

Signed-off-by: Manfred Hanke <Manfred.Hanke@tngtech.com>
2024-08-08 22:24:18 +02:00
Ceki Gulcu 46b5ea54a6 start work on 2.0.16-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-08 16:48:10 +02:00
Ceki Gulcu 5321a975d4 prepare release 2.0.15
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-08 14:56:10 +02:00
Ceki Gulcu 09111e8c1e added copyright, @since to Slf4jEnvUtil
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-07 17:46:14 +02:00
Ceki Gulcu 6a04f67fdd start work on version 2.0.15-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-07 17:31:29 +02:00
Ceki Gulcu 03aa6b915a prepare release 2.0.14
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-06 22:30:45 +02:00
Ceki Gulcu 7c3b0ef011 added method returning slf4j version
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-06 22:17:49 +02:00
Ceki Gulcu 42810107b0 LoggerFactory emits 'SLF4J(I): Connected with provider of type'
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-05 22:10:08 +02:00
Ceki Gulcu 982e4b067f clearer assertion take II
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-04 21:30:31 +02:00
Ceki Gulcu dd4486b5c5 clearer assertion
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-08-04 21:25:43 +02:00
Ceki Gulcu 1d82519b07 start work on 2.0.14-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-04-12 18:05:28 +02:00
Ceki Gulcu 5ffbc67def prepare release 2.0.13
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-04-12 16:21:00 +02:00
Ceki Gulcu 3386517ad6 fix issues/409 SLF4J-601, wrong classname when using slf4j inside a wrapper
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-04-12 15:47:48 +02:00
Ceki Gulcu 448bca173c start work on 2.0.13-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-02-05 22:58:12 +01:00
Ceki Gulcu 955209464d increase leniency count
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-02-05 22:32:22 +01:00
Ceki Gulcu c1473c957a prepare release 2.0.12
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-02-05 22:21:34 +01:00
Ceki Gulcu 98932348fb minor reminder
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-02-05 22:20:48 +01:00
Ceki Gulcu c52da92599 revert Util.report methods removed by mistake
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-02-05 22:17:54 +01:00
Ceki Gulcu da91e4f219 export provider packages, allow reflection by org.slf4j
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-02-05 21:45:58 +01:00
Ceki Gulcu 8c4ea8f225 more comments
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-23 15:51:31 +01:00
Ceki Gulcu 6b2921a523 start wotk on 2.0.12-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 20:50:02 +01:00
Ceki Gulcu 3f4717c44e get javadoc:aggregate command to work
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 20:48:59 +01:00
Ceki Gulcu d9145fba56 prepare release 2.0.11
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 18:58:10 +01:00
Ceki Gulcu 68ff7064ec acceptance test, disabled for the moment
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 18:50:54 +01:00
Guillaume Nodet db8cd90c10 Use computeIfAbsent with a protected method, make reset protected
Signed-off-by: Guillaume Nodet <gnodet@gmail.com>
2024-01-08 17:39:25 +01:00
Guillaume Nodet d564304a61 Use computeIfAbsent with a protected method, make reset protected
Signed-off-by: Guillaume Nodet <gnodet@gmail.com>
2024-01-08 17:39:25 +01:00
Ceki Gulcu ef8dda71dd javadoc changed for SimpleLogger constructor
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 15:23:23 +01:00
Ceki Gulcu fe42ecb5f7 change constructor access modifier instead of
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 15:16:08 +01:00
Ceki Gulcu 7029a8b7fd add renderLevel method in SimpleLogger
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2024-01-08 15:02:22 +01:00
Ceki Gulcu 8c873b2e75 start work on 2.0.11-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-12-29 00:03:40 +01:00
Ceki Gulcu 7bcee9aa1f javadoc configuration tweak
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-12-29 00:02:38 +01:00
Ceki Gulcu 6fe9c07113 more javadoc adjustments
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-12-28 21:48:34 +01:00
Ceki Gulcu df562c22d8 migrator should have javadocs
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-12-28 21:38:38 +01:00
Ceki Gulcu 6d39ca8bf9 prepare release 2.0.10
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-12-28 21:14:08 +01:00
Ceki Gulcu 86ee8298d9 javadoc edit
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-12-06 20:54:40 +01:00
Ceki Gulcu 5ccbe20b11 remove unreachable code, see issues/371
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-12-05 10:02:43 +01:00
Ceki Gulcu 02b36a269a attempt at fixing PR 358
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-11-25 20:47:16 +01:00
Ceki Gulcu c12667b906 document Reporter class
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-11-17 12:57:30 +01:00
Ceki Gulcu 316b5d1727 first attempt at fixing issues/361
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-11-15 19:59:01 +01:00
Hervé Boutemy 7c164fab8d upgrade maven-bundle-plugin
fixes Reproducible  Builds issue with OSGi metadata
2023-09-03 23:03:40 +02:00
Ceki Gulcu 56e42fdb61 start work on 2.0.10-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-09-03 18:20:34 +02:00
Ceki Gulcu 216459e5d8 prepare release 2.0.9
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-09-03 18:12:02 +02:00
Ceki Gulcu 2481810f94 rename slf4j.binding system proerty as slf4j.provider
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-09-03 18:06:27 +02:00
Ceki Gulcu 25d742d666 start work on 2.0.9-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-09-03 17:44:47 +02:00
Ceki Gulcu 10a151756d further adjusments for successful deployment on Maven Central
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-08-29 23:31:08 +02:00
Ceki Gulcu 17f5bf3d87 fix issues during deployment
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-08-29 23:04:24 +02:00
Ceki Gulcu f967033766 move parent-pom.xml to parent/pom.xml as explained in SLF4J-437
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-08-29 22:50:25 +02:00
Ceki Gulcu 0b9c92cc3a prepare release 2.0.8
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-08-29 22:14:17 +02:00
Ceki Gulcu 05698f8d23 fine tuning for SLF4J-450
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-08-29 22:06:48 +02:00
Kengo TODA 9783320b6c feat: allow binding to be explicitly specified 2023-08-29 16:40:18 +02:00
Ethan McCue aa13da39ed Fix typo in "SLF4JPlarformLoggerFactory"
Signed-off-by: Ethan McCue <ethan@mccue.dev>
2023-08-08 18:25:20 +02:00
Ceki Gulcu 7a4da876b3 add equals/hashCode to KeyValuePair
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-08-08 18:20:12 +02:00
Taku Miyakawa 0769bc8182 use MessageFormat insetad of String.format to comply spec of System.Logger.log
Signed-off-by: Taku Miyakawa <miyakawa.taku@gmail.com>
2023-08-08 18:12:15 +02:00
Ceki Gulcu e63f87f02c fix SLF4J-595
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-07-12 22:50:26 +02:00
Ceki Gulcu 3f20e0dfd2 update certain plugins, add parent-pom.xml as a module fixing SLF4J-596
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-07-12 21:52:15 +02:00
Ceki Gulcu 06fa09a2fb use jar plugin to add MainClass information in MANIFEST.MF instead of the fleix plugin, see SLF4J-594
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-07-11 11:04:41 +02:00
Ceki Gulcu 6fd9db9b5e add BOM file, fixes SLF4J-437
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-06-16 18:05:17 +02:00
Hannes Wellmann f871e7f2e9 Restore 'Main-Class' header in slf4j-migrator Manifest.MF
Because the Manifest.MF did not have a terminating new-line it was
invalid and its content was ignored, thus the Main-Class entry was
missing.

To have less files in the project, generate the entry using the
maven-bundle-plugin.

Signed-off-by: Hannes Wellmann <wellmann.hannes1@gmx.net>
2023-04-10 00:13:24 +02:00
Hannes Wellmann 0b4d88edef Use project.name in Bundle-Name and simplify slf4j-api OSGi metadata gen
The value of project.name is more expressive than the previously used
project.artifactId.

Signed-off-by: Hannes Wellmann <wellmann.hannes1@gmx.net>
2023-04-10 00:11:41 +02:00
Hannes Wellmann 2ec7c1034c Replace all remaining OSGi MANIFEST.MF by bundle-plugin instructions
This ensures that there is only a single source for OSGi metadata.
Additionally this improves the metadata for some Export-Package entries.

Signed-off-by: Hannes Wellmann <wellmann.hannes1@gmx.net>
2023-04-10 00:11:41 +02:00
Hannes Wellmann df44ace9c3 Automate OSGi metadata creation and fix metadata for other slf4j-modules
Only use the maven-bundle-plugin to generate all OSGi metadata into
slf4j's Manifest.MF files. This unifies the resulting MANIFEST.MFs
that are currently partly generated and partly statically defined and
fixes the following aspects:

- Fix the package-export of slf4j-jdk-platform-logging (from
'slf4j.jdk.platform.logging' to 'org.slf4j.jdk.platform.logging')
- Import missing packages for slf4j-reload4j and log4j-over-slf4j
- Replace the deprecated 'Bundle-RequiredExecutionEnvironment' by a
corresponding required 'osgi.ee' capability
- Restores the exported packages of jcl-over-slf4j

Fixes https://jira.qos.ch/browse/SLF4J-578

Signed-off-by: Hannes Wellmann <wellmann.hannes1@gmx.net>
2023-04-10 00:11:41 +02:00
Hannes Wellmann 661869eeb2 Adapt project names from 'Binding' to 'Provider'
Since slf4j 2 Bindings are now called Providers. The corresponding Maven
project names and descriptions should be adapted accordingly.

Signed-off-by: Hannes Wellmann <wellmann.hannes1@gmx.net>
2023-04-09 18:25:43 +02:00
Ceki Gulcu cff3312e43 start work on 2.0.8-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-03-17 20:41:07 +01:00
Ceki Gulcu d6a21ae68f update javadoc plugin to version 3.0.5
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-03-17 20:35:35 +01:00
Ceki Gulcu 13950e51a6 prepare release 2.0.7
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-03-17 19:49:13 +01:00
Ceki Gulcu 122e0c18dd add LICENSE.txt files to all modules, rename LICENSE as LICENSE.txt when appropriate
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2023-03-17 19:35:56 +01:00
TWI 2a8ca99caf add license file to jar 2023-03-17 19:25:44 +01:00
Hannes Wellmann b363bb31ed SLF4J-579: Export client packages of slf4j-api in version 1
Fixes https://jira.qos.ch/browse/SLF4J-576

This allows to use the slf4j-api version 2 artifact as drop-in
replacement for slf4j-api version 1 in OSGi environments as well.
slf4j-api can now be wired to bundles that require packages of slf4j-api
in version 1 or 2.

Signed-off-by: Hannes Wellmann <wellmann.hannes1@gmx.net>
2023-03-17 18:01:31 +01:00
Hannes Wellmann 2235d3c698
Fully automate OSGi metadata creation and fix brocken OSGi-metadata in slf4j-api (#330)
* Improve generated OSGi metadata and restore Bundle-SymbolicName

Enhance the generated OSGi metadata for all slf4j-modules in the
following ways:
- Restore the Bundle-SymbolicName, Bundle-Name, Bundle-Vendor and
Bundle-DocURL from SLF4J-2.0.5 and before
- Removes Export-Package: META-INF.versions.9
- Removes self-Imports of exported package (has to be added again in a
follow up, where desired)
- Remove unnecessary BND-internal headers

Additionally move the maven-bundle-plugin configuration from the
execution configuration up into the configuration of the plugin so that
it can be easier overwritten in child-modules.

Signed-off-by: Hannes Wellmann <wellmann.hannes1@gmx.net>

* Automate OSGi metadata creation and restore package-exports of slf4j-api

Only use the maven-bundle-plugin to generate all OSGi metadata into
slf4j-api's Manifest.MF file. This unifies the resulting MANIFEST.MFs
that are currently partly generated and partly statically defined.

Furthermore it fixes the following flaws in the currently generated OSGi
metadata of slf4j-api:
- Import only the exported org.slf4j.spi package (like in slf4j 2.0.5
and before)
- Replace the deprecated 'Bundle-RequiredExecutionEnvironment' header by
a corresponding required 'osgi.ee' capability

Signed-off-by: Hannes Wellmann <wellmann.hannes1@gmx.net>

---------

Signed-off-by: Hannes Wellmann <wellmann.hannes1@gmx.net>
2023-03-15 21:28:25 +01:00
Sean C. Sullivan a5540ad510 setup-java v3
Signed-off-by: Sean C. Sullivan <github@seansullivan.com>
2022-12-19 20:40:13 +01:00
Ceki Gulcu 1ed084cbc0 add missing distribution instruction to github action
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-12-19 20:25:11 +01:00
Ceki Gulcu b2cb017422 update github action versions
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-12-19 20:21:52 +01:00
Sean C. Sullivan fa6721a53e add JDK 19 to CI build
Signed-off-by: Sean C. Sullivan <github@seansullivan.com>
2022-12-19 20:19:54 +01:00
Ceki Gulcu f85104040c start work on 2.0.7-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-12-12 20:19:53 +01:00
Ceki Gulcu 5ff6f2c385 prepare for release 2.0.6
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-12-12 20:11:11 +01:00
Ceki Gulcu 2f4aa75445 fix SLF4J-575
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-12-10 19:30:48 +01:00
Ceki Gulcu 363f0a534e remove unused parts
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-12-10 00:38:56 +01:00
Jonah Graham 171679baa8 SLF4J-574: Add full OSGi headers, especially "uses" clauses
Fixes: https://jira.qos.ch/browse/SLF4J-574

This uses the BND tool, via org.apache.felix to generate
the MANIFEST.MF to be fully compliant with OSGi.
Compared to using just the maven-jar-plugin to create
the MANIFEST.MF the uses clauses are added to the
Export-Package

Signed-off-by: Jonah Graham <jonah@kichwacoders.com>
2022-12-10 00:10:39 +01:00
Ceki Gulcu 921b5b31e1 fix FUNDING file
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-12-09 13:31:52 +01:00
Ceki Gulcu e02244c39f fix FUNDING file
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-12-09 13:31:16 +01:00
Ceki Gulcu 441d4584be fix FUNDING file
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-12-09 13:30:56 +01:00
Ceki Gulcu f5e741ba1a add FUNDING file
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-12-09 13:30:01 +01:00
Ceki Gulcu 2e71327c8e remove unused log4j dependency in the version definition section of pom.xml
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-11-26 20:43:43 +01:00
Ceki Gulcu 3ff2a30e05 start work on 2.0.6-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-11-25 13:33:29 +01:00
Ceki Gulcu 7e62e1e691 prepare release 2.0.5
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-11-25 12:40:18 +01:00
Ceki Gulcu d250ad79eb in jcl-over-slf4j rename LICENSE.TXT as LICENSE, add LICENSE file to log4j-over-slf4j
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-11-25 09:56:46 +01:00
Ceki Gulcu 3bc58f3e81 add SecurityManager support
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-11-24 20:12:00 +01:00
Ceki Gulcu 207bb299c3 start work on 2.0.5-SNAPSHOT
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
2022-11-17 21:38:06 +01:00
103 changed files with 2570 additions and 1441 deletions

2
.github/FUNDING.yml vendored Normal file
View File

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

View File

@ -26,18 +26,19 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
jdk: [11, 17]
jdk: [11, 17, 19]
os: [ubuntu-latest, windows-latest, macos-latest]
fail-fast: true
max-parallel: 4
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 50
- name: Set up Java ${{ matrix.jdk }}
if: ${{ matrix.jdk != '8' }}
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: ${{ matrix.jdk }}
- name: Install
# download dependencies, etc, so test log looks better

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,8 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.4</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -18,7 +19,7 @@
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<name>Apache-2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
@ -27,7 +28,7 @@
<properties>
<module-name>org.apache.commons.logging</module-name>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
@ -39,5 +40,19 @@
<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

@ -1,9 +0,0 @@
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}

24
jul-to-slf4j/LICENSE.txt Normal file
View File

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

View File

@ -7,7 +7,8 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.4</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>jul-to-slf4j</artifactId>
@ -31,4 +32,9 @@
</dependency>
</dependencies>
<build>
<plugins>
</plugins>
</build>
</project>

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,8 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.4</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
@ -20,8 +21,8 @@
<licenses>
<license>
<name>Apache Software Licenses</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<name>Apache-2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
@ -41,4 +42,20 @@
</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

@ -1,13 +0,0 @@
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=${reload4j.version},
org.apache.log4j.helpers;version=${reload4j.version},
org.apache.log4j.spi;version=${reload4j.version},
org.apache.log4j.xml;version=${reload4j.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

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

View File

@ -7,7 +7,8 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.4</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>osgi-over-slf4j</artifactId>
@ -37,8 +38,27 @@
<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

@ -1,8 +0,0 @@
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}

397
parent/pom.xml Normal file
View File

@ -0,0 +1,397 @@
<?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>

536
pom.xml
View File

@ -5,80 +5,41 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.4</version>
<artifactId>slf4j-bom</artifactId>
<version>2.0.19-SNAPSHOT</version>
<packaging>pom</packaging>
<name>SLF4J</name>
<description>Top SLF4J project pom.xml file</description>
<url>http://www.slf4j.org</url>
<organization>
<name>QOS.ch</name>
<url>http://www.qos.ch</url>
</organization>
<inceptionYear>2005</inceptionYear>
<name>SLF4J BOM</name>
<description>SLF4J project BOM</description>
<licenses>
<license>
<name>MIT License</name>
<url>http://www.opensource.org/licenses/mit-license.php</url>
<name>MIT</name>
<url>https://opensource.org/license/mit</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<url>https://github.com/qos-ch/slf4j</url>
<connection>scm:git:https://github.com/qos-ch/slf4j.git</connection>
</scm>
</scm>
<properties>
<!-- yyyy-MM-dd'T'HH:mm:ss'Z' -->
<project.build.outputTimestamp>2022-11-17T20:03:00Z</project.build.outputTimestamp>
<latest.stable.version>1.7.36</latest.stable.version>
<latest.2.version>2.0.0-alpha7</latest.2.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>
<reload4j.version>1.2.22</reload4j.version>
<log4j.version>1.2.17</log4j.version>
<logback.version>1.2.10</logback.version>
<junit.version>4.13.1</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.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>
<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-reload4j</module>
<module>slf4j-ext</module>
<module>jcl-over-slf4j</module>
<module>log4j-over-slf4j</module>
@ -86,17 +47,11 @@
<module>osgi-over-slf4j</module>
<module>integration</module>
<module>slf4j-migrator</module>
</modules>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<central-publishing-maven-plugin.version>0.9.0</central-publishing-maven-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
@ -107,341 +62,183 @@
<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-simple</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
<version>${reload4j.version}</version>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.cal10n</groupId>
<artifactId>cal10n-api</artifactId>
<version>${cal10n.version}</version>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk-platform-logging</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-ext</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>osgi-over-slf4j</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<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-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>
<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>
<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>
<linkJavadoc>true</linkJavadoc>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version>
<version>3.6.3</version>
<configuration>
<linkJavadoc>true</linkJavadoc>
<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>
<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 packages</title>
<packages>org.slf4j:org.slf4j.*</packages>
<title>SLF4J API packages</title>
<packages>org.slf4j:org.slf4j.spi:org.slf4j.event:org.slf4j.helpers</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>Apache log4j</title>
<title>log4j-over-slf4j redirection</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>
</reporting>
</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>sign-artifacts</id>
@ -464,59 +261,6 @@
</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>
<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

@ -4,6 +4,10 @@
#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}
@ -42,8 +46,9 @@ echoRunAndCheck "$MVN install"
if [ ! -z "$PASS" ]
then
export GPG_TTY=$(tty)
echoRunAndCheck "$MVN deploy -P javadocjar,sign-artifacts"
# WARNING deploying without cleaning may leave stale MANIFEST files
export GPG_TTY=$(tty)
echoRunAndCheck "$MVN deploy -P javadocjar,sign-artifacts"
fi

View File

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

View File

@ -7,7 +7,8 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.4</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>slf4j-api</artifactId>
@ -52,6 +53,27 @@
</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

@ -25,7 +25,11 @@
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;
@ -39,28 +43,29 @@ import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.event.SubstituteLoggingEvent;
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.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, most notably for log4j, logback and JDK 1.4 logging.
* various logging APIs, e.g. logback, reload4j, log4j 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 bound with <code>LoggerFactory</code> at
* compile time.
*
*
* <p><code>LoggerFactory</code> is essentially a wrapper around an
* {@link ILoggerFactory} instance provided by a {@link SLF4JServiceProvider}.
*
* <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 {
@ -69,9 +74,7 @@ public final class LoggerFactory {
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";
@ -81,6 +84,16 @@ 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;
@ -101,11 +114,21 @@ public final class LoggerFactory {
// 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();
ServiceLoader<SLF4JServiceProvider> serviceLoader = ServiceLoader.load(SLF4JServiceProvider.class, classLoaderOfLoggerFactory);
List<SLF4JServiceProvider> providerList = new ArrayList<>();
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);
@ -113,12 +136,24 @@ public final class LoggerFactory {
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) {
Util.report("A SLF4J service provider failed to instantiate:\n" + e.getMessage());
Reporter.error("A service provider failed to instantiate:\n" + e.getMessage());
}
}
@ -126,8 +161,6 @@ public final class LoggerFactory {
* 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" };
@ -163,15 +196,16 @@ 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;
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.");
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.");
Set<URL> staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
reportIgnoredStaticLoggerBinders(staticLoggerBinderPathSet);
@ -183,16 +217,52 @@ 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;
}
Util.report("Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier.");
Reporter.warn("Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier.");
for (URL path : staticLoggerBinderPathSet) {
Util.report("Ignoring binding found at [" + path + "]");
Reporter.warn("Ignoring binding found at [" + path + "]");
}
Util.report("See " + IGNORED_BINDINGS_URL + " for an explanation.");
Reporter.warn("See " + IGNORED_BINDINGS_URL + " for an explanation.");
}
@ -218,7 +288,7 @@ public final class LoggerFactory {
staticLoggerBinderPathSet.add(path);
}
} catch (IOException ioe) {
Util.report("Error getting resources from path", ioe);
Reporter.error("Error getting resources from path", ioe);
}
return staticLoggerBinderPathSet;
}
@ -243,7 +313,7 @@ public final class LoggerFactory {
static void failedBinding(Throwable t) {
INITIALIZATION_STATE = FAILED_INITIALIZATION;
Util.report("Failed to instantiate SLF4J LoggerFactory", t);
Reporter.error("Failed to instantiate SLF4J LoggerFactory", t);
}
private static void replayEvents() {
@ -288,24 +358,26 @@ public final class LoggerFactory {
if (substLogger.isDelegateNOP()) {
// nothing to do
} else if (substLogger.isDelegateEventAware()) {
substLogger.log(event);
if(substLogger.isEnabledForLevel(event.getLevel())) {
substLogger.log(event);
}
} else {
Util.report(loggerName);
Reporter.warn(loggerName);
}
}
private static void emitSubstitutionWarning() {
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);
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);
}
private static void emitReplayWarning(int eventCount) {
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);
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);
}
private final static void versionSanityCheck() {
@ -319,18 +391,13 @@ public final class LoggerFactory {
}
}
if (!match) {
Util.report("The requested version " + requested + " by your slf4j binding is not compatible with "
Reporter.warn("The requested version " + requested + " by your slf4j provider is not compatible with "
+ Arrays.asList(API_COMPATIBILITY_LIST).toString());
Util.report("See " + VERSION_MISMATCH + " for further details.");
Reporter.warn("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
Util.report("Unexpected problem occured during version sanity check", e);
Reporter.error("Unexpected problem occurred during version sanity check", e);
}
}
@ -341,29 +408,36 @@ 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)) {
Util.report("Class path contains multiple SLF4J providers.");
Reporter.warn("Class path contains multiple SLF4J providers.");
for (SLF4JServiceProvider provider : providerList) {
Util.report("Found provider [" + provider + "]");
Reporter.warn("Found provider [" + provider + "]");
}
Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");
Reporter.warn("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");
}
}
private static void reportActualBinding(List<SLF4JServiceProvider> providerList) {
// binderPathSet can be null under Android
if (!providerList.isEmpty() && isAmbiguousProviderList(providerList)) {
Util.report("Actual provider is of type [" + providerList.get(0) + "]");
// 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() + "]");
}
}
/**
* 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
@ -376,7 +450,7 @@ 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
* caller as computed internally by SLF4J, a logger name mismatch warning
@ -384,12 +458,12 @@ public final class LoggerFactory {
* <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>
@ -399,9 +473,9 @@ public final class LoggerFactory {
if (DETECT_LOGGER_NAME_MISMATCH) {
Class<?> autoComputedCallingClass = Util.getCallingClass();
if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(),
Reporter.warn(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(),
autoComputedCallingClass.getName()));
Util.report("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation");
Reporter.warn("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation");
}
}
return logger;
@ -416,7 +490,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() {
@ -425,7 +499,7 @@ public final class LoggerFactory {
/**
* Return the {@link SLF4JServiceProvider} in use.
* @return provider in use
* @since 1.8.0
*/

View File

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

View File

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

View File

@ -1,5 +1,7 @@
package org.slf4j.event;
import java.util.Objects;
public class KeyValuePair {
public final String key;
@ -14,4 +16,17 @@ 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

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

View File

@ -291,7 +291,7 @@ final public class MessageFormatter {
String oAsString = o.toString();
sbuf.append(oAsString);
} catch (Throwable t) {
Util.report("SLF4J: Failed toString() invocation on an object of type [" + o.getClass().getName() + "]", t);
Reporter.error("Failed toString() invocation on an object of type [" + o.getClass().getName() + "]", t);
sbuf.append("[FAILED toString()]");
}

View File

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

@ -0,0 +1,73 @@
/*
* Copyright (c) 2004-2024 QOS.ch
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.slf4j.helpers;
/**
* Various utility methods
*
* @since 2.0.14
*/
public class Slf4jEnvUtil {
/**
* Returns the current version of slf4j, or null if data is not available.
*
* @return current version or null if missing version data
* @since 2.0.14
*/
static public String slf4jVersion() {
// String moduleVersion = slf4jVersionByModule();
// if(moduleVersion != null)
// return moduleVersion;
Package pkg = Slf4jEnvUtil.class.getPackage();
if(pkg == null) {
return null;
}
final String pkgVersion = pkg.getImplementationVersion();
return pkgVersion;
}
/**
* Returns the current version of slf4j via class.getModule()
* or null if data is not available.
*
* @return current version or null if missing version data
* @since 2.0.14
*/
// static private String slf4jVersionByModule() {
// Module module = Slf4jEnvUtil.class.getModule();
// if (module == null)
// return null;
//
// ModuleDescriptor md = module.getDescriptor();
// if (md == null)
// return null;
// Optional<String> opt = md.rawVersion();
// return opt.orElse(null);
// }
}

View File

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

View File

@ -117,12 +117,26 @@ 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,7 +1,7 @@
/**
* Copyright (c) 2004-2022 QOS.ch
* All rights reserved.
*
* <p>
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
@ -9,10 +9,10 @@
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* <p>
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* <p>
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -20,10 +20,10 @@
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package org.slf4j.spi;
import java.util.List;
import java.util.function.Supplier;
import org.slf4j.Logger;
@ -38,11 +38,11 @@ import org.slf4j.event.LoggingEvent;
*/
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 +53,7 @@ public class DefaultLoggingEventBuilder implements LoggingEventBuilder, CallerBo
/**
* Add a marker to the current logging event being built.
*
* <p>
* It is possible to add multiple markers to the same logging event.
*
* @param marker the marker to add
@ -72,165 +72,16 @@ public class DefaultLoggingEventBuilder implements LoggingEventBuilder, CallerBo
@Override
public LoggingEventBuilder addArgument(Object p) {
loggingEvent.addArgument(p);
this.loggingEvent.addArgument(p);
return this;
}
@Override
public LoggingEventBuilder addArgument(Supplier<?> objectSupplier) {
loggingEvent.addArgument(objectSupplier.get());
this.loggingEvent.addArgument(objectSupplier.get());
return this;
}
@Override
public void setCallerBoundary(String fqcn) {
loggingEvent.setCallerBoundary(fqcn);
}
@Override
public void log() {
log(loggingEvent);
}
@Override
public LoggingEventBuilder setMessage(String message) {
loggingEvent.setMessage(message);
return this;
}
@Override
public LoggingEventBuilder setMessage(Supplier<String> messageSupplier) {
loggingEvent.setMessage(messageSupplier.get());
return this;
}
@Override
public void log(String message) {
loggingEvent.setMessage(message);
log(loggingEvent);
}
@Override
public void log(String message, Object arg) {
loggingEvent.setMessage(message);
loggingEvent.addArgument(arg);
log(loggingEvent);
}
@Override
public void log(String message, Object arg0, Object arg1) {
loggingEvent.setMessage(message);
loggingEvent.addArgument(arg0);
loggingEvent.addArgument(arg1);
log(loggingEvent);
}
@Override
public void log(String message, Object... args) {
loggingEvent.setMessage(message);
loggingEvent.addArguments(args);
log(loggingEvent);
}
@Override
public void log(Supplier<String> messageSupplier) {
if (messageSupplier == null) {
log((String) null);
} else {
log(messageSupplier.get());
}
}
protected void log(LoggingEvent aLoggingEvent) {
setCallerBoundary(DLEB_FQCN);
if (logger instanceof LoggingEventAware) {
((LoggingEventAware) logger).log(aLoggingEvent);
} else {
logViaPublicSLF4JLoggerAPI(aLoggingEvent);
}
}
private void logViaPublicSLF4JLoggerAPI(LoggingEvent aLoggingEvent) {
Object[] argArray = aLoggingEvent.getArgumentArray();
int argLen = argArray == null ? 0 : argArray.length;
Throwable t = aLoggingEvent.getThrowable();
int tLen = t == null ? 0 : 1;
String msg = aLoggingEvent.getMessage();
Object[] combinedArguments = new Object[argLen + tLen];
if (argArray != null) {
System.arraycopy(argArray, 0, combinedArguments, 0, argLen);
}
if (t != null) {
combinedArguments[argLen] = t;
}
msg = mergeMarkersAndKeyValuePairs(aLoggingEvent, msg);
switch (aLoggingEvent.getLevel()) {
case TRACE:
logger.trace(msg, combinedArguments);
break;
case DEBUG:
logger.debug(msg, combinedArguments);
break;
case INFO:
logger.info(msg, combinedArguments);
break;
case WARN:
logger.warn(msg, combinedArguments);
break;
case ERROR:
logger.error(msg, combinedArguments);
break;
}
}
/**
* Prepend markers and key-value pairs to the message.
*
* @param aLoggingEvent
* @param msg
* @return
*/
private String mergeMarkersAndKeyValuePairs(LoggingEvent aLoggingEvent, String msg) {
StringBuilder sb = null;
if (aLoggingEvent.getMarkers() != null) {
sb = new StringBuilder();
for (Marker marker : aLoggingEvent.getMarkers()) {
sb.append(marker);
sb.append(' ');
}
}
if (aLoggingEvent.getKeyValuePairs() != null) {
if (sb == null) {
sb = new StringBuilder();
}
for (KeyValuePair kvp : aLoggingEvent.getKeyValuePairs()) {
sb.append(kvp.key);
sb.append('=');
sb.append(kvp.value);
sb.append(' ');
}
}
if (sb != null) {
sb.append(msg);
return sb.toString();
} else {
return msg;
}
}
@Override
public LoggingEventBuilder addKeyValue(String key, Object value) {
loggingEvent.addKeyValue(key, value);
@ -243,4 +94,184 @@ public class DefaultLoggingEventBuilder implements LoggingEventBuilder, CallerBo
return this;
}
@Override
public void setCallerBoundary(String fqcn) {
this.loggingEvent.setCallerBoundary(fqcn);
}
@Override
public void log() {
log(this.loggingEvent);
}
@Override
public LoggingEventBuilder setMessage(String message) {
this.loggingEvent.setMessage(message);
return this;
}
@Override
public LoggingEventBuilder setMessage(Supplier<String> messageSupplier) {
this.loggingEvent.setMessage(messageSupplier.get());
return this;
}
@Override
public void log(String message) {
this.loggingEvent.setMessage(message);
log(this.loggingEvent);
}
@Override
public void log(String message, Object arg) {
this.loggingEvent.setMessage(message);
this.loggingEvent.addArgument(arg);
log(this.loggingEvent);
}
@Override
public void log(String message, Object arg0, Object arg1) {
this.loggingEvent.setMessage(message);
this.loggingEvent.addArgument(arg0);
this.loggingEvent.addArgument(arg1);
log(this.loggingEvent);
}
@Override
public void log(String message, Object... args) {
this.loggingEvent.setMessage(message);
this.loggingEvent.addArguments(args);
log(this.loggingEvent);
}
@Override
public void log(Supplier<String> messageSupplier) {
if(messageSupplier == null) {
log((String) null);
} else {
log(messageSupplier.get());
}
}
protected void log(LoggingEvent aLoggingEvent) {
if(aLoggingEvent.getCallerBoundary() == null) {
setCallerBoundary(DLEB_FQCN);
}
if(logger instanceof LoggingEventAware) {
((LoggingEventAware) logger).log(aLoggingEvent);
} else if(logger instanceof LocationAwareLogger) {
logViaLocationAwareLoggerAPI((LocationAwareLogger) logger, aLoggingEvent);
} else {
logViaPublicSLF4JLoggerAPI(aLoggingEvent);
}
}
private void logViaLocationAwareLoggerAPI(LocationAwareLogger locationAwareLogger, LoggingEvent aLoggingEvent) {
List<Marker> markerList = aLoggingEvent.getMarkers();
Marker firstMarker = (markerList != null && !markerList.isEmpty()) ? markerList.get(0) : null;
String mergedMessage = mergeMarkersAndKeyValuePairsAndMessage(aLoggingEvent);
locationAwareLogger.log(firstMarker, aLoggingEvent.getCallerBoundary(), aLoggingEvent.getLevel().toInt(),
mergedMessage,
aLoggingEvent.getArgumentArray(), aLoggingEvent.getThrowable());
}
private void logViaPublicSLF4JLoggerAPI(LoggingEvent aLoggingEvent) {
Object[] argArray = aLoggingEvent.getArgumentArray();
int argLen = argArray == null ? 0 : argArray.length;
Throwable t = aLoggingEvent.getThrowable();
int tLen = t == null ? 0 : 1;
Object[] combinedArguments = new Object[argLen + tLen];
if(argArray != null) {
System.arraycopy(argArray, 0, combinedArguments, 0, argLen);
}
if(t != null) {
combinedArguments[argLen] = t;
}
String mergedMessage = mergeMarkersAndKeyValuePairsAndMessage(aLoggingEvent);
switch(aLoggingEvent.getLevel()) {
case TRACE:
logger.trace(mergedMessage, combinedArguments);
break;
case DEBUG:
logger.debug(mergedMessage, combinedArguments);
break;
case INFO:
logger.info(mergedMessage, combinedArguments);
break;
case WARN:
logger.warn(mergedMessage, combinedArguments);
break;
case ERROR:
logger.error(mergedMessage, combinedArguments);
break;
}
}
/**
* Prepend markers and key-value pairs to the message.
*
* @param aLoggingEvent
*
* @return
*/
private String mergeMarkersAndKeyValuePairsAndMessage(LoggingEvent aLoggingEvent) {
StringBuilder sb = mergeMarkers(aLoggingEvent.getMarkers(), null);
sb = mergeKeyValuePairs(aLoggingEvent.getKeyValuePairs(), sb);
final String mergedMessage = mergeMessage(aLoggingEvent.getMessage(), sb);
return mergedMessage;
}
private StringBuilder mergeMarkers(List<Marker> markerList, StringBuilder sb) {
if(markerList == null || markerList.isEmpty())
return sb;
if(sb == null)
sb = new StringBuilder();
for(Marker marker : markerList) {
sb.append(marker);
sb.append(' ');
}
return sb;
}
private StringBuilder mergeKeyValuePairs(List<KeyValuePair> keyValuePairList, StringBuilder sb) {
if(keyValuePairList == null || keyValuePairList.isEmpty())
return sb;
if(sb == null)
sb = new StringBuilder();
for(KeyValuePair kvp : keyValuePairList) {
sb.append(kvp.key);
sb.append('=');
sb.append(kvp.value);
sb.append(' ');
}
return sb;
}
private String mergeMessage(String msg, StringBuilder sb) {
if(sb != null) {
sb.append(msg);
return sb.toString();
} else {
return msg;
}
}
}

View File

@ -4,7 +4,17 @@ 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
*/

View File

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

View File

@ -1,15 +0,0 @@
Implementation-Title: slf4j-api
Bundle-ManifestVersion: 2
Bundle-SymbolicName: slf4j.api
Bundle-Name: slf4j-api
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.slf4j;version=${parsedVersion.osgiVersion},
org.slf4j.spi;version=${parsedVersion.osgiVersion},
org.slf4j.helpers;version=${parsedVersion.osgiVersion},
org.slf4j.event;version=${parsedVersion.osgiVersion}
Import-Package: org.slf4j.spi;version=${parsedVersion.osgiVersion}
Require-Capability: osgi.extender;filter:="(&(osgi.extender=osgi.servi
celoader.processor)(version>=1.0.0)(!(version>=2.0.0)))",osgi.service
loader;filter:="(osgi.serviceloader=org.slf4j.spi.SLF4JServiceProvide
r)";osgi.serviceloader="org.slf4j.spi.SLF4JServiceProvider"

View File

@ -0,0 +1,91 @@
package org.slf4j;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.spi.MDCAdapter;
import org.slf4j.spi.SLF4JServiceProvider;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;
public class LoggerFactoryTest {
private PrintStream rawSyserr;
private ByteArrayOutputStream mockedSyserr;
final ClassLoader classLoaderOfLoggerFactory = LoggerFactory.class.getClassLoader();
@Before
public void setUp() {
rawSyserr = System.err;
mockedSyserr = new ByteArrayOutputStream();
System.setErr(new PrintStream(mockedSyserr));
}
@After
public void cleanUp() {
System.clearProperty(LoggerFactory.PROVIDER_PROPERTY_KEY);
System.setErr(rawSyserr);
}
@Test
public void testExplicitlySpecified() {
System.setProperty(LoggerFactory.PROVIDER_PROPERTY_KEY, "org.slf4j.LoggerFactoryTest$TestingProvider");
SLF4JServiceProvider provider = LoggerFactory.loadExplicitlySpecified(classLoaderOfLoggerFactory);
assertTrue("provider should be instance of TestingProvider class", provider instanceof TestingProvider);
assertTrue(mockedSyserr.toString().contains(" Attempting to load provider \"org.slf4j.LoggerFactoryTest$TestingProvider\" specified via \"slf4j.provider\" system property"));
System.out.println(mockedSyserr.toString());
}
@Test
public void testExplicitlySpecifiedNull() {
assertNull(LoggerFactory.loadExplicitlySpecified(classLoaderOfLoggerFactory));
}
@Test
public void testExplicitlySpecifyMissingServiceProvider() {
System.setProperty(LoggerFactory.PROVIDER_PROPERTY_KEY, "com.example.ServiceProvider");
SLF4JServiceProvider provider = LoggerFactory.loadExplicitlySpecified(classLoaderOfLoggerFactory);
assertNull(provider);
assertTrue(mockedSyserr.toString().contains("Failed to instantiate the specified SLF4JServiceProvider (com.example.ServiceProvider)"));
}
@Test
public void testExplicitlySpecifyNonServiceProvider() {
System.setProperty(LoggerFactory.PROVIDER_PROPERTY_KEY, "java.lang.String");
assertNull(LoggerFactory.loadExplicitlySpecified(classLoaderOfLoggerFactory));
assertTrue(mockedSyserr.toString().contains("Specified SLF4JServiceProvider (java.lang.String) does not implement SLF4JServiceProvider interface"));
}
public static class TestingProvider implements SLF4JServiceProvider {
@Override
public ILoggerFactory getLoggerFactory() {
return null;
}
@Override
public IMarkerFactory getMarkerFactory() {
return null;
}
@Override
public MDCAdapter getMDCAdapter() {
return null;
}
@Override
public String getRequestedApiVersion() {
return null;
}
@Override
public void initialize() {
}
}
}

View File

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

View File

@ -36,16 +36,15 @@ abstract public class MultithreadedInitializationTest {
assertAllSubstLoggersAreFixed();
long recordedEventCount = getRecordedEventCount();
int LENIENCY_COUNT = 21;
int LENIENCY_COUNT = 30;
long expectedEventCount = eventCount.get() + extraLogEvents();
assertTrue(expectedEventCount + " >= " + recordedEventCount, expectedEventCount >= recordedEventCount);
assertTrue(expectedEventCount + " < " + recordedEventCount + "+" + LENIENCY_COUNT, expectedEventCount < recordedEventCount + LENIENCY_COUNT);
}
assertTrue("unmet condition: " + expectedEventCount + " >= " + recordedEventCount, expectedEventCount >= recordedEventCount);
assertTrue("unmet condition: " + expectedEventCount + " < " + recordedEventCount + "+" + LENIENCY_COUNT, expectedEventCount < (recordedEventCount + LENIENCY_COUNT)); }
abstract protected long getRecordedEventCount();
protected int extraLogEvents() {
return 0;
}

24
slf4j-ext/LICENSE.txt Normal file
View File

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

View File

@ -7,7 +7,8 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.4</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>slf4j-ext</artifactId>
@ -73,8 +74,19 @@
</archive>
</configuration>
</plugin>
</plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Import-Package>ch.qos.cal10n;version="${cal10n.version}";resolution:="optional", org.slf4j, org.slf4j.*</Import-Package>
<_exportcontents>org.slf4j.ext, org.slf4j.profiler, org.slf4j.cal10n</_exportcontents>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,8 +0,0 @@
Implementation-Title: slf4j-ext
Bundle-ManifestVersion: 2
Bundle-SymbolicName: slf4j.ext
Bundle-Name: slf4j-ext
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.slf4j.profiler;version=${parsedVersion.osgiVersion}, org.slf4j.cal10n;version=${parsedVersion.osgiVersion}, org.slf4j.ext;version=${parsedVersion.osgiVersion}
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion}, org.slf4j.spi;version=${parsedVersion.osgiVersion}, org.slf4j.helpers;version=${parsedVersion.osgiVersion}, ch.qos.cal10n;version=${cal10n.version};resolution:=optional

View File

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

View File

@ -8,7 +8,8 @@
<parent>
<artifactId>slf4j-parent</artifactId>
<groupId>org.slf4j</groupId>
<version>2.0.4</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>slf4j-jdk-platform-logging</artifactId>

View File

@ -26,10 +26,12 @@ package org.slf4j.jdk.platform.logging;
import static java.util.Objects.requireNonNull;
import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.slf4j.Logger;
import org.slf4j.helpers.Reporter;
import org.slf4j.spi.CallerBoundaryAware;
import org.slf4j.spi.LoggingEventBuilder;
@ -113,16 +115,11 @@ class SLF4JPlatformLogger implements System.Logger {
* @param thrown
* @param params
*/
private void log(Level jplLevel, ResourceBundle bundle, String msg, Throwable thrown, Object... params) {
if (jplLevel == Level.OFF)
return;
private void log(final Level jplLevel, final ResourceBundle bundle, final String msg, final Throwable thrown, final Object... params) {
if (jplLevel == Level.ALL) {
performLog(org.slf4j.event.Level.TRACE, bundle, msg, thrown, params);
return;
}
final Level jplLevelReduced = fixExtremeLevels(jplLevel);
org.slf4j.event.Level slf4jLevel = jplLevelToSLF4JLevel(jplLevel);
org.slf4j.event.Level slf4jLevel = jplLevelToSLF4JLevel(jplLevelReduced);
boolean isEnabled = slf4jLogger.isEnabledForLevel(slf4jLevel);
if (isEnabled) {
@ -130,6 +127,27 @@ class SLF4JPlatformLogger implements System.Logger {
}
}
/**
* <p>Level.OFF and Level.ALL levels are not supposed to be used when calling log printing methods.
* </p>
*
* <p>We compensate for such incorrect usage by transforming Level.OFF as Level.ERROR and
* Level.ALL as Level.TRACE.
* </p>
*
* @param jplLevel
* @return
*/
private Level fixExtremeLevels(Level jplLevel) {
if (jplLevel == Level.OFF)
return Level.ERROR;
if (jplLevel == Level.ALL)
return Level.TRACE;
return jplLevel;
}
private void performLog(org.slf4j.event.Level slf4jLevel, ResourceBundle bundle, String msg, Throwable thrown, Object... params) {
String message = getResourceStringOrMessage(bundle, msg);
LoggingEventBuilder leb = slf4jLogger.makeLoggingEventBuilder(slf4jLevel);
@ -142,7 +160,7 @@ class SLF4JPlatformLogger implements System.Logger {
leb = leb.addArgument(p);
}
// The JDK uses a different formatting convention. We must invoke it now.
message = String.format(message, params);
message = MessageFormat.format(message, params);
}
if (leb instanceof CallerBoundaryAware) {
CallerBoundaryAware cba = (CallerBoundaryAware) leb;
@ -154,7 +172,7 @@ class SLF4JPlatformLogger implements System.Logger {
private void reportUnknownLevel(Level jplLevel) {
String message = "Unknown log level [" + jplLevel + "]";
IllegalArgumentException iae = new IllegalArgumentException(message);
org.slf4j.helpers.Util.report("Unsupported log level", iae);
Reporter.error("Unsupported log level", iae);
}
private static String getResourceStringOrMessage(ResourceBundle bundle, String msg) {

View File

@ -37,7 +37,7 @@ import org.slf4j.LoggerFactory;
* @author Ceki
*
*/
public class SLF4JPlarformLoggerFactory {
public class SLF4JPlatformLoggerFactory {
ConcurrentMap<String, SLF4JPlatformLogger> loggerMap = new ConcurrentHashMap<>();
/**

View File

@ -25,14 +25,14 @@
package org.slf4j.jdk.platform.logging;
/**
* Uses {@link SLF4JPlarformLoggerFactory#getLogger(String)} to get a logger
* Uses {@link SLF4JPlatformLoggerFactory#getLogger(String)} to get a logger
* that is adapted for {@link System.Logger}.
*
* @since 2.0.0
*/
public class SLF4JSystemLoggerFinder extends System.LoggerFinder {
final SLF4JPlarformLoggerFactory platformLoggerFactory = new SLF4JPlarformLoggerFactory();
final SLF4JPlatformLoggerFactory platformLoggerFactory = new SLF4JPlatformLoggerFactory();
@Override
public System.Logger getLogger(String name, Module module) {

View File

@ -1,9 +0,0 @@
Implementation-Title: slf4j-jdk-platform-logging
Bundle-ManifestVersion: 2
Bundle-SymbolicName: slf4j.jdk.platform.logging
Bundle-Name: slf4j-jdk-platform-logging
Bundle-Vendor: SLF4J.ORG
Require-Bundle: slf4j.api
Bundle-RequiredExecutionEnvironment: JavaSE-9
Export-Package: slf4j.jdk.platform.logging;version=${parsedVersion.osgiVersion}
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion}

View File

@ -39,6 +39,7 @@ import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.LoggerFactory;
/**
* The present test is fragile in the sense that it sets up SimpleLogger
@ -88,7 +89,7 @@ public class SLF4JPlatformLoggingTest {
assertEquals(EXPECTED_FINDER_CLASS, finder.getClass().getName());
Logger systemLogger = finder.getLogger("smoke", null);
systemLogger.log(Level.INFO, "hello");
systemLogger.log(Level.INFO, "hello %s", "world");
systemLogger.log(Level.INFO, "hello {0}", "world");
List<String> results = SPS.stringList;
assertEquals(2, results.size());
@ -108,12 +109,27 @@ public class SLF4JPlatformLoggingTest {
//INFO throwTest - a problem
//java.lang.Exception
// at org.slf4j.jdk.platform.logging/org.slf4j.jdk.platform.logging.SLF4JPlatformLoggingTest.throwTest(SLF4JPlatformLoggingTest.java:92)
assertEquals("INFO throwTest - we have a problem", results.get(0));
assertEquals(Exception.class.getName(), results.get(1));
assertTrue(results.get(2).contains("at "));
assertTrue(results.get(2).contains(this.getClass().getName()));
int line = 0;
//assertTrue(results.get(0).startsWith("SLF4J(I): Connected with provider of type ["));
assertEquals("INFO throwTest - we have a problem", results.get(line++));
assertEquals(Exception.class.getName(), results.get(line++));
assertTrue(results.get(line).contains("at "));
assertTrue(results.get(line++).contains(this.getClass().getName()));
}
@Test
public void extremeLevels() throws IOException {
LoggerFinder finder = System.LoggerFinder.getLoggerFinder();
assertEquals(EXPECTED_FINDER_CLASS, finder.getClass().getName());
Logger systemLogger = finder.getLogger("extremeLevels", null);
systemLogger.log(Level.OFF, "hello");
systemLogger.log(Level.ALL, "world");
List<String> results = SPS.stringList;
assertEquals(1, results.size());
assertEquals("ERROR extremeLevels - hello", results.get(0));
}
}

View File

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

View File

@ -7,17 +7,20 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.4</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>slf4j-jdk14</artifactId>
<packaging>jar</packaging>
<name>SLF4J JDK14 Binding</name>
<description>SLF4J JDK14 Binding</description>
<name>SLF4J JDK14 Provider</name>
<description>SLF4J JDK14 Provider</description>
<url>http://www.slf4j.org</url>
<properties>
<module-name>org.slf4j.jul</module-name>
<slf4j.provider.implementation>org.slf4j.jul.JULServiceProvider</slf4j.provider.implementation>
<slf4j.provider.type>jul</slf4j.provider.type>
</properties>
<dependencies>

View File

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

View File

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

View File

@ -2,5 +2,8 @@ module org.slf4j.jul {
requires org.slf4j;
requires java.logging;
provides org.slf4j.spi.SLF4JServiceProvider with org.slf4j.jul.JULServiceProvider;
exports org.slf4j.jul;
opens org.slf4j.jul to org.slf4j;
}

View File

@ -1,17 +0,0 @@
Implementation-Title: slf4j-jdk14
Bundle-ManifestVersion: 2
Bundle-SymbolicName: slf4j.jdk14
Bundle-Name: slf4j-jdk14
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.slf4j.jul;version=${parsedVersion.osgiVersion}
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion},
org.slf4j.spi;version=${parsedVersion.osgiVersion},
org.slf4j.helpers;version=${parsedVersion.osgiVersion},
org.slf4j.event;version=${parsedVersion.osgiVersion}
Provide-Capability: osgi.service;objectClass:List<String>="org.slf4j.s
pi.SLF4JServiceProvider";type=jul;effective:=active,osgi.serviceloade
r;osgi.serviceloader="org.slf4j.spi.SLF4JServiceProvider";register:="
org.slf4j.jul.JULServiceProvider";type=jul
Require-Capability: osgi.extender;filter:="(&(osgi.extender=osgi.servi
celoader.registrar)(version>=1.0.0)(!(version>=2.0.0)))"

View File

@ -19,6 +19,8 @@ import org.slf4j.event.SubstituteLoggingEvent;
import org.slf4j.helpers.SubstituteLogger;
import org.slf4j.helpers.SubstituteServiceProvider;
import org.slf4j.jul.ListHandler;
import org.slf4j.spi.CallerBoundaryAware;
import org.slf4j.spi.LoggingEventBuilder;
public class CallerInfoTest {
Level oldLevel;
@ -77,6 +79,22 @@ public class CallerInfoTest {
assertEquals(this.getClass().getName(), logRecod.getSourceClassName());
}
@Test
public void testCallerInfoWithFluentAPIAndAWrapper() {
Logger logger = LoggerFactory.getLogger("bla");
LoggingWrapper wrappedLogger = new LoggingWrapper(logger);
wrappedLogger.logWithEvent("hello");
List<LogRecord> recordList = listHandler.recordList;
assertEquals(1, recordList.size());
LogRecord logRecod = recordList.get(0);
assertEquals(this.getClass().getName(), logRecod.getSourceClassName());
}
@Test
public void testPostInitializationCallerInfoWithSubstituteLogger() {
Logger logger = LoggerFactory.getLogger("bla");
@ -119,4 +137,22 @@ public class CallerInfoTest {
assertEquals(EventConstants.NA_SUBST, logRecod.getSourceClassName());
}
static class LoggingWrapper {
Logger underlyingLogger;
LoggingWrapper(Logger aLogger) {
this.underlyingLogger = aLogger;
}
public void logWithEvent(String msg) {
LoggingEventBuilder lev = underlyingLogger.atInfo();
// setting the caller boundary to LoggingWrapper
if(lev instanceof CallerBoundaryAware) {
// builder is CallerBoundaryAware
((CallerBoundaryAware) lev).setCallerBoundary(LoggingWrapper.class.getName());
}
lev.log(msg);
}
}
}

View File

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

View File

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

View File

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

View File

@ -7,7 +7,8 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.4</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>slf4j-migrator</artifactId>
@ -16,4 +17,23 @@
<name>SLF4J Migrator</name>
<description>SLF4J Migrator</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<configuration>
<archive>
<manifest>
<mainClass>org.slf4j.migrator.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1 +0,0 @@
Main-Class: org.slf4j.migrator.Main

View File

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

View File

@ -7,18 +7,21 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.4</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>slf4j-nop</artifactId>
<packaging>jar</packaging>
<name>SLF4J NOP Binding</name>
<description>SLF4J NOP Binding</description>
<name>SLF4J NOP Provider</name>
<description>SLF4J NOP Provider</description>
<url>http://www.slf4j.org</url>
<properties>
<module-name>org.slf4j.nop</module-name>
<slf4j.provider.implementation>org.slf4j.nop.NOPServiceProvider</slf4j.provider.implementation>
<slf4j.provider.type>nop</slf4j.provider.type>
</properties>
<dependencies>
@ -26,6 +29,14 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<type>test-jar</type>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -18,9 +18,18 @@ public class NOPServiceProvider implements SLF4JServiceProvider {
public static String REQUESTED_API_VERSION = "2.0.99"; // !final
private final ILoggerFactory loggerFactory = new NOPLoggerFactory();
private final IMarkerFactory markerFactory = new BasicMarkerFactory();
private final MDCAdapter mdcAdapter = new NOPMDCAdapter();
// LoggerFactory expects providers to initialize markerFactory as early as possible.
private final IMarkerFactory markerFactory;
// LoggerFactory expects providers to initialize their MDCAdapter field
// as early as possible, preferably at construction time.
private final MDCAdapter mdcAdapter;
public NOPServiceProvider() {
markerFactory = new BasicMarkerFactory();
mdcAdapter = new NOPMDCAdapter();
}
public ILoggerFactory getLoggerFactory() {
return loggerFactory;
}
@ -39,7 +48,6 @@ public class NOPServiceProvider implements SLF4JServiceProvider {
}
public void initialize() {
}

View File

@ -1,4 +1,7 @@
module org.slf4j.nop {
requires org.slf4j;
provides org.slf4j.spi.SLF4JServiceProvider with org.slf4j.nop.NOPServiceProvider;
exports org.slf4j.nop;
opens org.slf4j.nop to org.slf4j;
}

View File

@ -1,17 +0,0 @@
Implementation-Title: slf4j-nop
Bundle-ManifestVersion: 2
Bundle-SymbolicName: slf4j.nop
Bundle-Name: slf4j-nop
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.slf4j.nop;version=${parsedVersion.osgiVersion}
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion},
org.slf4j.spi;version=${parsedVersion.osgiVersion},
org.slf4j.helpers;version=${parsedVersion.osgiVersion},
org.slf4j.event;version=${parsedVersion.osgiVersion}
Provide-Capability: osgi.service;objectClass:List<String>="org.slf4j.s
pi.SLF4JServiceProvider";type=nop;effective:=active,osgi.serviceloade
r;osgi.serviceloader="org.slf4j.spi.SLF4JServiceProvider";register:="
org.slf4j.nop.NOPServiceProvider";type=nop
Require-Capability: osgi.extender;filter:="(&(osgi.extender=osgi.servi
celoader.registrar)(version>=1.0.0)(!(version>=2.0.0)))"

View File

@ -1,7 +1,7 @@
/**
* Copyright (c) 2004-2016 QOS.ch
* All rights reserved.
*
* <p>
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
@ -9,10 +9,10 @@
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* <p>
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* <p>
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -20,29 +20,29 @@
* 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.nop;
import static org.junit.Assert.assertEquals;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.LoggerFactoryFriend;
import org.slf4j.helpers.StringPrintStream;
import java.io.PrintStream;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicLong;
import static org.junit.Assert.assertEquals;
import static org.slf4j.helpers.Reporter.SLF4J_INTERNAL_VERBOSITY_KEY;
public class MultithreadedInitializationTest {
static int NUM_LINES_IN_SLF4J_CONNECTED_WITH_PROVIDER_INFO = 1;
final static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2;
private static final AtomicLong EVENT_COUNT = new AtomicLong(0);
@ -52,16 +52,18 @@ public class MultithreadedInitializationTest {
int diff = new Random().nextInt(10000);
String loggerName = "org.slf4j.impl.MultithreadedInitializationTest";
private final PrintStream oldErr = System.err;
StringPrintStream sps = new StringPrintStream(oldErr);
StringPrintStream sps = new StringPrintStream(oldErr, false);
@Before
public void setup() {
System.setProperty(SLF4J_INTERNAL_VERBOSITY_KEY, "debug");
LoggerFactoryFriend.reset();
System.setErr(sps);
}
@After
public void tearDown() throws Exception {
System.clearProperty(SLF4J_INTERNAL_VERBOSITY_KEY);
LoggerFactoryFriend.reset();
System.setErr(oldErr);
}
@ -71,7 +73,7 @@ public class MultithreadedInitializationTest {
System.out.println("THREAD_COUNT=" + THREAD_COUNT);
LoggerAccessingThread[] accessors = harness();
for (LoggerAccessingThread accessor : accessors) {
for(LoggerAccessingThread accessor : accessors) {
EVENT_COUNT.getAndIncrement();
accessor.logger.info("post harness");
}
@ -80,19 +82,19 @@ public class MultithreadedInitializationTest {
logger.info("hello");
EVENT_COUNT.getAndIncrement();
assertEquals(0, sps.stringList.size());
assertEquals(NUM_LINES_IN_SLF4J_CONNECTED_WITH_PROVIDER_INFO, sps.stringList.size());
}
private static LoggerAccessingThread[] harness() throws InterruptedException, BrokenBarrierException {
LoggerAccessingThread[] threads = new LoggerAccessingThread[THREAD_COUNT];
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
for (int i = 0; i < THREAD_COUNT; i++) {
for(int i = 0; i < THREAD_COUNT; i++) {
threads[i] = new LoggerAccessingThread(barrier, i);
threads[i].start();
}
barrier.await();
for (int i = 0; i < THREAD_COUNT; i++) {
for(int i = 0; i < THREAD_COUNT; i++) {
threads[i].join();
}
return threads;
@ -118,33 +120,35 @@ public class MultithreadedInitializationTest {
logger.info("in run method");
EVENT_COUNT.getAndIncrement();
}
};
}
public static class StringPrintStream extends PrintStream {
;
public static final String LINE_SEP = System.getProperty("line.separator");
PrintStream other;
List<String> stringList = new ArrayList<>();
public StringPrintStream(PrintStream ps) {
super(ps);
other = ps;
}
public void print(String s) {
other.print(s);
stringList.add(s);
}
public void println(String s) {
other.println(s);
stringList.add(s);
}
public void println(Object o) {
other.println(o);
stringList.add(o.toString());
}
};
// public static class StringPrintStream extends PrintStream {
//
// public static final String LINE_SEP = System.getProperty("line.separator");
// PrintStream other;
// List<String> stringList = new ArrayList<>();
//
// public StringPrintStream(PrintStream ps) {
// super(ps);
// other = ps;
// }
//
// public void print(String s) {
// other.print(s);
// stringList.add(s);
// }
//
// public void println(String s) {
// other.println(s);
// stringList.add(s);
// }
//
// public void println(Object o) {
// other.println(o);
// stringList.add(o.toString());
// }
// };
}

View File

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

View File

@ -7,18 +7,23 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.4</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>slf4j-reload4j</artifactId>
<packaging>jar</packaging>
<name>SLF4J Reload4j Binding</name>
<description>SLF4J Reload4j Binding</description>
<name>SLF4J Reload4j Provider</name>
<description>SLF4J Reload4j Provider</description>
<url>http://reload4j.qos.ch</url>
<properties>
<slf4j.provider.implementation>org.slf4j.reload4j.Reload4jServiceProvider</slf4j.provider.implementation>
<slf4j.provider.type>reload4j</slf4j.provider.type>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
@ -29,7 +34,7 @@
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
@ -42,11 +47,10 @@
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
@ -56,12 +60,11 @@
<exclude>**/AllTest.java</exclude>
<exclude>**/PackageTest.java</exclude>
</excludes>
<argLine>-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8001</argLine>
<!--<argLine>-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8001</argLine> -->
<!--<argLine>XXadd-opens log4j/org.apache.log4j=org.slf4j.log4j12</argLine>-->
</configuration>
</plugin>
</plugin>
</plugins>
</build>
</project>

View File

@ -30,6 +30,7 @@ import java.util.concurrent.ConcurrentMap;
import org.apache.log4j.LogManager;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.helpers.Reporter;
import org.slf4j.helpers.Util;
/**
@ -49,8 +50,8 @@ public class Reload4jLoggerFactory implements ILoggerFactory {
String part1 = "Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. ";
String part2 = "See also " + LOG4J_DELEGATION_LOOP_URL + " for more details.";
Util.report(part1);
Util.report(part2);
Reporter.error(part1);
Reporter.error(part2);
throw new IllegalStateException(part1 + part2);
} catch (ClassNotFoundException e) {
// this is the good case

View File

@ -4,6 +4,7 @@ import org.apache.log4j.Level;
import org.slf4j.ILoggerFactory;
import org.slf4j.IMarkerFactory;
import org.slf4j.helpers.BasicMarkerFactory;
import org.slf4j.helpers.Reporter;
import org.slf4j.helpers.Util;
import org.slf4j.spi.MDCAdapter;
import org.slf4j.spi.SLF4JServiceProvider;
@ -18,23 +19,28 @@ public class Reload4jServiceProvider implements SLF4JServiceProvider {
public static String REQUESTED_API_VERSION = "2.0.99"; // !final
private ILoggerFactory loggerFactory;
private IMarkerFactory markerFactory;
private MDCAdapter mdcAdapter;
// LoggerFactory expects providers to initialize markerFactory as early as possible.
private final IMarkerFactory markerFactory;
// LoggerFactory expects providers to have a valid MDCAdapter field
// as early as possible, preferably at construction time.
private final MDCAdapter mdcAdapter;
public Reload4jServiceProvider() {
markerFactory = new BasicMarkerFactory();
mdcAdapter = new Reload4jMDCAdapter();
try {
@SuppressWarnings("unused")
Level level = Level.TRACE;
} catch (NoSuchFieldError nsfe) {
Util.report("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version");
Reporter.error("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version");
}
}
@Override
public void initialize() {
loggerFactory = new Reload4jLoggerFactory();
markerFactory = new BasicMarkerFactory();
mdcAdapter = new Reload4jMDCAdapter();
}
@Override

View File

@ -1,18 +0,0 @@
Implementation-Title: slf4j-reload4j
Bundle-ManifestVersion: 2
Bundle-SymbolicName: slf4j.reload4j
Bundle-Name: slf4j-reload4j
Bundle-Vendor: SLF4J.ORG
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.slf4j.reload4j;version=${parsedVersion.osgiVersion}
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion},
org.slf4j.spi;version=${parsedVersion.osgiVersion},
org.slf4j.helpers;version=${parsedVersion.osgiVersion},
org.slf4j.event;version=${parsedVersion.osgiVersion},
org.apache.log4j
Provide-Capability: osgi.service;objectClass:List<String>="org.slf4j.s
pi.SLF4JServiceProvider";type=reload4j;effective:=active,osgi.service
loader;osgi.serviceloader="org.slf4j.spi.SLF4JServiceProvider";regist
er:="org.slf4j.reload4j.Reload4jServiceProvider";type=reload4j
Require-Capability: osgi.extender;filter:="(&(osgi.extender=osgi.servi
celoader.registrar)(version>=1.0.0)(!(version>=2.0.0)))"

View File

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

View File

@ -7,17 +7,20 @@
<parent>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-parent</artifactId>
<version>2.0.4</version>
<version>2.0.19-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>slf4j-simple</artifactId>
<packaging>jar</packaging>
<name>SLF4J Simple Binding</name>
<description>SLF4J Simple binding</description>
<name>SLF4J Simple Provider</name>
<description>SLF4J Simple Provider</description>
<url>http://www.slf4j.org</url>
<properties>
<module-name>org.slf4j.simple</module-name>
<slf4j.provider.implementation>org.slf4j.simple.SimpleServiceProvider</slf4j.provider.implementation>
<slf4j.provider.type>simple</slf4j.provider.type>
</properties>
<dependencies>
@ -25,7 +28,7 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>

View File

@ -221,10 +221,10 @@ public class SimpleLogger extends LegacyAbstractLogger {
public static final String DEFAULT_LOG_LEVEL_KEY = SimpleLogger.SYSTEM_PREFIX + "defaultLogLevel";
/**
* Package access allows only {@link SimpleLoggerFactory} to instantiate
* Protected access allows only {@link SimpleLoggerFactory} and also derived classes to instantiate
* SimpleLogger instances.
*/
SimpleLogger(String name) {
protected SimpleLogger(String name) {
this.name = name;
String levelString = recursivelyComputeLevelString();
@ -409,7 +409,7 @@ public class SimpleLogger extends LegacyAbstractLogger {
buf.append('[');
// Append a readable representation of the log level
String levelStr = level.name();
String levelStr = renderLevel(level.toInt());
buf.append(levelStr);
if (CONFIG_PARAMS.levelInBrackets)
buf.append(']');
@ -439,6 +439,22 @@ public class SimpleLogger extends LegacyAbstractLogger {
write(buf, t);
}
protected String renderLevel(int levelInt) {
switch (levelInt) {
case LOG_LEVEL_TRACE:
return "TRACE";
case LOG_LEVEL_DEBUG:
return("DEBUG");
case LOG_LEVEL_INFO:
return "INFO";
case LOG_LEVEL_WARN:
return CONFIG_PARAMS.warnLevelString;
case LOG_LEVEL_ERROR:
return "ERROR";
}
throw new IllegalStateException("Unrecognized level ["+levelInt+"]");
}
public void log(LoggingEvent event) {
int levelInt = event.getLevel().toInt();

View File

@ -10,6 +10,7 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Properties;
import org.slf4j.helpers.Reporter;
import org.slf4j.helpers.Util;
import org.slf4j.simple.OutputChoice.OutputChoiceType;
@ -98,7 +99,7 @@ public class SimpleLoggerConfiguration {
try {
dateFormatter = new SimpleDateFormat(dateTimeFormatStr);
} catch (IllegalArgumentException e) {
Util.report("Bad date format in " + CONFIGURATION_FILE + "; will output relative time", e);
Reporter.error("Bad date format in " + CONFIGURATION_FILE + "; will output relative time", e);
}
}
}
@ -183,7 +184,7 @@ public class SimpleLoggerConfiguration {
PrintStream printStream = new PrintStream(fos);
return new OutputChoice(printStream);
} catch (FileNotFoundException e) {
Util.report("Could not open [" + logFile + "]. Defaulting to System.err", e);
Reporter.error("Could not open [" + logFile + "]. Defaulting to System.err", e);
return new OutputChoice(OutputChoiceType.SYS_ERR);
}
}

View File

@ -47,28 +47,31 @@ public class SimpleLoggerFactory implements ILoggerFactory {
/**
* Return an appropriate {@link SimpleLogger} instance by name.
*
* This method will call {@link #createLogger(String)} if the logger
* has not been created yet.
*/
public Logger getLogger(String name) {
Logger simpleLogger = loggerMap.get(name);
if (simpleLogger != null) {
return simpleLogger;
} else {
Logger newInstance = new SimpleLogger(name);
Logger oldInstance = loggerMap.putIfAbsent(name, newInstance);
return oldInstance == null ? newInstance : oldInstance;
}
return loggerMap.computeIfAbsent(name, this::createLogger);
}
/**
* Actually creates the logger for the given name.
*/
protected Logger createLogger(String name) {
return new SimpleLogger(name);
}
/**
* Clear the internal logger cache.
*
* This method is intended to be called by classes (in the same package) for
* testing purposes. This method is internal. It can be modified, renamed or
* removed at any time without notice.
* This method is intended to be called by classes (in the same package or
* subclasses) for testing purposes. This method is internal. It can be
* modified, renamed or removed at any time without notice.
*
* You are strongly discouraged from calling this method in production code.
*/
void reset() {
protected void reset() {
loggerMap.clear();
}
}

View File

@ -17,8 +17,16 @@ public class SimpleServiceProvider implements SLF4JServiceProvider {
public static String REQUESTED_API_VERSION = "2.0.99"; // !final
private ILoggerFactory loggerFactory;
private IMarkerFactory markerFactory;
private MDCAdapter mdcAdapter;
// LoggerFactory expects providers to initialize markerFactory as early as possible.
private final IMarkerFactory markerFactory;
// LoggerFactory expects providers to initialize their MDCAdapter field
// as early as possible, preferably at construction time.
private final MDCAdapter mdcAdapter;
public SimpleServiceProvider() {
markerFactory = new BasicMarkerFactory();
mdcAdapter = new NOPMDCAdapter();
}
public ILoggerFactory getLoggerFactory() {
return loggerFactory;
@ -41,10 +49,8 @@ public class SimpleServiceProvider implements SLF4JServiceProvider {
@Override
public void initialize() {
loggerFactory = new SimpleLoggerFactory();
markerFactory = new BasicMarkerFactory();
mdcAdapter = new NOPMDCAdapter();
}
}

View File

@ -1,4 +1,6 @@
module org.slf4j.simple {
module org.slf4j.simple {
requires org.slf4j;
provides org.slf4j.spi.SLF4JServiceProvider with org.slf4j.simple.SimpleServiceProvider;
exports org.slf4j.simple;
opens org.slf4j.simple to org.slf4j;
}

View File

@ -1,18 +0,0 @@
Implementation-Title: slf4j-simple
Bundle-ManifestVersion: 2
Bundle-SymbolicName: slf4j.simple
Bundle-Name: slf4j-simple
Bundle-Vendor: SLF4J.ORG
Require-Bundle: slf4j.api
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.slf4j.simple;version=${parsedVersion.osgiVersion}
Import-Package: org.slf4j;version=${parsedVersion.osgiVersion},
org.slf4j.spi;version=${parsedVersion.osgiVersion},
org.slf4j.helpers;version=${parsedVersion.osgiVersion},
org.slf4j.event;version=${parsedVersion.osgiVersion}
Provide-Capability: osgi.service;objectClass:List<String>="org.slf4j.s
pi.SLF4JServiceProvider";type=simple;effective:=active,osgi.servicelo
ader;osgi.serviceloader="org.slf4j.spi.SLF4JServiceProvider";register
:="org.slf4j.simple.SimpleServiceProvider";type=simple
Require-Capability: osgi.extender;filter:="(&(osgi.extender=osgi.servi
celoader.registrar)(version>=1.0.0)(!(version>=2.0.0)))"

View File

@ -0,0 +1,50 @@
package org.slf4j.simple;
import org.junit.Ignore;
import org.slf4j.Logger;
import org.slf4j.event.Level;
import java.io.PrintStream;
@Ignore
public class AcceptanceTest extends LoggerTestSuite {
@Override
public Logger createLogger(ListAppendingOutputStream outputStream, Level level) {
SimpleLogger.CONFIG_PARAMS.outputChoice = new OutputChoice(new PrintStream(outputStream));
SimpleLogger logger = new SimpleLogger("TestSuiteLogger");
logger.currentLogLevel = SimpleLoggerConfiguration.stringToLevel(level.toString());
return logger;
}
@Override
public String extractMessage(String message) {
return message
.split("\n")[0]
.split("- ")[1];
}
@Override
public String extractExceptionMessage(String message) {
String[] logLines = message.split("\n");
if (logLines.length < 2) {
return null;
}
String exceptionLine = logLines[1];
return exceptionLine.split(": ")[1];
}
@Override
public String extractExceptionType(String message) {
String[] logLines = message.split("\n");
if (logLines.length < 2) {
return null;
}
String exceptionLine = logLines[1];
return exceptionLine.split(": ")[0];
}
}

View File

@ -0,0 +1,53 @@
package org.slf4j.simple;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.event.Level;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertTrue;
/**
* Test class to verify configuration parameters of SimpleLogger
*
* @since 2.0.18
*/
public class ConfigParamsTest {
private ListAppendingOutputStream prepareSink(List<String> outputList) {
return new ListAppendingOutputStream(outputList);
}
@BeforeClass
static public void resetConfigParams() {
SimpleLogger.CONFIG_PARAMS.init();
}
public Logger createLogger(ListAppendingOutputStream outputStream, Level level, String warnLevelString) {
SimpleLogger.CONFIG_PARAMS.outputChoice = new OutputChoice(new PrintStream(outputStream));
SimpleLogger.CONFIG_PARAMS.warnLevelString = warnLevelString;
SimpleLogger logger = new SimpleLogger(ConfigParamsTest.class.getName());
logger.currentLogLevel = SimpleLoggerConfiguration.stringToLevel(level.toString());
return logger;
}
@Test
public void simpleTest(){
String WARN_LEVEL_STRING = "WXYZ";
ArrayList<String> outputList = new ArrayList<>();
Logger configuredLogger = createLogger(prepareSink(outputList), Level.TRACE, WARN_LEVEL_STRING);
configuredLogger.warn("This is a test");
String str0 = outputList.get(0);
assertTrue(str0.contains(WARN_LEVEL_STRING));
}
}

View File

@ -0,0 +1,25 @@
package org.slf4j.simple;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
public class ListAppendingOutputStream extends OutputStream {
private final StringBuilder stringBuilder = new StringBuilder();
private final List<String> targetList;
ListAppendingOutputStream(List<String> list) {this.targetList = list;}
@Override
public void write(int b) throws IOException {
stringBuilder.append((char) b);
}
@Override
public void flush() {
targetList.add(stringBuilder.toString());
stringBuilder.delete(0, stringBuilder.length());
}
}

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