diff --git a/spring-jcl/src/main/java/org/apache/commons/logging/LogDelegate.java b/spring-jcl/src/main/java/org/apache/commons/logging/LogDelegate.java new file mode 100644 index 0000000000..41c71012c2 --- /dev/null +++ b/spring-jcl/src/main/java/org/apache/commons/logging/LogDelegate.java @@ -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 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 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; + } + } + +} diff --git a/spring-jcl/src/main/java/org/apache/commons/logging/LogFactory.java b/spring-jcl/src/main/java/org/apache/commons/logging/LogFactory.java index d18f89ec97..0484350277 100644 --- a/spring-jcl/src/main/java/org/apache/commons/logging/LogFactory.java +++ b/spring-jcl/src/main/java/org/apache/commons/logging/LogFactory.java @@ -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 Log 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 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 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; - } - } - } diff --git a/spring-jcl/src/main/java/org/apache/commons/logging/LogFactoryService.java b/spring-jcl/src/main/java/org/apache/commons/logging/LogFactoryService.java new file mode 100644 index 0000000000..af8d81095c --- /dev/null +++ b/spring-jcl/src/main/java/org/apache/commons/logging/LogFactoryService.java @@ -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() { + } + +} diff --git a/spring-jcl/src/main/resources/META-INF/services/org.apache.commons.logging.LogFactory b/spring-jcl/src/main/resources/META-INF/services/org.apache.commons.logging.LogFactory new file mode 100644 index 0000000000..375a5aa79f --- /dev/null +++ b/spring-jcl/src/main/resources/META-INF/services/org.apache.commons.logging.LogFactory @@ -0,0 +1 @@ +org.apache.commons.logging.LogFactoryService \ No newline at end of file