Slf4jLogFactory.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.logging.impl;

  18. import static org.slf4j.spi.LocationAwareLogger.DEBUG_INT;
  19. import static org.slf4j.spi.LocationAwareLogger.ERROR_INT;
  20. import static org.slf4j.spi.LocationAwareLogger.INFO_INT;
  21. import static org.slf4j.spi.LocationAwareLogger.TRACE_INT;
  22. import static org.slf4j.spi.LocationAwareLogger.WARN_INT;

  23. import java.util.concurrent.ConcurrentHashMap;
  24. import java.util.concurrent.ConcurrentMap;

  25. import org.apache.commons.logging.Log;
  26. import org.apache.commons.logging.LogConfigurationException;
  27. import org.apache.commons.logging.LogFactory;
  28. import org.slf4j.ILoggerFactory;
  29. import org.slf4j.Logger;
  30. import org.slf4j.LoggerFactory;
  31. import org.slf4j.Marker;
  32. import org.slf4j.MarkerFactory;
  33. import org.slf4j.spi.LocationAwareLogger;

  34. /**
  35.  * Logger factory hardcoded to send everything to SLF4J.
  36.  *
  37.  * @since 1.3.0
  38.  */
  39. public final class Slf4jLogFactory extends LogFactory {

  40.     private static final class Slf4jLocationAwareLog implements Log {

  41.         private static final String FQCN = Slf4jLocationAwareLog.class.getName();

  42.         private final LocationAwareLogger logger;

  43.         public Slf4jLocationAwareLog(final LocationAwareLogger logger) {
  44.             this.logger = logger;
  45.         }

  46.         @Override
  47.         public void debug(final Object message) {
  48.             log(DEBUG_INT, message, null);
  49.         }

  50.         @Override
  51.         public void debug(final Object message, final Throwable t) {
  52.             log(DEBUG_INT, message, t);
  53.         }

  54.         @Override
  55.         public void error(final Object message) {
  56.             log(ERROR_INT, message, null);
  57.         }

  58.         @Override
  59.         public void error(final Object message, final Throwable t) {
  60.             log(ERROR_INT, message, t);
  61.         }

  62.         @Override
  63.         public void fatal(final Object message) {
  64.             error(message);
  65.         }

  66.         @Override
  67.         public void fatal(final Object message, final Throwable t) {
  68.             error(message, t);
  69.         }

  70.         @Override
  71.         public void info(final Object message) {
  72.             log(INFO_INT, message, null);
  73.         }

  74.         @Override
  75.         public void info(final Object message, final Throwable t) {
  76.             log(INFO_INT, message, t);
  77.         }

  78.         @Override
  79.         public boolean isDebugEnabled() {
  80.             return logger.isDebugEnabled(MARKER);
  81.         }

  82.         @Override
  83.         public boolean isErrorEnabled() {
  84.             return logger.isErrorEnabled(MARKER);
  85.         }

  86.         @Override
  87.         public boolean isFatalEnabled() {
  88.             return isErrorEnabled();
  89.         }

  90.         @Override
  91.         public boolean isInfoEnabled() {
  92.             return logger.isInfoEnabled(MARKER);
  93.         }

  94.         @Override
  95.         public boolean isTraceEnabled() {
  96.             return logger.isTraceEnabled(MARKER);
  97.         }

  98.         @Override
  99.         public boolean isWarnEnabled() {
  100.             return logger.isWarnEnabled(MARKER);
  101.         }

  102.         private void log(final int level, final Object message, final Throwable t) {
  103.             logger.log(MARKER, FQCN, level, String.valueOf(message), EMPTY_OBJECT_ARRAY, t);
  104.         }

  105.         @Override
  106.         public void trace(final Object message) {
  107.             log(TRACE_INT, message, null);
  108.         }

  109.         @Override
  110.         public void trace(final Object message, final Throwable t) {
  111.             log(TRACE_INT, message, t);
  112.         }

  113.         @Override
  114.         public void warn(final Object message) {
  115.             log(WARN_INT, message, null);
  116.         }

  117.         @Override
  118.         public void warn(final Object message, final Throwable t) {
  119.             log(WARN_INT, message, t);
  120.         }
  121.     }
  122.     private static class Slf4jLog implements Log {

  123.         private final Logger logger;

  124.         public Slf4jLog(final Logger logger) {
  125.             this.logger = logger;
  126.         }

  127.         @Override
  128.         public void debug(final Object message) {
  129.             logger.debug(MARKER, String.valueOf(message));
  130.         }

  131.         @Override
  132.         public void debug(final Object message, final Throwable t) {
  133.             logger.debug(MARKER, String.valueOf(message), t);
  134.         }

  135.         @Override
  136.         public void error(final Object message) {
  137.             logger.error(MARKER, String.valueOf(message));
  138.         }

  139.         @Override
  140.         public void error(final Object message, final Throwable t) {
  141.             logger.debug(MARKER, String.valueOf(message), t);
  142.         }

  143.         @Override
  144.         public void fatal(final Object message) {
  145.             error(message);
  146.         }

  147.         @Override
  148.         public void fatal(final Object message, final Throwable t) {
  149.             error(message, t);
  150.         }

  151.         @Override
  152.         public void info(final Object message) {
  153.             logger.info(MARKER, String.valueOf(message));
  154.         }

  155.         @Override
  156.         public void info(final Object message, final Throwable t) {
  157.             logger.info(MARKER, String.valueOf(message), t);
  158.         }

  159.         @Override
  160.         public boolean isDebugEnabled() {
  161.             return logger.isDebugEnabled(MARKER);
  162.         }

  163.         @Override
  164.         public boolean isErrorEnabled() {
  165.             return logger.isErrorEnabled(MARKER);
  166.         }

  167.         @Override
  168.         public boolean isFatalEnabled() {
  169.             return isErrorEnabled();
  170.         }

  171.         @Override
  172.         public boolean isInfoEnabled() {
  173.             return logger.isInfoEnabled(MARKER);
  174.         }

  175.         @Override
  176.         public boolean isTraceEnabled() {
  177.             return logger.isTraceEnabled(MARKER);
  178.         }

  179.         @Override
  180.         public boolean isWarnEnabled() {
  181.             return logger.isWarnEnabled(MARKER);
  182.         }

  183.         @Override
  184.         public void trace(final Object message) {
  185.             logger.trace(MARKER, String.valueOf(message));
  186.         }

  187.         @Override
  188.         public void trace(final Object message, final Throwable t) {
  189.             logger.trace(MARKER, String.valueOf(message), t);
  190.         }

  191.         @Override
  192.         public void warn(final Object message) {
  193.             logger.warn(MARKER, String.valueOf(message));
  194.         }

  195.         @Override
  196.         public void warn(final Object message, final Throwable t) {
  197.             logger.warn(MARKER, String.valueOf(message), t);
  198.         }
  199.     }

  200.     private static final Object[] EMPTY_OBJECT_ARRAY = {};

  201.     private static final String[] EMPTY_STRING_ARRAY = {};

  202.     /**
  203.      * Marker used by all messages coming from Apache Commons Logging.
  204.      */
  205.     private static final Marker MARKER = MarkerFactory.getMarker("COMMONS-LOGGING");

  206.     /**
  207.      * Caches Log instances.
  208.      * <p>
  209.      * The SLF4J reference implementation (Logback) has a single logger context, so each call to
  210.      * {@link #getInstance(String)}
  211.      * should give the same result.
  212.      * </p>
  213.      */
  214.     private final ConcurrentMap<String, Log> loggers = new ConcurrentHashMap<>();

  215.     private final ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<>();

  216.     /**
  217.      * Constructs a new instance.
  218.      */
  219.     public Slf4jLogFactory() {
  220.         // empty
  221.     }

  222.     @Override
  223.     public Object getAttribute(final String name) {
  224.         return attributes.get(name);
  225.     }

  226.     @Override
  227.     public String[] getAttributeNames() {
  228.         return attributes.keySet().toArray(EMPTY_STRING_ARRAY);
  229.     }

  230.     @Override
  231.     public Log getInstance(final Class<?> clazz) throws LogConfigurationException {
  232.         return getInstance(clazz.getName());
  233.     }

  234.     @Override
  235.     public Log getInstance(final String name) {
  236.         return loggers.computeIfAbsent(name, n -> {
  237.             final Logger logger = LoggerFactory.getLogger(n);
  238.             return logger instanceof LocationAwareLogger ? new Slf4jLocationAwareLog((LocationAwareLogger) logger) : new Slf4jLog(
  239.                     logger);
  240.         });
  241.     }

  242.     /**
  243.      * This method is supposed to clear all loggers.
  244.      * <p>
  245.      * In this implementation it calls a "stop" method if the logger factory supports it. This is the case of
  246.      * Logback.
  247.      * </p>
  248.      */
  249.     @Override
  250.     public void release() {
  251.         final ILoggerFactory factory = LoggerFactory.getILoggerFactory();
  252.         try {
  253.             factory.getClass().getMethod("stop").invoke(factory);
  254.         } catch (final ReflectiveOperationException ignored) {
  255.             // empty
  256.         }
  257.     }

  258.     @Override
  259.     public void removeAttribute(final String name) {
  260.         attributes.remove(name);
  261.     }

  262.     @Override
  263.     public void setAttribute(final String name, final Object value) {
  264.         if (value != null) {
  265.             attributes.put(name, value);
  266.         } else {
  267.             removeAttribute(name);
  268.         }
  269.     }
  270. }