From 35427e2ce731741528d0cf178d63e10c6a4ed68c Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Sat, 25 Nov 2023 17:06:46 +0100 Subject: [PATCH] Disable Lumberjack and Log4j 1.x and document it (#182) This PR removes Lumberjack and Log4j 1.x for the automatic logging backend discovery procedure. The updated procedure is documented in the guide. This closes LOGGING-173 and LOGGING-188. --- src/changes/changes.xml | 6 + .../commons/logging/impl/LogFactoryImpl.java | 6 +- src/site/xdoc/guide.xml | 140 ++++++------------ .../log4j12/ApiClasspathStandardTestCase.java | 5 + .../log4j12/AppClasspathStandardTestCase.java | 4 + .../ChildClasspathStandardTestCase.java | 4 + .../ParentClasspathStandardTestCase.java | 4 + 7 files changed, 71 insertions(+), 98 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f075f16..e2ea10e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -52,6 +52,12 @@ The type attribute can be add,update,fix,remove. Deprecate org.apache.commons.logging.impl.WeakHashtable without replacement. + + Deprecate and disable `Jdk13LumberjackLogger` and `Log4JLogger`. + + + Deprecate and disable `AvalonLogger` and `LogKitLogger`. + Add Automatic-Module-Name Manifest Header for Java 9 compatibility. diff --git a/src/main/java/org/apache/commons/logging/impl/LogFactoryImpl.java b/src/main/java/org/apache/commons/logging/impl/LogFactoryImpl.java index 15abfa2..8edaa0b 100644 --- a/src/main/java/org/apache/commons/logging/impl/LogFactoryImpl.java +++ b/src/main/java/org/apache/commons/logging/impl/LogFactoryImpl.java @@ -150,10 +150,8 @@ public class LogFactoryImpl extends LogFactory { * but broken/unusable for some reason. */ private static final String[] classesToDiscover = { - LOGGING_IMPL_LOG4J_LOGGER, - "org.apache.commons.logging.impl.Jdk14Logger", - "org.apache.commons.logging.impl.Jdk13LumberjackLogger", - "org.apache.commons.logging.impl.SimpleLog" + LOGGING_IMPL_JDK14_LOGGER, + LOGGING_IMPL_SIMPLE_LOGGER }; /** diff --git a/src/site/xdoc/guide.xml b/src/site/xdoc/guide.xml index 721cbb2..b199e1e 100644 --- a/src/site/xdoc/guide.xml +++ b/src/site/xdoc/guide.xml @@ -94,20 +94,24 @@ is intended to be both light-weight and an independent abstraction of other logg It provides the middleware/tooling developer with a simple logging abstraction, that allows the user (application developer) to plug in a specific logging implementation. -

-

JCL provides thin-wrapper Log implementations for -other logging tools, including -Log4J, -Avalon LogKit -(the Avalon Framework's logging infrastructure), -JDK 1.4, and an implementation of JDK 1.4 logging APIs (JSR-47) for pre-1.4 -systems. -The interface maps closely to Log4J and LogKit. -

+

+

+ JCL provides thin-wrapper Log implementations for other logging APIs and backends, including + Log4j API, + SLF4J and java.util.logging. +

+ +

+ Warning: implementations for older logging backends such as + Log4j 1.2, + Avalon LogKit and + Lumberjack are also provided, although they are disabled by default. +

+

Familiarity with high-level details of the relevant Logging implementations is presumed. -

- +

+

As far as possible, JCL tries to be as unobtrusive as possible. @@ -134,58 +138,66 @@ JCL's discovery process). There are two base abstractions used by JCL: Log (the basic logger) and LogFactory (which knows how to create Log instances). Specifying a particular Log implementation is very useful (whether that is -one provided by commons-logging or a user-defined one). Specifying a -LogFactory implementation other than the default is a subject for +one provided by Commons Logging or a user-defined one). Specifying a +LogFactory implementation explicitly is a subject for advanced users only, so will not be addressed here. -

+

-The default LogFactory implementation uses the following discovery process + JCL provides three standard log factories: +

+
    +
  1. if Log4j API + is present on the classpath and it is not redirected to SLF4J, then Log4jApiLogFactory + is used. This factory redirects all output to Log4j API.
  2. +
  3. otherwise if SLF4J is presend on the classpath, + then Slf4jLogFactory is used. This factory redirects all output to SLF4J.
  4. +
  5. otherwise the legacy LogFactoryImpl is used.
  6. +
+

+The legacy LogFactory implementation uses the following discovery process to determine what type of Log implementation it should use (the process terminates when the first positive match - in order - is found): -

+

  1. +

    Look for a configuration attribute of this factory named org.apache.commons.logging.Log (for backwards compatibility to pre-1.0 versions of this API, an attribute org.apache.commons.logging.log is also consulted). -

    +

    +

    Configuration attributes can be set explicitly by java code, but they are more -commonly set by placing a file named commons-logging.properties in the classpath. +commonly set by placing a file named commons-logging.properties in the classpath. When such a file exists, every entry in the properties file becomes an "attribute" of the LogFactory. When there is more than one such file in the classpath, releases of commons-logging prior to 1.1 simply use the first one found. From release 1.1, each file may define a priority key, and the file with the highest priority is used (no priority definition implies priority of zero). When multiple files have the same priority, the first one found is used. -

    -

    -Defining this property in a commons-logging.properties file is the recommended +

    +

    + Defining this property in a commons-logging.properties file is the recommended way of explicitly selecting a Log implementation. -

    -
  2. +

    +
  3. Look for a system property named org.apache.commons.logging.Log (for backwards compatibility to pre-1.0 versions of this API, a system property org.apache.commons.logging.log is also consulted). -
  4. +
  5. -If the Log4J logging system is available in the application -class path, use the corresponding wrapper class -(Log4JLogger). -
  6. -
  7. -If the application is executing on a JDK 1.4 system, use +If the java.logging module is available, use the corresponding wrapper class (Jdk14Logger). -
  8. +
  9. Fall back to the default simple logging wrapper (SimpleLog). -
  10. -
+ +

Consult the JCL javadocs for details of the various Log implementations that ship with the component. (The discovery process is also covered in more @@ -213,66 +225,6 @@ be required in the application. JCL simply forwards logging method calls to the implementation. When writing library code this issue is of course not relevant as the calling application is responsible for handling such issues.

- -

-Log4J is a very commonly used logging implementation (as well as being the JCL primary default), -so a few details are presented herein to get the developer/integrator going. -Please see the Log4J Home for more details -on Log4J and it's configuration. -

-

-Configure Log4J using system properties and/or a properties file: -

-
    -
  • -log4j.configuration=log4j.properties -Use this system property to specify the name of a Log4J configuration file. -If not specified, the default configuration file is log4j.properties. -
  • -
  • -log4j.rootCategory=priority [, appender]* -
  • -Set the default (root) logger priority. -
  • -log4j.logger.logger.name=priority -Set the priority for the named logger -and all loggers hierarchically lower than, or below, the -named logger. -logger.name corresponds to the parameter of -LogFactory.getLog(logger.name), -used to create the logger instance. Priorities are: -DEBUG, -INFO, -WARN, -ERROR, -or FATAL. -
    -Log4J understands hierarchical names, -enabling control by package or high-level qualifiers: -log4j.logger.org.apache.component=DEBUG -will enable debug messages for all classes in both -org.apache.component -and -org.apache.component.sub. -Likewise, setting -log4j.logger.org.apache.component=DEBUG -will enable debug message for all 'component' classes, -but not for other Apache projects. -
  • -
  • -log4j.appender.appender.Threshold=priority -
  • -Log4J appenders correspond to different output devices: -console, files, sockets, and others. -If appender's threshold -is less than or equal to the message priority then -the message is written by that appender. -This allows different levels of detail to be appear -at different log destinations. -For example: one can capture DEBUG (and higher) level information in a logfile, -while limiting console output to INFO (and higher). -
-
diff --git a/src/test/java/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java b/src/test/java/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java index f275e9f..7790c28 100644 --- a/src/test/java/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java +++ b/src/test/java/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java @@ -19,6 +19,9 @@ package org.apache.commons.logging.log4j.log4j12; import org.apache.commons.logging.PathableClassLoader; import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.impl.Log4JLogger; +import org.apache.commons.logging.impl.Log4jApiLogFactory; +import org.apache.commons.logging.impl.LogFactoryImpl; import junit.framework.Test; import junit.framework.TestCase; @@ -36,6 +39,8 @@ public class ApiClasspathStandardTestCase extends TestCase { * Return the tests included in this test suite. */ public static Test suite() throws Exception { + // Ensure Log4JLogger is used + System.setProperty(LogFactoryImpl.LOG_PROPERTY, Log4JLogger.class.getName()); final PathableClassLoader parent = new PathableClassLoader(null); parent.useExplicitLoader("junit.", Test.class.getClassLoader()); parent.addLogicalLib("commons-logging-api"); diff --git a/src/test/java/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java b/src/test/java/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java index ca5851c..2220a35 100644 --- a/src/test/java/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java +++ b/src/test/java/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java @@ -19,6 +19,8 @@ package org.apache.commons.logging.log4j.log4j12; import org.apache.commons.logging.PathableClassLoader; import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.impl.Log4JLogger; +import org.apache.commons.logging.impl.LogFactoryImpl; import junit.framework.Test; import junit.framework.TestCase; @@ -34,6 +36,8 @@ public class AppClasspathStandardTestCase extends TestCase { * Return the tests included in this test suite. */ public static Test suite() throws Exception { + // Ensure Log4JLogger is used + System.setProperty(LogFactoryImpl.LOG_PROPERTY, Log4JLogger.class.getName()); final PathableClassLoader loader = new PathableClassLoader(null); loader.useExplicitLoader("junit.", Test.class.getClassLoader()); loader.addLogicalLib("testclasses"); diff --git a/src/test/java/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java b/src/test/java/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java index 04bbe9f..9543904 100644 --- a/src/test/java/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java +++ b/src/test/java/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java @@ -19,6 +19,8 @@ package org.apache.commons.logging.log4j.log4j12; import org.apache.commons.logging.PathableClassLoader; import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.impl.Log4JLogger; +import org.apache.commons.logging.impl.LogFactoryImpl; import junit.framework.Test; import junit.framework.TestCase; @@ -35,6 +37,8 @@ public class ChildClasspathStandardTestCase extends TestCase { * Return the tests included in this test suite. */ public static Test suite() throws Exception { + // Ensure Log4JLogger is used + System.setProperty(LogFactoryImpl.LOG_PROPERTY, Log4JLogger.class.getName()); final PathableClassLoader parent = new PathableClassLoader(null); parent.useExplicitLoader("junit.", Test.class.getClassLoader()); diff --git a/src/test/java/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java b/src/test/java/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java index ccfba9a..5c30cac 100644 --- a/src/test/java/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java +++ b/src/test/java/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java @@ -19,6 +19,8 @@ package org.apache.commons.logging.log4j.log4j12; import org.apache.commons.logging.PathableClassLoader; import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.impl.Log4JLogger; +import org.apache.commons.logging.impl.LogFactoryImpl; import junit.framework.Test; import junit.framework.TestCase; @@ -34,6 +36,8 @@ public class ParentClasspathStandardTestCase extends TestCase { * Return the tests included in this test suite. */ public static Test suite() throws Exception { + // Ensure Log4JLogger is used + System.setProperty(LogFactoryImpl.LOG_PROPERTY, Log4JLogger.class.getName()); final PathableClassLoader parent = new PathableClassLoader(null); parent.useExplicitLoader("junit.", Test.class.getClassLoader()); parent.addLogicalLib("commons-logging");