1
0

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.
This commit is contained in:
Piotr P. Karwasz
2023-11-25 17:06:46 +01:00
committed by GitHub
parent 2a1457cb34
commit 35427e2ce7
7 changed files with 71 additions and 98 deletions

View File

@@ -52,6 +52,12 @@ The <action> type attribute can be add,update,fix,remove.
<action dev="ggregory" type="add" due-to="Piotr P. Karwasz"> <action dev="ggregory" type="add" due-to="Piotr P. Karwasz">
Deprecate org.apache.commons.logging.impl.WeakHashtable without replacement. Deprecate org.apache.commons.logging.impl.WeakHashtable without replacement.
</action> </action>
<action issue="LOGGING-188" dev="pkarwasz" type="add" due-to="Piotr P. Karwasz">
Deprecate and disable `Jdk13LumberjackLogger` and `Log4JLogger`.
</action>
<action issue="LOGGING-173" dev="pkarwasz" type="add" due-to="SingingBush">
Deprecate and disable `AvalonLogger` and `LogKitLogger`.
</action>
<!-- FIX --> <!-- FIX -->
<action issue="LOGGING-165" dev="britter" type="add"> <action issue="LOGGING-165" dev="britter" type="add">
Add Automatic-Module-Name Manifest Header for Java 9 compatibility. Add Automatic-Module-Name Manifest Header for Java 9 compatibility.

View File

@@ -150,10 +150,8 @@ public class LogFactoryImpl extends LogFactory {
* but broken/unusable for some reason. * but broken/unusable for some reason.
*/ */
private static final String[] classesToDiscover = { private static final String[] classesToDiscover = {
LOGGING_IMPL_LOG4J_LOGGER, LOGGING_IMPL_JDK14_LOGGER,
"org.apache.commons.logging.impl.Jdk14Logger", LOGGING_IMPL_SIMPLE_LOGGER
"org.apache.commons.logging.impl.Jdk13LumberjackLogger",
"org.apache.commons.logging.impl.SimpleLog"
}; };
/** /**

View File

@@ -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 It provides the middleware/tooling developer with a simple
logging abstraction, that allows the user (application developer) to plug in logging abstraction, that allows the user (application developer) to plug in
a specific logging implementation. a specific logging implementation.
</p> </p>
<p>JCL provides thin-wrapper <code>Log</code> implementations for <p>
other logging tools, including JCL provides thin-wrapper <code>Log</code> implementations for other logging APIs and backends, including
<a href="https//logging.apache.org/log4j/docs/index.html">Log4J</a>, <a href="https://logging.apache.org/log4j/2.x/manual/api-separation">Log4j API</a>,
<a href="https//avalon.apache.org/logkit/index.html">Avalon LogKit</a> <a href="https://www.slf4j.org">SLF4J</a> and <code>java.util.logging</code>.
(the Avalon Framework's logging infrastructure), </p>
JDK 1.4, and an implementation of JDK 1.4 logging APIs (JSR-47) for pre-1.4
systems. <p>
The interface maps closely to Log4J and LogKit. <strong>Warning:</strong> implementations for older logging backends such as
</p> <a href="https//logging.apache.org/log4j/1.2/">Log4j 1.2</a>,
<a href="https//avalon.apache.org">Avalon LogKit</a> and
<a href="https://javalogging.sourceforge.net">Lumberjack</a> are also provided, although they are disabled by default.
</p>
<p> <p>
Familiarity with high-level details of the relevant Logging implementations is presumed. Familiarity with high-level details of the relevant Logging implementations is presumed.
</p> </p>
</section> </section>
<section name="Quick Start"> <section name="Quick Start">
<p> <p>
As far as possible, JCL tries to be as unobtrusive as possible. 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: <code>Log</code> There are two base abstractions used by JCL: <code>Log</code>
(the basic logger) and <code>LogFactory</code> (which knows how to create <code>Log</code> (the basic logger) and <code>LogFactory</code> (which knows how to create <code>Log</code>
instances). Specifying a particular Log implementation is very useful (whether that is instances). Specifying a particular Log implementation is very useful (whether that is
one provided by commons-logging or a user-defined one). Specifying a one provided by Commons Logging or a user-defined one). Specifying a
<code>LogFactory</code> implementation other than the default is a subject for <code>LogFactory</code> implementation explicitly is a subject for
advanced users only, so will not be addressed here. advanced users only, so will not be addressed here.
</p> </p>
<p> <p>
The default <code>LogFactory</code> implementation uses the following discovery process JCL provides three standard log factories:
</p>
<ol>
<li>if <a href="https://logging.apache.org/log4j/2.x/manual/api-separation">Log4j API</a>
is present on the classpath and it is not redirected to SLF4J, then <code>Log4jApiLogFactory</code>
is used. This factory redirects all output to Log4j API.</li>
<li>otherwise if <a href="https://www.slf4j.org">SLF4J</a> is presend on the classpath,
then <code>Slf4jLogFactory</code> is used. This factory redirects all output to SLF4J.</li>
<li>otherwise the legacy <code>LogFactoryImpl</code> is used.</li>
</ol>
<p>
The legacy <code>LogFactory</code> implementation uses the following discovery process
to determine what type of <code>Log</code> implementation it should use to determine what type of <code>Log</code> implementation it should use
(the process terminates when the first positive match - in order - is found): (the process terminates when the first positive match - in order - is found):
</p> </p>
<ol> <ol>
<li> <li>
<p>
Look for a configuration attribute of this factory named Look for a configuration attribute of this factory named
<code>org.apache.commons.logging.Log</code> (for backwards compatibility to <code>org.apache.commons.logging.Log</code> (for backwards compatibility to
pre-1.0 versions of this API, an attribute pre-1.0 versions of this API, an attribute
<code>org.apache.commons.logging.log</code> is also consulted). <code>org.apache.commons.logging.log</code> is also consulted).
<p> </p>
<p>
Configuration attributes can be set explicitly by java code, but they are more 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 <code>commons-logging.properties</code> in the classpath.
When such a file exists, every entry in the properties file becomes an "attribute" 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 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, of commons-logging prior to 1.1 simply use the first one found. From release 1.1,
each file may define a <code>priority</code> key, and the file with each file may define a <code>priority</code> key, and the file with
the highest priority is used (no priority definition implies priority of zero). 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. When multiple files have the same priority, the first one found is used.
</p> </p>
<p> <p>
Defining this property in a commons-logging.properties file is the recommended Defining this property in a <code>commons-logging.properties</code> file is the recommended
way of explicitly selecting a Log implementation. way of explicitly selecting a Log implementation.
</p> </p>
</li> </li>
<li> <li>
Look for a system property named Look for a system property named
<code>org.apache.commons.logging.Log</code> (for backwards <code>org.apache.commons.logging.Log</code> (for backwards
compatibility to pre-1.0 versions of this API, a system property compatibility to pre-1.0 versions of this API, a system property
<code>org.apache.commons.logging.log</code> is also consulted). <code>org.apache.commons.logging.log</code> is also consulted).
</li> </li>
<li> <li>
If the Log4J logging system is available in the application If the <code>java.logging</code> module is available, use
class path, use the corresponding wrapper class
(<a href="https//commons.apache.org/logging/apidocs/org/apache/commons/logging/impl/Log4JLogger.html">Log4JLogger</a>).
</li>
<li>
If the application is executing on a JDK 1.4 system, use
the corresponding wrapper class the corresponding wrapper class
(<a href="https//commons.apache.org/logging/apidocs/org/apache/commons/logging/impl/Jdk14Logger.html">Jdk14Logger</a>). (<a href="https//commons.apache.org/logging/apidocs/org/apache/commons/logging/impl/Jdk14Logger.html">Jdk14Logger</a>).
</li> </li>
<li> <li>
Fall back to the default simple logging wrapper Fall back to the default simple logging wrapper
(<a href="https//commons.apache.org/logging/apidocs/org/apache/commons/logging/impl/SimpleLog.html">SimpleLog</a>). (<a href="https//commons.apache.org/logging/apidocs/org/apache/commons/logging/impl/SimpleLog.html">SimpleLog</a>).
</li> </li>
</ol> </ol>
<p> <p>
Consult the JCL javadocs for details of the various <code>Log</code> Consult the JCL javadocs for details of the various <code>Log</code>
implementations that ship with the component. (The discovery process is also covered in more 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 implementation. When writing library code this issue is of course not relevant as the calling application
is responsible for handling such issues. is responsible for handling such issues.
</p> </p>
<subsection name='Configuring Log4J'>
<p>
Log4J is a very commonly used logging implementation (as well as being the JCL primary default),
so a <i>few</i> details are presented herein to get the developer/integrator going.
Please see the <a href='https//logging.apache.org/log4j/docs/index.html'>Log4J Home</a> for more details
on Log4J and it's configuration.
</p>
<p>
Configure Log4J using system properties and/or a properties file:
</p>
<ul>
<li>
<strong>log4j.configuration=<em>log4j.properties</em></strong>
Use this system property to specify the name of a Log4J configuration file.
If not specified, the default configuration file is <i>log4j.properties</i>.
</li>
<li>
<strong>log4j.rootCategory=<i>priority</i> [, <i>appender</i>]*</strong>
</li>
Set the default (root) logger priority.
<li>
<strong>log4j.logger.<i>logger.name</i>=<i>priority</i></strong>
Set the priority for the named logger
and all loggers hierarchically lower than, or below, the
named logger.
<i>logger.name</i> corresponds to the parameter of
<code>LogFactory.getLog(<i>logger.name</i>)</code>,
used to create the logger instance. Priorities are:
<code>DEBUG</code>,
<code>INFO</code>,
<code>WARN</code>,
<code>ERROR</code>,
or <code>FATAL</code>.
<br/>
Log4J understands hierarchical names,
enabling control by package or high-level qualifiers:
<code>log4j.logger.org.apache.component=DEBUG</code>
will enable debug messages for all classes in both
<code>org.apache.component</code>
and
<code>org.apache.component.sub</code>.
Likewise, setting
<code>log4j.logger.org.apache.component=DEBUG</code>
will enable debug message for all 'component' classes,
but not for other Apache projects.
</li>
<li>
<strong>log4j.appender.<i>appender</i>.Threshold=<i>priority</i></strong>
</li>
Log4J <i>appenders</i> correspond to different output devices:
console, files, sockets, and others.
If appender's <i>threshold</i>
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).
</ul>
</subsection>
</subsection> </subsection>
</section> </section>
<section name='Developing With JCL'> <section name='Developing With JCL'>

View File

@@ -19,6 +19,9 @@ package org.apache.commons.logging.log4j.log4j12;
import org.apache.commons.logging.PathableClassLoader; import org.apache.commons.logging.PathableClassLoader;
import org.apache.commons.logging.PathableTestSuite; 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.Test;
import junit.framework.TestCase; import junit.framework.TestCase;
@@ -36,6 +39,8 @@ public class ApiClasspathStandardTestCase extends TestCase {
* Return the tests included in this test suite. * Return the tests included in this test suite.
*/ */
public static Test suite() throws Exception { public static Test suite() throws Exception {
// Ensure Log4JLogger is used
System.setProperty(LogFactoryImpl.LOG_PROPERTY, Log4JLogger.class.getName());
final PathableClassLoader parent = new PathableClassLoader(null); final PathableClassLoader parent = new PathableClassLoader(null);
parent.useExplicitLoader("junit.", Test.class.getClassLoader()); parent.useExplicitLoader("junit.", Test.class.getClassLoader());
parent.addLogicalLib("commons-logging-api"); parent.addLogicalLib("commons-logging-api");

View File

@@ -19,6 +19,8 @@ package org.apache.commons.logging.log4j.log4j12;
import org.apache.commons.logging.PathableClassLoader; import org.apache.commons.logging.PathableClassLoader;
import org.apache.commons.logging.PathableTestSuite; 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.Test;
import junit.framework.TestCase; import junit.framework.TestCase;
@@ -34,6 +36,8 @@ public class AppClasspathStandardTestCase extends TestCase {
* Return the tests included in this test suite. * Return the tests included in this test suite.
*/ */
public static Test suite() throws Exception { public static Test suite() throws Exception {
// Ensure Log4JLogger is used
System.setProperty(LogFactoryImpl.LOG_PROPERTY, Log4JLogger.class.getName());
final PathableClassLoader loader = new PathableClassLoader(null); final PathableClassLoader loader = new PathableClassLoader(null);
loader.useExplicitLoader("junit.", Test.class.getClassLoader()); loader.useExplicitLoader("junit.", Test.class.getClassLoader());
loader.addLogicalLib("testclasses"); loader.addLogicalLib("testclasses");

View File

@@ -19,6 +19,8 @@ package org.apache.commons.logging.log4j.log4j12;
import org.apache.commons.logging.PathableClassLoader; import org.apache.commons.logging.PathableClassLoader;
import org.apache.commons.logging.PathableTestSuite; 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.Test;
import junit.framework.TestCase; import junit.framework.TestCase;
@@ -35,6 +37,8 @@ public class ChildClasspathStandardTestCase extends TestCase {
* Return the tests included in this test suite. * Return the tests included in this test suite.
*/ */
public static Test suite() throws Exception { public static Test suite() throws Exception {
// Ensure Log4JLogger is used
System.setProperty(LogFactoryImpl.LOG_PROPERTY, Log4JLogger.class.getName());
final PathableClassLoader parent = new PathableClassLoader(null); final PathableClassLoader parent = new PathableClassLoader(null);
parent.useExplicitLoader("junit.", Test.class.getClassLoader()); parent.useExplicitLoader("junit.", Test.class.getClassLoader());

View File

@@ -19,6 +19,8 @@ package org.apache.commons.logging.log4j.log4j12;
import org.apache.commons.logging.PathableClassLoader; import org.apache.commons.logging.PathableClassLoader;
import org.apache.commons.logging.PathableTestSuite; 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.Test;
import junit.framework.TestCase; import junit.framework.TestCase;
@@ -34,6 +36,8 @@ public class ParentClasspathStandardTestCase extends TestCase {
* Return the tests included in this test suite. * Return the tests included in this test suite.
*/ */
public static Test suite() throws Exception { public static Test suite() throws Exception {
// Ensure Log4JLogger is used
System.setProperty(LogFactoryImpl.LOG_PROPERTY, Log4JLogger.class.getName());
final PathableClassLoader parent = new PathableClassLoader(null); final PathableClassLoader parent = new PathableClassLoader(null);
parent.useExplicitLoader("junit.", Test.class.getClassLoader()); parent.useExplicitLoader("junit.", Test.class.getClassLoader());
parent.addLogicalLib("commons-logging"); parent.addLogicalLib("commons-logging");