Replace spring-jcl with regular Apache Commons Logging 1.3

Closes gh-32459
This commit is contained in:
Juergen Hoeller 2024-12-12 17:37:11 +01:00
parent c5eefaa5f3
commit 3db1b94465
19 changed files with 6 additions and 1404 deletions

View File

@ -79,9 +79,6 @@ configure([rootProject] + javaProjects) { project ->
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
testRuntimeOnly("org.junit.platform:junit-platform-suite-engine")
testRuntimeOnly("org.apache.logging.log4j:log4j-core")
testRuntimeOnly("org.apache.logging.log4j:log4j-jul")
testRuntimeOnly("org.apache.logging.log4j:log4j-slf4j2-impl")
// JSR-305 only used for non-required meta-annotations
compileOnly("com.google.code.findbugs:jsr305")
testCompileOnly("com.google.code.findbugs:jsr305")

View File

@ -101,7 +101,6 @@
*** xref:core/aop-api/extensibility.adoc[]
** xref:core/null-safety.adoc[]
** xref:core/databuffer-codec.adoc[]
** xref:core/spring-jcl.adoc[]
** xref:core/aot.adoc[]
** xref:core/appendix.adoc[]
*** xref:core/appendix/xsd-schemas.adoc[]

View File

@ -1,47 +0,0 @@
[[spring-jcl]]
= Logging
Spring comes with its own Commons Logging bridge implemented
in the `spring-jcl` module. The implementation checks for the presence of the Log4j 2.x
API and the SLF4J 1.7 API in the classpath and uses the first one of those found as the
logging implementation, falling back to the Java platform's core logging facilities (also
known as _JUL_ or `java.util.logging`) if neither Log4j 2.x nor SLF4J is available.
Put Log4j 2.x or Logback (or another SLF4J provider) in your classpath, without any extra
bridges, and let the framework auto-adapt to your choice. For further information see the
{spring-boot-docs-ref}/features/logging.html[Spring
Boot Logging Reference Documentation].
[NOTE]
====
Spring's Commons Logging variant is only meant to be used for infrastructure logging
purposes in the core framework and in extensions.
For logging needs within application code, prefer direct use of Log4j 2.x, SLF4J, or JUL.
====
A `Log` implementation may be retrieved via `org.apache.commons.logging.LogFactory` as in
the following example.
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MyBean {
private final Log log = LogFactory.getLog(getClass());
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MyBean {
private val log = LogFactory.getLog(javaClass)
// ...
}
----
======

View File

@ -14,7 +14,6 @@ dependencies {
api(platform("io.projectreactor:reactor-bom:2024.0.1"))
api(platform("io.rsocket:rsocket-bom:1.1.4"))
api(platform("org.apache.groovy:groovy-bom:4.0.24"))
api(platform("org.apache.logging.log4j:log4j-bom:2.21.1"))
api(platform("org.assertj:assertj-bom:3.26.3"))
api(platform("org.eclipse.jetty:jetty-bom:12.0.15"))
api(platform("org.eclipse.jetty.ee10:jetty-ee10-bom:12.0.15"))
@ -45,6 +44,7 @@ dependencies {
api("com.thoughtworks.qdox:qdox:2.1.0")
api("com.thoughtworks.xstream:xstream:1.4.21")
api("commons-io:commons-io:2.15.0")
api("commons-logging:commons-logging:1.3.4")
api("de.bechte.junit:junit-hierarchicalcontextrunner:4.12.2")
api("io.micrometer:context-propagation:1.1.1")
api("io.mockk:mockk:1.13.4")
@ -138,7 +138,6 @@ dependencies {
api("org.seleniumhq.selenium:htmlunit3-driver:4.26.0")
api("org.seleniumhq.selenium:selenium-java:4.26.0")
api("org.skyscreamer:jsonassert:1.5.3")
api("org.slf4j:slf4j-api:2.0.16")
api("org.testng:testng:7.10.2")
api("org.webjars:underscorejs:1.8.3")
api("org.webjars:webjars-locator-lite:1.0.0")

View File

@ -14,7 +14,6 @@ include "spring-core"
include "spring-core-test"
include "spring-expression"
include "spring-instrument"
include "spring-jcl"
include "spring-jdbc"
include "spring-jms"
include "spring-messaging"

View File

@ -70,7 +70,7 @@ dependencies {
objenesis("org.objenesis:objenesis:${objenesisVersion}@jar")
api(files(javapoetRepackJar))
api(files(objenesisRepackJar))
api(project(":spring-jcl"))
api("commons-logging:commons-logging")
compileOnly("io.projectreactor.tools:blockhound")
compileOnly("org.graalvm.sdk:graal-sdk")
optional("io.micrometer:context-propagation")

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -26,9 +26,7 @@ import org.apache.commons.logging.LogFactory;
/**
* Factory for common {@link Log} delegates with Spring's logging conventions.
*
* <p>Mainly for internal use within the framework with Apache Commons Logging,
* typically in the form of the {@code spring-jcl} bridge but also compatible
* with other Commons Logging bridges.
* <p>Mainly for internal use within the framework with Apache Commons Logging.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,9 +28,7 @@ import org.springframework.util.StringUtils;
/**
* Utility methods for formatting and logging messages.
*
* <p>Mainly for internal use within the framework with Apache Commons Logging,
* typically in the form of the {@code spring-jcl} bridge but also compatible
* with other Commons Logging bridges.
* <p>Mainly for internal use within the framework with Apache Commons Logging.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller

View File

@ -1,6 +0,0 @@
description = "Spring Commons Logging Bridge"
dependencies {
optional("org.apache.logging.log4j:log4j-api")
optional("org.slf4j:slf4j-api")
}

View File

@ -1,196 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.logging;
/**
* A simple logging interface abstracting logging APIs. In order to be
* instantiated successfully by {@link LogFactory}, classes that implement
* this interface must have a constructor that takes a single String
* parameter representing the "name" of this Log.
*
* <p>The six logging levels used by <code>Log</code> are (in order):
* <ol>
* <li>trace (the least serious)</li>
* <li>debug</li>
* <li>info</li>
* <li>warn</li>
* <li>error</li>
* <li>fatal (the most serious)</li>
* </ol>
*
* The mapping of these log levels to the concepts used by the underlying
* logging system is implementation dependent.
* The implementation should ensure, though, that this ordering behaves
* as expected.
*
* <p>Performance is often a logging concern.
* By examining the appropriate property,
* a component can avoid expensive operations (producing information
* to be logged).
*
* <p>For example,
* <pre>
* if (log.isDebugEnabled()) {
* ... do something expensive ...
* log.debug(theResult);
* }
* </pre>
*
* <p>Configuration of the underlying logging system will generally be done
* external to the Logging APIs, through whatever mechanism is supported by
* that system.
*
* @author Juergen Hoeller (for the {@code spring-jcl} variant)
* @since 5.0
*/
public interface Log {
/**
* Is fatal logging currently enabled?
* <p>Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than fatal.
* @return true if fatal is enabled in the underlying logger.
*/
boolean isFatalEnabled();
/**
* Is error logging currently enabled?
* <p>Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than error.
* @return true if error is enabled in the underlying logger.
*/
boolean isErrorEnabled();
/**
* Is warn logging currently enabled?
* <p>Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than warn.
* @return true if warn is enabled in the underlying logger.
*/
boolean isWarnEnabled();
/**
* Is info logging currently enabled?
* <p>Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than info.
* @return true if info is enabled in the underlying logger.
*/
boolean isInfoEnabled();
/**
* Is debug logging currently enabled?
* <p>Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than debug.
* @return true if debug is enabled in the underlying logger.
*/
boolean isDebugEnabled();
/**
* Is trace logging currently enabled?
* <p>Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than trace.
* @return true if trace is enabled in the underlying logger.
*/
boolean isTraceEnabled();
/**
* Logs a message with fatal log level.
* @param message log this message
*/
void fatal(Object message);
/**
* Logs an error with fatal log level.
* @param message log this message
* @param t log this cause
*/
void fatal(Object message, Throwable t);
/**
* Logs a message with error log level.
* @param message log this message
*/
void error(Object message);
/**
* Logs an error with error log level.
* @param message log this message
* @param t log this cause
*/
void error(Object message, Throwable t);
/**
* Logs a message with warn log level.
* @param message log this message
*/
void warn(Object message);
/**
* Logs an error with warn log level.
* @param message log this message
* @param t log this cause
*/
void warn(Object message, Throwable t);
/**
* Logs a message with info log level.
* @param message log this message
*/
void info(Object message);
/**
* Logs an error with info log level.
* @param message log this message
* @param t log this cause
*/
void info(Object message, Throwable t);
/**
* Logs a message with debug log level.
* @param message log this message
*/
void debug(Object message);
/**
* Logs an error with debug log level.
* @param message log this message
* @param t log this cause
*/
void debug(Object message, Throwable t);
/**
* Logs a message with trace log level.
* @param message log this message
*/
void trace(Object message);
/**
* Logs an error with trace log level.
* @param message log this message
* @param t log this cause
*/
void trace(Object message, Throwable t);
}

View File

@ -1,698 +0,0 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.logging;
import java.io.Serializable;
import java.util.function.Function;
import java.util.logging.LogRecord;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.spi.ExtendedLogger;
import org.apache.logging.log4j.spi.LoggerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.spi.LocationAwareLogger;
/**
* Spring's common JCL adapter behind {@link LogFactory} and {@link LogFactoryService}.
* Detects the presence of Log4j 2.x / SLF4J, falling back to {@code java.util.logging}.
*
* @author Juergen Hoeller
* @author Sebastien Deleuze
* @since 5.1
*/
final class LogAdapter {
private static final boolean log4jSpiPresent = isPresent("org.apache.logging.log4j.spi.ExtendedLogger");
private static final boolean log4jSlf4jProviderPresent = isPresent("org.apache.logging.slf4j.SLF4JProvider");
private static final boolean slf4jSpiPresent = isPresent("org.slf4j.spi.LocationAwareLogger");
private static final boolean slf4jApiPresent = isPresent("org.slf4j.Logger");
private static final Function<String, Log> createLog;
static {
if (log4jSpiPresent) {
if (log4jSlf4jProviderPresent && slf4jSpiPresent) {
// log4j-to-slf4j bridge -> we'll rather go with the SLF4J SPI;
// however, we still prefer Log4j over the plain SLF4J API since
// the latter does not have location awareness support.
createLog = Slf4jAdapter::createLocationAwareLog;
}
else {
// Use Log4j 2.x directly, including location awareness support
createLog = Log4jAdapter::createLog;
}
}
else if (slf4jSpiPresent) {
// Full SLF4J SPI including location awareness support
createLog = Slf4jAdapter::createLocationAwareLog;
}
else if (slf4jApiPresent) {
// Minimal SLF4J API without location awareness support
createLog = Slf4jAdapter::createLog;
}
else {
// java.util.logging as default
// Defensively use lazy-initializing adapter class here as well since the
// java.logging module is not present by default on JDK 9. We are requiring
// its presence if neither Log4j nor SLF4J is available; however, in the
// case of Log4j or SLF4J, we are trying to prevent early initialization
// of the JavaUtilLog adapter - for example, by a JVM in debug mode - when eagerly
// trying to parse the bytecode for all the cases of this switch clause.
createLog = JavaUtilAdapter::createLog;
}
}
private LogAdapter() {
}
/**
* Create an actual {@link Log} instance for the selected API.
* @param name the logger name
*/
public static Log createLog(String name) {
return createLog.apply(name);
}
private static boolean isPresent(String className) {
try {
Class.forName(className, false, LogAdapter.class.getClassLoader());
return true;
}
catch (Throwable ex) {
// Typically ClassNotFoundException or NoClassDefFoundError...
return false;
}
}
private static class Log4jAdapter {
public static Log createLog(String name) {
return new Log4jLog(name);
}
}
private static class Slf4jAdapter {
public static Log createLocationAwareLog(String name) {
Logger logger = LoggerFactory.getLogger(name);
return (logger instanceof LocationAwareLogger locationAwareLogger ?
new Slf4jLocationAwareLog(locationAwareLogger) : new Slf4jLog<>(logger));
}
public static Log createLog(String name) {
return new Slf4jLog<>(LoggerFactory.getLogger(name));
}
}
private static class JavaUtilAdapter {
public static Log createLog(String name) {
return new JavaUtilLog(name);
}
}
@SuppressWarnings("serial")
private static class Log4jLog implements Log, Serializable {
private static final String FQCN = Log4jLog.class.getName();
private static final LoggerContext loggerContext =
LogManager.getContext(Log4jLog.class.getClassLoader(), false);
private final String name;
private final transient ExtendedLogger logger;
public Log4jLog(String name) {
this.name = name;
LoggerContext context = loggerContext;
if (context == null) {
// Circular call in early-init scenario -> static field not initialized yet
context = LogManager.getContext(Log4jLog.class.getClassLoader(), false);
}
this.logger = context.getLogger(name);
}
@Override
public boolean isFatalEnabled() {
return this.logger.isEnabled(Level.FATAL);
}
@Override
public boolean isErrorEnabled() {
return this.logger.isEnabled(Level.ERROR);
}
@Override
public boolean isWarnEnabled() {
return this.logger.isEnabled(Level.WARN);
}
@Override
public boolean isInfoEnabled() {
return this.logger.isEnabled(Level.INFO);
}
@Override
public boolean isDebugEnabled() {
return this.logger.isEnabled(Level.DEBUG);
}
@Override
public boolean isTraceEnabled() {
return this.logger.isEnabled(Level.TRACE);
}
@Override
public void fatal(Object message) {
log(Level.FATAL, message, null);
}
@Override
public void fatal(Object message, Throwable exception) {
log(Level.FATAL, message, exception);
}
@Override
public void error(Object message) {
log(Level.ERROR, message, null);
}
@Override
public void error(Object message, Throwable exception) {
log(Level.ERROR, message, exception);
}
@Override
public void warn(Object message) {
log(Level.WARN, message, null);
}
@Override
public void warn(Object message, Throwable exception) {
log(Level.WARN, message, exception);
}
@Override
public void info(Object message) {
log(Level.INFO, message, null);
}
@Override
public void info(Object message, Throwable exception) {
log(Level.INFO, message, exception);
}
@Override
public void debug(Object message) {
log(Level.DEBUG, message, null);
}
@Override
public void debug(Object message, Throwable exception) {
log(Level.DEBUG, message, exception);
}
@Override
public void trace(Object message) {
log(Level.TRACE, message, null);
}
@Override
public void trace(Object message, Throwable exception) {
log(Level.TRACE, message, exception);
}
private void log(Level level, Object message, Throwable exception) {
if (message instanceof String text) {
// Explicitly pass a String argument, avoiding Log4j's argument expansion
// for message objects in case of "{}" sequences (SPR-16226)
if (exception != null) {
this.logger.logIfEnabled(FQCN, level, null, text, exception);
}
else {
this.logger.logIfEnabled(FQCN, level, null, text);
}
}
else {
this.logger.logIfEnabled(FQCN, level, null, message, exception);
}
}
protected Object readResolve() {
return new Log4jLog(this.name);
}
}
@SuppressWarnings("serial")
private static class Slf4jLog<T extends Logger> implements Log, Serializable {
protected final String name;
protected final transient T logger;
public Slf4jLog(T logger) {
this.name = logger.getName();
this.logger = logger;
}
@Override
public boolean isFatalEnabled() {
return isErrorEnabled();
}
@Override
public boolean isErrorEnabled() {
return this.logger.isErrorEnabled();
}
@Override
public boolean isWarnEnabled() {
return this.logger.isWarnEnabled();
}
@Override
public boolean isInfoEnabled() {
return this.logger.isInfoEnabled();
}
@Override
public boolean isDebugEnabled() {
return this.logger.isDebugEnabled();
}
@Override
public boolean isTraceEnabled() {
return this.logger.isTraceEnabled();
}
@Override
public void fatal(Object message) {
error(message);
}
@Override
public void fatal(Object message, Throwable exception) {
error(message, exception);
}
@Override
public void error(Object message) {
if (message instanceof String || this.logger.isErrorEnabled()) {
this.logger.error(String.valueOf(message));
}
}
@Override
public void error(Object message, Throwable exception) {
if (message instanceof String || this.logger.isErrorEnabled()) {
this.logger.error(String.valueOf(message), exception);
}
}
@Override
public void warn(Object message) {
if (message instanceof String || this.logger.isWarnEnabled()) {
this.logger.warn(String.valueOf(message));
}
}
@Override
public void warn(Object message, Throwable exception) {
if (message instanceof String || this.logger.isWarnEnabled()) {
this.logger.warn(String.valueOf(message), exception);
}
}
@Override
public void info(Object message) {
if (message instanceof String || this.logger.isInfoEnabled()) {
this.logger.info(String.valueOf(message));
}
}
@Override
public void info(Object message, Throwable exception) {
if (message instanceof String || this.logger.isInfoEnabled()) {
this.logger.info(String.valueOf(message), exception);
}
}
@Override
public void debug(Object message) {
if (message instanceof String || this.logger.isDebugEnabled()) {
this.logger.debug(String.valueOf(message));
}
}
@Override
public void debug(Object message, Throwable exception) {
if (message instanceof String || this.logger.isDebugEnabled()) {
this.logger.debug(String.valueOf(message), exception);
}
}
@Override
public void trace(Object message) {
if (message instanceof String || this.logger.isTraceEnabled()) {
this.logger.trace(String.valueOf(message));
}
}
@Override
public void trace(Object message, Throwable exception) {
if (message instanceof String || this.logger.isTraceEnabled()) {
this.logger.trace(String.valueOf(message), exception);
}
}
protected Object readResolve() {
return Slf4jAdapter.createLog(this.name);
}
}
@SuppressWarnings("serial")
private static class Slf4jLocationAwareLog extends Slf4jLog<LocationAwareLogger> implements Serializable {
private static final String FQCN = Slf4jLocationAwareLog.class.getName();
public Slf4jLocationAwareLog(LocationAwareLogger logger) {
super(logger);
}
@Override
public void fatal(Object message) {
error(message);
}
@Override
public void fatal(Object message, Throwable exception) {
error(message, exception);
}
@Override
public void error(Object message) {
if (message instanceof String || this.logger.isErrorEnabled()) {
this.logger.log(null, FQCN, LocationAwareLogger.ERROR_INT, String.valueOf(message), null, null);
}
}
@Override
public void error(Object message, Throwable exception) {
if (message instanceof String || this.logger.isErrorEnabled()) {
this.logger.log(null, FQCN, LocationAwareLogger.ERROR_INT, String.valueOf(message), null, exception);
}
}
@Override
public void warn(Object message) {
if (message instanceof String || this.logger.isWarnEnabled()) {
this.logger.log(null, FQCN, LocationAwareLogger.WARN_INT, String.valueOf(message), null, null);
}
}
@Override
public void warn(Object message, Throwable exception) {
if (message instanceof String || this.logger.isWarnEnabled()) {
this.logger.log(null, FQCN, LocationAwareLogger.WARN_INT, String.valueOf(message), null, exception);
}
}
@Override
public void info(Object message) {
if (message instanceof String || this.logger.isInfoEnabled()) {
this.logger.log(null, FQCN, LocationAwareLogger.INFO_INT, String.valueOf(message), null, null);
}
}
@Override
public void info(Object message, Throwable exception) {
if (message instanceof String || this.logger.isInfoEnabled()) {
this.logger.log(null, FQCN, LocationAwareLogger.INFO_INT, String.valueOf(message), null, exception);
}
}
@Override
public void debug(Object message) {
if (message instanceof String || this.logger.isDebugEnabled()) {
this.logger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, String.valueOf(message), null, null);
}
}
@Override
public void debug(Object message, Throwable exception) {
if (message instanceof String || this.logger.isDebugEnabled()) {
this.logger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, String.valueOf(message), null, exception);
}
}
@Override
public void trace(Object message) {
if (message instanceof String || this.logger.isTraceEnabled()) {
this.logger.log(null, FQCN, LocationAwareLogger.TRACE_INT, String.valueOf(message), null, null);
}
}
@Override
public void trace(Object message, Throwable exception) {
if (message instanceof String || this.logger.isTraceEnabled()) {
this.logger.log(null, FQCN, LocationAwareLogger.TRACE_INT, String.valueOf(message), null, exception);
}
}
@Override
protected Object readResolve() {
return Slf4jAdapter.createLocationAwareLog(this.name);
}
}
@SuppressWarnings("serial")
private static class JavaUtilLog implements Log, Serializable {
private final String name;
private final transient java.util.logging.Logger logger;
public JavaUtilLog(String name) {
this.name = name;
this.logger = java.util.logging.Logger.getLogger(name);
}
@Override
public boolean isFatalEnabled() {
return isErrorEnabled();
}
@Override
public boolean isErrorEnabled() {
return this.logger.isLoggable(java.util.logging.Level.SEVERE);
}
@Override
public boolean isWarnEnabled() {
return this.logger.isLoggable(java.util.logging.Level.WARNING);
}
@Override
public boolean isInfoEnabled() {
return this.logger.isLoggable(java.util.logging.Level.INFO);
}
@Override
public boolean isDebugEnabled() {
return this.logger.isLoggable(java.util.logging.Level.FINE);
}
@Override
public boolean isTraceEnabled() {
return this.logger.isLoggable(java.util.logging.Level.FINEST);
}
@Override
public void fatal(Object message) {
error(message);
}
@Override
public void fatal(Object message, Throwable exception) {
error(message, exception);
}
@Override
public void error(Object message) {
log(java.util.logging.Level.SEVERE, message, null);
}
@Override
public void error(Object message, Throwable exception) {
log(java.util.logging.Level.SEVERE, message, exception);
}
@Override
public void warn(Object message) {
log(java.util.logging.Level.WARNING, message, null);
}
@Override
public void warn(Object message, Throwable exception) {
log(java.util.logging.Level.WARNING, message, exception);
}
@Override
public void info(Object message) {
log(java.util.logging.Level.INFO, message, null);
}
@Override
public void info(Object message, Throwable exception) {
log(java.util.logging.Level.INFO, message, exception);
}
@Override
public void debug(Object message) {
log(java.util.logging.Level.FINE, message, null);
}
@Override
public void debug(Object message, Throwable exception) {
log(java.util.logging.Level.FINE, message, exception);
}
@Override
public void trace(Object message) {
log(java.util.logging.Level.FINEST, message, null);
}
@Override
public void trace(Object message, Throwable exception) {
log(java.util.logging.Level.FINEST, message, exception);
}
private void log(java.util.logging.Level level, Object message, Throwable exception) {
if (this.logger.isLoggable(level)) {
LogRecord rec;
if (message instanceof LogRecord logRecord) {
rec = logRecord;
}
else {
rec = new LocationResolvingLogRecord(level, String.valueOf(message));
rec.setLoggerName(this.name);
rec.setResourceBundleName(this.logger.getResourceBundleName());
rec.setResourceBundle(this.logger.getResourceBundle());
rec.setThrown(exception);
}
logger.log(rec);
}
}
protected Object readResolve() {
return new JavaUtilLog(this.name);
}
}
@SuppressWarnings("serial")
private static class LocationResolvingLogRecord extends LogRecord {
private static final String FQCN = JavaUtilLog.class.getName();
private volatile boolean resolved;
public LocationResolvingLogRecord(java.util.logging.Level level, String msg) {
super(level, msg);
}
@Override
public String getSourceClassName() {
if (!this.resolved) {
resolve();
}
return super.getSourceClassName();
}
@Override
public void setSourceClassName(String sourceClassName) {
super.setSourceClassName(sourceClassName);
this.resolved = true;
}
@Override
public String getSourceMethodName() {
if (!this.resolved) {
resolve();
}
return super.getSourceMethodName();
}
@Override
public void setSourceMethodName(String sourceMethodName) {
super.setSourceMethodName(sourceMethodName);
this.resolved = true;
}
private void resolve() {
StackTraceElement[] stack = new Throwable().getStackTrace();
String sourceClassName = null;
String sourceMethodName = null;
boolean found = false;
for (StackTraceElement element : stack) {
String className = element.getClassName();
if (FQCN.equals(className)) {
found = true;
}
else if (found) {
sourceClassName = className;
sourceMethodName = element.getMethodName();
break;
}
}
setSourceClassName(sourceClassName);
setSourceMethodName(sourceMethodName);
}
protected Object writeReplace() {
LogRecord serialized = new LogRecord(getLevel(), getMessage());
serialized.setLoggerName(getLoggerName());
serialized.setResourceBundle(getResourceBundle());
serialized.setResourceBundleName(getResourceBundleName());
serialized.setSourceClassName(getSourceClassName());
serialized.setSourceMethodName(getSourceMethodName());
serialized.setSequenceNumber(getSequenceNumber());
serialized.setParameters(getParameters());
serialized.setLongThreadID(getLongThreadID());
serialized.setInstant(getInstant());
serialized.setThrown(getThrown());
return serialized;
}
}
}

View File

@ -1,156 +0,0 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.logging;
/**
* A minimal incarnation of Apache Commons Logging's {@code LogFactory} API,
* providing just the common {@link Log} lookup methods. This is inspired
* by the JCL-over-SLF4J bridge and should be source as well as binary
* compatible with all common use of the Commons Logging API (in particular:
* with {@code LogFactory.getLog(Class/String)} field initializers).
*
* <p>This implementation does not support Commons Logging's original provider
* detection. It rather only checks for the presence of the Log4j 2.x API
* and the SLF4J 1.7 API in the Spring Framework classpath, falling back to
* {@code java.util.logging} if none of the two is available. In that sense,
* it works as a replacement for the Log4j 2 Commons Logging bridge as well as
* the JCL-over-SLF4J bridge, both of which become irrelevant for Spring-based
* setups as a consequence (with no need for manual excludes of the standard
* Commons Logging API jar anymore either). Furthermore, for simple setups
* without an external logging provider, Spring does not require any extra jar
* on the classpath anymore since this embedded log factory automatically
* delegates to {@code java.util.logging} in such a scenario.
*
* <p><b>Note that this Commons Logging variant is only meant to be used for
* infrastructure logging purposes in the core framework and in extensions.</b>
* It also serves as a common bridge for third-party libraries using the
* Commons Logging API, for example, Apache HttpClient, and HtmlUnit, bringing
* them into the same consistent arrangement without any extra bridge jars.
*
* <p><b>For logging need in application code, prefer direct use of Log4j 2.x
* or SLF4J or {@code java.util.logging}.</b> Simply put Log4j 2.x or Logback
* (or another SLF4J provider) onto your classpath, without any extra bridges,
* and let the framework auto-adapt to your choice.
*
* @author Juergen Hoeller (for the {@code spring-jcl} variant)
* @since 5.0
*/
public abstract class LogFactory {
/**
* Convenience method to return a named logger.
* @param clazz containing Class from which a log name will be derived
*/
public static Log getLog(Class<?> clazz) {
return getLog(clazz.getName());
}
/**
* Convenience method to return a named logger.
* @param name logical name of the <code>Log</code> instance to be returned
*/
public static Log getLog(String name) {
return LogAdapter.createLog(name);
}
/**
* This method only exists for compatibility with unusual Commons Logging API
* usage like, for example, {@code LogFactory.getFactory().getInstance(Class/String)}.
* @see #getInstance(Class)
* @see #getInstance(String)
* @deprecated in favor of {@link #getLog(Class)}/{@link #getLog(String)}
*/
@Deprecated
public static LogFactory getFactory() {
return new LogFactory() {
@Override
public Object getAttribute(String name) {
return null;
}
@Override
public String[] getAttributeNames() {
return new String[0];
}
@Override
public void removeAttribute(String name) {
}
@Override
public void setAttribute(String name, Object value) {
}
@Override
public void release() {
}
};
}
/**
* Convenience method to return a named logger.
* <p>This variant just dispatches straight to {@link #getLog(Class)}.
* @param clazz containing Class from which a log name will be derived
* @deprecated in favor of {@link #getLog(Class)}
*/
@Deprecated
public Log getInstance(Class<?> clazz) {
return getLog(clazz);
}
/**
* Convenience method to return a named logger.
* <p>This variant just dispatches straight to {@link #getLog(String)}.
* @param name logical name of the <code>Log</code> instance to be returned
* @deprecated in favor of {@link #getLog(String)}
*/
@Deprecated
public Log getInstance(String name) {
return getLog(name);
}
// Just in case some code happens to call uncommon Commons Logging methods...
@Deprecated
public abstract Object getAttribute(String name);
@Deprecated
public abstract String[] getAttributeNames();
@Deprecated
public abstract void removeAttribute(String name);
@Deprecated
public abstract void setAttribute(String name, Object value);
@Deprecated
public abstract void release();
@Deprecated
public static void release(ClassLoader classLoader) {
// do nothing
}
@Deprecated
public static void releaseAll() {
// do nothing
}
@Deprecated
public static String objectId(Object o) {
return (o == null ? "null" : o.getClass().getName() + "@" + System.identityHashCode(o));
}
}

View File

@ -1,87 +0,0 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.logging;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* A minimal subclass of the standard Apache Commons Logging's {@code LogFactory} class,
* overriding the abstract {@code getInstance} lookup methods. This is just applied in
* case of the standard {@code commons-logging} jar accidentally ending up on the classpath,
* with the standard {@code LogFactory} class performing its META-INF service discovery.
* This implementation simply delegates to Spring's common {@link Log} factory methods.
*
* @author Juergen Hoeller
* @since 5.1
* @deprecated since it is only meant to be used in the above-mentioned fallback scenario
*/
@Deprecated
public class LogFactoryService extends LogFactory {
private final Map<String, Object> attributes = new ConcurrentHashMap<>();
public LogFactoryService() {
System.out.println("Standard Commons Logging discovery in action with spring-jcl: " +
"please remove commons-logging.jar from classpath in order to avoid potential conflicts");
}
@Override
public Log getInstance(Class<?> clazz) {
return getInstance(clazz.getName());
}
@Override
public Log getInstance(String name) {
return LogAdapter.createLog(name);
}
// Just in case some code happens to rely on Commons Logging attributes...
@Override
public void setAttribute(String name, Object value) {
if (value != null) {
this.attributes.put(name, value);
}
else {
this.attributes.remove(name);
}
}
@Override
public void removeAttribute(String name) {
this.attributes.remove(name);
}
@Override
public Object getAttribute(String name) {
return this.attributes.get(name);
}
@Override
public String[] getAttributeNames() {
return this.attributes.keySet().toArray(new String[0]);
}
@Override
public void release() {
}
}

View File

@ -1,117 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.logging.impl;
import java.io.Serializable;
import org.apache.commons.logging.Log;
/**
* Trivial implementation of {@link Log} that throws away all messages.
*
* @author Juergen Hoeller (for the {@code spring-jcl} variant)
* @since 5.0
*/
@SuppressWarnings("serial")
public class NoOpLog implements Log, Serializable {
public NoOpLog() {
}
public NoOpLog(String name) {
}
@Override
public boolean isFatalEnabled() {
return false;
}
@Override
public boolean isErrorEnabled() {
return false;
}
@Override
public boolean isWarnEnabled() {
return false;
}
@Override
public boolean isInfoEnabled() {
return false;
}
@Override
public boolean isDebugEnabled() {
return false;
}
@Override
public boolean isTraceEnabled() {
return false;
}
@Override
public void fatal(Object message) {
}
@Override
public void fatal(Object message, Throwable t) {
}
@Override
public void error(Object message) {
}
@Override
public void error(Object message, Throwable t) {
}
@Override
public void warn(Object message) {
}
@Override
public void warn(Object message, Throwable t) {
}
@Override
public void info(Object message) {
}
@Override
public void info(Object message, Throwable t) {
}
@Override
public void debug(Object message) {
}
@Override
public void debug(Object message, Throwable t) {
}
@Override
public void trace(Object message) {
}
@Override
public void trace(Object message, Throwable t) {
}
}

View File

@ -1,40 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.logging.impl;
/**
* Originally a simple Commons Logging provider configured by system properties.
* Deprecated in {@code spring-jcl}, effectively equivalent to {@link NoOpLog}.
*
* <p>Instead of instantiating this directly, call {@code LogFactory#getLog(Class/String)}
* which will fall back to {@code java.util.logging} if neither Log4j nor SLF4J are present.
*
* @author Juergen Hoeller (for the {@code spring-jcl} variant)
* @since 5.0
* @deprecated in {@code spring-jcl} (effectively equivalent to {@link NoOpLog})
*/
@Deprecated
@SuppressWarnings("serial")
public class SimpleLog extends NoOpLog {
public SimpleLog(String name) {
super(name);
System.out.println(SimpleLog.class.getName() + " is deprecated and equivalent to NoOpLog in spring-jcl. " +
"Use a standard LogFactory.getLog(Class/String) call instead.");
}
}

View File

@ -1,11 +0,0 @@
/**
* Spring's variant of the
* <a href="https://commons.apache.org/logging">Commons Logging API</a>:
* with special support for Log4J 2, SLF4J and {@code java.util.logging}.
*
* <p>This {@code impl} package is only present for binary compatibility
* with existing Commons Logging usage, for example, in Commons Configuration.
* {@code NoOpLog} can be used as a {@code Log} fallback instance, and
* {@code SimpleLog} is not meant to work (issuing a warning when used).
*/
package org.apache.commons.logging.impl;

View File

@ -1,25 +0,0 @@
/**
* Spring's variant of the
* <a href="https://commons.apache.org/logging">Commons Logging API</a>:
* with special support for Log4J 2, SLF4J and {@code java.util.logging}.
*
* <p>This is a custom bridge along the lines of {@code jcl-over-slf4j}.
* You may exclude {@code spring-jcl} and switch to {@code jcl-over-slf4j}
* instead if you prefer the hard-bound SLF4J bridge. However, Spring's own
* bridge provides a better out-of-the-box experience when using Log4J 2
* or {@code java.util.logging}, with no extra bridge jars necessary, and
* also easier setup of SLF4J with Logback (no JCL exclude, no JCL bridge).
*
* <p>{@link org.apache.commons.logging.Log} is equivalent to the original.
* However, {@link org.apache.commons.logging.LogFactory} is a very different
* implementation which is minimized and optimized for Spring's purposes,
* detecting Log4J 2.x and SLF4J 1.7 in the framework classpath and falling
* back to {@code java.util.logging}. If you run into any issues with this
* implementation, consider excluding {@code spring-jcl} and switching to the
* standard {@code commons-logging} artifact or to {@code jcl-over-slf4j}.
*
* <p>Note that this Commons Logging bridge is only meant to be used for
* framework logging purposes, both in the core framework and in extensions.
* For applications, prefer direct use of Log4J/SLF4J or {@code java.util.logging}.
*/
package org.apache.commons.logging;

View File

@ -1 +0,0 @@
org.apache.commons.logging.LogFactoryService

View File

@ -65,10 +65,6 @@
<suppress files="SpelMessage" checks="JavadocVariable|JavadocStyle"/>
<suppress files="SpelReproTests" checks="InterfaceIsType"/>
<!-- spring-jcl -->
<suppress files="[\\/]src[\\/]main[\\/]java[\\/]org[\\/]apache[\\/]commons[\\/]logging[\\/]" checks="Header|SpringNoThis|IllegalImport"/>
<suppress files="[\\/]src[\\/]main[\\/]java[\\/]org[\\/]apache[\\/]commons[\\/]logging[\\/]" checks="RegexpSinglelineJava" id="systemOutErrPrint"/>
<!-- spring-jdbc -->
<suppress files="ResultSetWrappingSqlRowSet" checks="JavadocStyle"/>