LogFactoryService class for standard Commons Logging service discovery
Issue: SPR-16585 Issue: SPR-15903
This commit is contained in:
parent
8bffb6a798
commit
0b86c71b2a
|
|
@ -0,0 +1,640 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.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 delegate behind {@link LogFactory} and {@link LogFactoryService}.
|
||||
* Detects the presence of Log4j 2.x / SLF4J, falling back to {@code java.util.logging}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 5.1
|
||||
*/
|
||||
final class LogDelegate {
|
||||
|
||||
private static LogApi logApi = LogApi.JUL;
|
||||
|
||||
static {
|
||||
ClassLoader cl = LogDelegate.class.getClassLoader();
|
||||
try {
|
||||
// Try Log4j 2.x API
|
||||
cl.loadClass("org.apache.logging.log4j.spi.ExtendedLogger");
|
||||
logApi = LogApi.LOG4J;
|
||||
}
|
||||
catch (ClassNotFoundException ex1) {
|
||||
try {
|
||||
// Try SLF4J 1.7 SPI
|
||||
cl.loadClass("org.slf4j.spi.LocationAwareLogger");
|
||||
logApi = LogApi.SLF4J_LAL;
|
||||
}
|
||||
catch (ClassNotFoundException ex2) {
|
||||
try {
|
||||
// Try SLF4J 1.7 API
|
||||
cl.loadClass("org.slf4j.Logger");
|
||||
logApi = LogApi.SLF4J;
|
||||
}
|
||||
catch (ClassNotFoundException ex3) {
|
||||
// Keep java.util.logging as default
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private LogDelegate() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create an actual {@link Log} instance for the selected API.
|
||||
* @param name the logger name
|
||||
*/
|
||||
public static Log createLog(String name) {
|
||||
switch (logApi) {
|
||||
case LOG4J:
|
||||
return Log4jDelegate.createLog(name);
|
||||
case SLF4J_LAL:
|
||||
return Slf4jDelegate.createLocationAwareLog(name);
|
||||
case SLF4J:
|
||||
return Slf4jDelegate.createLog(name);
|
||||
default:
|
||||
// Defensively use lazy-initializing delegate 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 - e.g. by a JVM in debug mode - when eagerly
|
||||
// trying to parse the bytecode for all the cases of this switch clause.
|
||||
return JavaUtilDelegate.createLog(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private enum LogApi {LOG4J, SLF4J_LAL, SLF4J, JUL}
|
||||
|
||||
|
||||
private static class Log4jDelegate {
|
||||
|
||||
public static Log createLog(String name) {
|
||||
return new Log4jLog(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class Slf4jDelegate {
|
||||
|
||||
public static Log createLocationAwareLog(String name) {
|
||||
Logger logger = LoggerFactory.getLogger(name);
|
||||
return (logger instanceof LocationAwareLogger ?
|
||||
new Slf4jLocationAwareLog((LocationAwareLogger) logger) : new Slf4jLog<>(logger));
|
||||
}
|
||||
|
||||
public static Log createLog(String name) {
|
||||
return new Slf4jLog<>(LoggerFactory.getLogger(name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class JavaUtilDelegate {
|
||||
|
||||
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 ExtendedLogger logger;
|
||||
|
||||
public Log4jLog(String name) {
|
||||
this.logger = loggerContext.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) {
|
||||
// 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, (String) message, exception);
|
||||
}
|
||||
else {
|
||||
this.logger.logIfEnabled(FQCN, level, null, (String) message);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.logger.logIfEnabled(FQCN, level, null, message, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class Slf4jLog<T extends Logger> implements Log, Serializable {
|
||||
|
||||
protected final String name;
|
||||
|
||||
protected transient T logger;
|
||||
|
||||
public Slf4jLog(T logger) {
|
||||
this.name = logger.getName();
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public boolean isFatalEnabled() {
|
||||
return isErrorEnabled();
|
||||
}
|
||||
|
||||
public boolean isErrorEnabled() {
|
||||
return this.logger.isErrorEnabled();
|
||||
}
|
||||
|
||||
public boolean isWarnEnabled() {
|
||||
return this.logger.isWarnEnabled();
|
||||
}
|
||||
|
||||
public boolean isInfoEnabled() {
|
||||
return this.logger.isInfoEnabled();
|
||||
}
|
||||
|
||||
public boolean isDebugEnabled() {
|
||||
return this.logger.isDebugEnabled();
|
||||
}
|
||||
|
||||
public boolean isTraceEnabled() {
|
||||
return this.logger.isTraceEnabled();
|
||||
}
|
||||
|
||||
public void fatal(Object message) {
|
||||
error(message);
|
||||
}
|
||||
|
||||
public void fatal(Object message, Throwable exception) {
|
||||
error(message, exception);
|
||||
}
|
||||
|
||||
public void error(Object message) {
|
||||
if (message instanceof String || this.logger.isErrorEnabled()) {
|
||||
this.logger.error(String.valueOf(message));
|
||||
}
|
||||
}
|
||||
|
||||
public void error(Object message, Throwable exception) {
|
||||
if (message instanceof String || this.logger.isErrorEnabled()) {
|
||||
this.logger.error(String.valueOf(message), exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void warn(Object message) {
|
||||
if (message instanceof String || this.logger.isWarnEnabled()) {
|
||||
this.logger.warn(String.valueOf(message));
|
||||
}
|
||||
}
|
||||
|
||||
public void warn(Object message, Throwable exception) {
|
||||
if (message instanceof String || this.logger.isWarnEnabled()) {
|
||||
this.logger.warn(String.valueOf(message), exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void info(Object message) {
|
||||
if (message instanceof String || this.logger.isInfoEnabled()) {
|
||||
this.logger.info(String.valueOf(message));
|
||||
}
|
||||
}
|
||||
|
||||
public void info(Object message, Throwable exception) {
|
||||
if (message instanceof String || this.logger.isInfoEnabled()) {
|
||||
this.logger.info(String.valueOf(message), exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void debug(Object message) {
|
||||
if (message instanceof String || this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(String.valueOf(message));
|
||||
}
|
||||
}
|
||||
|
||||
public void debug(Object message, Throwable exception) {
|
||||
if (message instanceof String || this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(String.valueOf(message), exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void trace(Object message) {
|
||||
if (message instanceof String || this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(String.valueOf(message));
|
||||
}
|
||||
}
|
||||
|
||||
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 Slf4jDelegate.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 Slf4jDelegate.createLocationAwareLog(this.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class JavaUtilLog implements Log, Serializable {
|
||||
|
||||
private String name;
|
||||
|
||||
private transient java.util.logging.Logger logger;
|
||||
|
||||
public JavaUtilLog(String name) {
|
||||
this.name = name;
|
||||
this.logger = java.util.logging.Logger.getLogger(name);
|
||||
}
|
||||
|
||||
public boolean isFatalEnabled() {
|
||||
return isErrorEnabled();
|
||||
}
|
||||
|
||||
public boolean isErrorEnabled() {
|
||||
return this.logger.isLoggable(java.util.logging.Level.SEVERE);
|
||||
}
|
||||
|
||||
public boolean isWarnEnabled() {
|
||||
return this.logger.isLoggable(java.util.logging.Level.WARNING);
|
||||
}
|
||||
|
||||
public boolean isInfoEnabled() {
|
||||
return this.logger.isLoggable(java.util.logging.Level.INFO);
|
||||
}
|
||||
|
||||
public boolean isDebugEnabled() {
|
||||
return this.logger.isLoggable(java.util.logging.Level.FINE);
|
||||
}
|
||||
|
||||
public boolean isTraceEnabled() {
|
||||
return this.logger.isLoggable(java.util.logging.Level.FINEST);
|
||||
}
|
||||
|
||||
public void fatal(Object message) {
|
||||
error(message);
|
||||
}
|
||||
|
||||
public void fatal(Object message, Throwable exception) {
|
||||
error(message, exception);
|
||||
}
|
||||
|
||||
public void error(Object message) {
|
||||
log(java.util.logging.Level.SEVERE, message, null);
|
||||
}
|
||||
|
||||
public void error(Object message, Throwable exception) {
|
||||
log(java.util.logging.Level.SEVERE, message, exception);
|
||||
}
|
||||
|
||||
public void warn(Object message) {
|
||||
log(java.util.logging.Level.WARNING, message, null);
|
||||
}
|
||||
|
||||
public void warn(Object message, Throwable exception) {
|
||||
log(java.util.logging.Level.WARNING, message, exception);
|
||||
}
|
||||
|
||||
public void info(Object message) {
|
||||
log(java.util.logging.Level.INFO, message, null);
|
||||
}
|
||||
|
||||
public void info(Object message, Throwable exception) {
|
||||
log(java.util.logging.Level.INFO, message, exception);
|
||||
}
|
||||
|
||||
public void debug(Object message) {
|
||||
log(java.util.logging.Level.FINE, message, null);
|
||||
}
|
||||
|
||||
public void debug(Object message, Throwable exception) {
|
||||
log(java.util.logging.Level.FINE, message, exception);
|
||||
}
|
||||
|
||||
public void trace(Object message) {
|
||||
log(java.util.logging.Level.FINEST, message, null);
|
||||
}
|
||||
|
||||
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) {
|
||||
rec = (LogRecord) message;
|
||||
}
|
||||
else {
|
||||
rec = new LocationResolvingLogRecord(level, String.valueOf(message));
|
||||
rec.setLoggerName(this.name);
|
||||
rec.setResourceBundleName(logger.getResourceBundleName());
|
||||
rec.setResourceBundle(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);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // setMillis is deprecated in JDK 9
|
||||
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.setThreadID(getThreadID());
|
||||
serialized.setMillis(getMillis());
|
||||
serialized.setThrown(getThrown());
|
||||
return serialized;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,17 +16,6 @@
|
|||
|
||||
package org.apache.commons.logging;
|
||||
|
||||
import java.io.Serializable;
|
||||
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;
|
||||
|
||||
/**
|
||||
* A minimal incarnation of Apache Commons Logging's {@code LogFactory} API,
|
||||
* providing just the common {@link Log} lookup methods. This is inspired
|
||||
|
|
@ -62,35 +51,6 @@ import org.slf4j.spi.LocationAwareLogger;
|
|||
*/
|
||||
public abstract class LogFactory {
|
||||
|
||||
private static LogApi logApi = LogApi.JUL;
|
||||
|
||||
static {
|
||||
ClassLoader cl = LogFactory.class.getClassLoader();
|
||||
try {
|
||||
// Try Log4j 2.x API
|
||||
cl.loadClass("org.apache.logging.log4j.spi.ExtendedLogger");
|
||||
logApi = LogApi.LOG4J;
|
||||
}
|
||||
catch (ClassNotFoundException ex1) {
|
||||
try {
|
||||
// Try SLF4J 1.7 SPI
|
||||
cl.loadClass("org.slf4j.spi.LocationAwareLogger");
|
||||
logApi = LogApi.SLF4J_LAL;
|
||||
}
|
||||
catch (ClassNotFoundException ex2) {
|
||||
try {
|
||||
// Try SLF4J 1.7 API
|
||||
cl.loadClass("org.slf4j.Logger");
|
||||
logApi = LogApi.SLF4J;
|
||||
}
|
||||
catch (ClassNotFoundException ex3) {
|
||||
// Keep java.util.logging as default
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to return a named logger.
|
||||
* @param clazz containing Class from which a log name will be derived
|
||||
|
|
@ -104,24 +64,10 @@ public abstract class LogFactory {
|
|||
* @param name logical name of the <code>Log</code> instance to be returned
|
||||
*/
|
||||
public static Log getLog(String name) {
|
||||
switch (logApi) {
|
||||
case LOG4J:
|
||||
return Log4jDelegate.createLog(name);
|
||||
case SLF4J_LAL:
|
||||
return Slf4jDelegate.createLocationAwareLog(name);
|
||||
case SLF4J:
|
||||
return Slf4jDelegate.createLog(name);
|
||||
default:
|
||||
// Defensively use lazy-initializing delegate 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 - e.g. by a JVM in debug mode - when eagerly
|
||||
// trying to parse the bytecode for all the cases of this switch clause.
|
||||
return JavaUtilDelegate.createLog(name);
|
||||
}
|
||||
return LogDelegate.createLog(name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method only exists for compatibility with unusual Commons Logging API
|
||||
* usage like e.g. {@code LogFactory.getFactory().getInstance(Class/String)}.
|
||||
|
|
@ -156,549 +102,4 @@ public abstract class LogFactory {
|
|||
return getLog(name);
|
||||
}
|
||||
|
||||
|
||||
private enum LogApi {LOG4J, SLF4J_LAL, SLF4J, JUL}
|
||||
|
||||
|
||||
private static class Log4jDelegate {
|
||||
|
||||
public static Log createLog(String name) {
|
||||
return new Log4jLog(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class Slf4jDelegate {
|
||||
|
||||
public static Log createLocationAwareLog(String name) {
|
||||
Logger logger = LoggerFactory.getLogger(name);
|
||||
return (logger instanceof LocationAwareLogger ?
|
||||
new Slf4jLocationAwareLog((LocationAwareLogger) logger) : new Slf4jLog<>(logger));
|
||||
}
|
||||
|
||||
public static Log createLog(String name) {
|
||||
return new Slf4jLog<>(LoggerFactory.getLogger(name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class JavaUtilDelegate {
|
||||
|
||||
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 ExtendedLogger logger;
|
||||
|
||||
public Log4jLog(String name) {
|
||||
this.logger = loggerContext.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) {
|
||||
// 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, (String) message, exception);
|
||||
}
|
||||
else {
|
||||
this.logger.logIfEnabled(FQCN, level, null, (String) message);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.logger.logIfEnabled(FQCN, level, null, message, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class Slf4jLog<T extends Logger> implements Log, Serializable {
|
||||
|
||||
protected final String name;
|
||||
|
||||
protected transient T logger;
|
||||
|
||||
public Slf4jLog(T logger) {
|
||||
this.name = logger.getName();
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public boolean isFatalEnabled() {
|
||||
return isErrorEnabled();
|
||||
}
|
||||
|
||||
public boolean isErrorEnabled() {
|
||||
return this.logger.isErrorEnabled();
|
||||
}
|
||||
|
||||
public boolean isWarnEnabled() {
|
||||
return this.logger.isWarnEnabled();
|
||||
}
|
||||
|
||||
public boolean isInfoEnabled() {
|
||||
return this.logger.isInfoEnabled();
|
||||
}
|
||||
|
||||
public boolean isDebugEnabled() {
|
||||
return this.logger.isDebugEnabled();
|
||||
}
|
||||
|
||||
public boolean isTraceEnabled() {
|
||||
return this.logger.isTraceEnabled();
|
||||
}
|
||||
|
||||
public void fatal(Object message) {
|
||||
error(message);
|
||||
}
|
||||
|
||||
public void fatal(Object message, Throwable exception) {
|
||||
error(message, exception);
|
||||
}
|
||||
|
||||
public void error(Object message) {
|
||||
if (message instanceof String || this.logger.isErrorEnabled()) {
|
||||
this.logger.error(String.valueOf(message));
|
||||
}
|
||||
}
|
||||
|
||||
public void error(Object message, Throwable exception) {
|
||||
if (message instanceof String || this.logger.isErrorEnabled()) {
|
||||
this.logger.error(String.valueOf(message), exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void warn(Object message) {
|
||||
if (message instanceof String || this.logger.isWarnEnabled()) {
|
||||
this.logger.warn(String.valueOf(message));
|
||||
}
|
||||
}
|
||||
|
||||
public void warn(Object message, Throwable exception) {
|
||||
if (message instanceof String || this.logger.isWarnEnabled()) {
|
||||
this.logger.warn(String.valueOf(message), exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void info(Object message) {
|
||||
if (message instanceof String || this.logger.isInfoEnabled()) {
|
||||
this.logger.info(String.valueOf(message));
|
||||
}
|
||||
}
|
||||
|
||||
public void info(Object message, Throwable exception) {
|
||||
if (message instanceof String || this.logger.isInfoEnabled()) {
|
||||
this.logger.info(String.valueOf(message), exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void debug(Object message) {
|
||||
if (message instanceof String || this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(String.valueOf(message));
|
||||
}
|
||||
}
|
||||
|
||||
public void debug(Object message, Throwable exception) {
|
||||
if (message instanceof String || this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(String.valueOf(message), exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void trace(Object message) {
|
||||
if (message instanceof String || this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(String.valueOf(message));
|
||||
}
|
||||
}
|
||||
|
||||
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 Slf4jDelegate.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 Slf4jDelegate.createLocationAwareLog(this.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class JavaUtilLog implements Log, Serializable {
|
||||
|
||||
private String name;
|
||||
|
||||
private transient java.util.logging.Logger logger;
|
||||
|
||||
public JavaUtilLog(String name) {
|
||||
this.name = name;
|
||||
this.logger = java.util.logging.Logger.getLogger(name);
|
||||
}
|
||||
|
||||
public boolean isFatalEnabled() {
|
||||
return isErrorEnabled();
|
||||
}
|
||||
|
||||
public boolean isErrorEnabled() {
|
||||
return this.logger.isLoggable(java.util.logging.Level.SEVERE);
|
||||
}
|
||||
|
||||
public boolean isWarnEnabled() {
|
||||
return this.logger.isLoggable(java.util.logging.Level.WARNING);
|
||||
}
|
||||
|
||||
public boolean isInfoEnabled() {
|
||||
return this.logger.isLoggable(java.util.logging.Level.INFO);
|
||||
}
|
||||
|
||||
public boolean isDebugEnabled() {
|
||||
return this.logger.isLoggable(java.util.logging.Level.FINE);
|
||||
}
|
||||
|
||||
public boolean isTraceEnabled() {
|
||||
return this.logger.isLoggable(java.util.logging.Level.FINEST);
|
||||
}
|
||||
|
||||
public void fatal(Object message) {
|
||||
error(message);
|
||||
}
|
||||
|
||||
public void fatal(Object message, Throwable exception) {
|
||||
error(message, exception);
|
||||
}
|
||||
|
||||
public void error(Object message) {
|
||||
log(java.util.logging.Level.SEVERE, message, null);
|
||||
}
|
||||
|
||||
public void error(Object message, Throwable exception) {
|
||||
log(java.util.logging.Level.SEVERE, message, exception);
|
||||
}
|
||||
|
||||
public void warn(Object message) {
|
||||
log(java.util.logging.Level.WARNING, message, null);
|
||||
}
|
||||
|
||||
public void warn(Object message, Throwable exception) {
|
||||
log(java.util.logging.Level.WARNING, message, exception);
|
||||
}
|
||||
|
||||
public void info(Object message) {
|
||||
log(java.util.logging.Level.INFO, message, null);
|
||||
}
|
||||
|
||||
public void info(Object message, Throwable exception) {
|
||||
log(java.util.logging.Level.INFO, message, exception);
|
||||
}
|
||||
|
||||
public void debug(Object message) {
|
||||
log(java.util.logging.Level.FINE, message, null);
|
||||
}
|
||||
|
||||
public void debug(Object message, Throwable exception) {
|
||||
log(java.util.logging.Level.FINE, message, exception);
|
||||
}
|
||||
|
||||
public void trace(Object message) {
|
||||
log(java.util.logging.Level.FINEST, message, null);
|
||||
}
|
||||
|
||||
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) {
|
||||
rec = (LogRecord) message;
|
||||
}
|
||||
else {
|
||||
rec = new LocationResolvingLogRecord(level, String.valueOf(message));
|
||||
rec.setLoggerName(this.name);
|
||||
rec.setResourceBundleName(logger.getResourceBundleName());
|
||||
rec.setResourceBundle(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);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // setMillis is deprecated in JDK 9
|
||||
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.setThreadID(getThreadID());
|
||||
serialized.setMillis(getMillis());
|
||||
serialized.setThrown(getThrown());
|
||||
return serialized;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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 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 {
|
||||
|
||||
@Override
|
||||
public Log getInstance(Class<?> clazz) {
|
||||
return getInstance(clazz.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getInstance(String name) {
|
||||
return LogDelegate.createLog(name);
|
||||
}
|
||||
|
||||
|
||||
// Just in case some code happens to call Commons Logging's LogFactory.release()
|
||||
public void release() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
org.apache.commons.logging.LogFactoryService
|
||||
Loading…
Reference in New Issue