    001/*
    002 * Copyright 2001-2004 The Apache Software Foundation.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *      http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    013 * See the License for the specific language governing permissions and
    014 * limitations under the License.
    015 */
    016
    017package org.apache.log4j;
    018
    019import org.apache.log4j.helpers.NullEnumeration;
    020import org.slf4j.LoggerFactory;
    021import org.slf4j.Marker;
    022import org.slf4j.MarkerFactory;
    023import org.slf4j.spi.LocationAwareLogger;
    024
    025import java.util.Enumeration;
    026
    027/**
    028 * <p>
    029 * This class is a minimal implementation of the original
    030 * <code>org.apache.log4j.Category</code> class (as found in log4j 1.2) by
    031 * delegation of all calls to a {@link org.slf4j.Logger} instance.
    032 * </p>
    033 *
    034 * <p>
    035 * Log4j's <code>trace</code>, <code>debug()</code>, <code>info()</code>,
    036 * <code>warn()</code>, <code>error()</code> printing methods are directly
    037 * mapped to their SLF4J equivalents. Log4j's <code>fatal()</code> printing
    038 * method is mapped to SLF4J's <code>error()</code> method with a FATAL marker.
    039 *
    040 * @author S&eacute;bastien Pennec
    041 * @author Ceki G&uuml;lc&uuml;
    042 */
    043@SuppressWarnings("rawtypes")
    044public class Category {
    045
    046    private static final String CATEGORY_FQCN = Category.class.getName();
    047
    048    private String name;
    049
    050    protected org.slf4j.Logger slf4jLogger;
    051    private org.slf4j.spi.LocationAwareLogger locationAwareLogger;
    052
    053    private static Marker FATAL_MARKER = MarkerFactory.getMarker("FATAL");
    054
    055    Category(String name) {
    056        this.name = name;
    057        slf4jLogger = LoggerFactory.getLogger(name);
    058        if (slf4jLogger instanceof LocationAwareLogger) {
    059            locationAwareLogger = (LocationAwareLogger) slf4jLogger;
    060        }
    061    }
    062
    063    public static Category getInstance(Class clazz) {
    064        return Log4jLoggerFactory.getLogger(clazz.getName());
    065    }
    066
    067    public static Category getInstance(String name) {
    068        return Log4jLoggerFactory.getLogger(name);
    069    }
    070
    071    public final Category getParent() {
    072        return null;
    073    }
    074
    075    /**
    076     * Returns the obvious.
    077     *
    078     * @return
    079     */
    080    public String getName() {
    081        return name;
    082    }
    083
    084    public Appender getAppender(String name) {
    085        return null;
    086    }
    087
    088    public Enumeration getAllAppenders() {
    089        return NullEnumeration.getInstance();
    090    }
    091
    092    /**
    093     * Return the level in effect for this category/logger.
    094     *
    095     * <p>
    096     * The result is computed by simulation.
    097     *
    098     * @return
    099     */
    100    public Level getEffectiveLevel() {
    101        if (slf4jLogger.isTraceEnabled()) {
    102            return Level.TRACE;
    103        }
    104        if (slf4jLogger.isDebugEnabled()) {
    105            return Level.DEBUG;
    106        }
    107        if (slf4jLogger.isInfoEnabled()) {
    108            return Level.INFO;
    109        }
    110        if (slf4jLogger.isWarnEnabled()) {
    111            return Level.WARN;
    112        }
    113        return Level.ERROR;
    114    }
    115
    116    /**
    117     * Returns the assigned {@link Level}, if any, for this Category. This
    118     * implementation always returns null.
    119     *
    120     * @return Level - the assigned Level, can be <code>null</code>.
    121     */
    122    final public Level getLevel() {
    123        return null;
    124    }
    125
    126    /**
    127     * @deprecated Please use {@link #getLevel} instead.
    128     */
    129    final public Level getPriority() {
    130        return null;
    131    }
    132
    133    /**
    134     * Delegates to {@link org.slf4j.Logger#isDebugEnabled} method in SLF4J
    135     */
    136    public boolean isDebugEnabled() {
    137        return slf4jLogger.isDebugEnabled();
    138    }
    139
    140    /**
    141     * Delegates to {@link org.slf4j.Logger#isInfoEnabled} method in SLF4J
    142     */
    143    public boolean isInfoEnabled() {
    144        return slf4jLogger.isInfoEnabled();
    145    }
    146
    147    /**
    148     * Delegates to {@link org.slf4j.Logger#isWarnEnabled} method in SLF4J
    149     */
    150    public boolean isWarnEnabled() {
    151        return slf4jLogger.isWarnEnabled();
    152    }
    153
    154    /**
    155     * Delegates to {@link org.slf4j.Logger#isErrorEnabled} method in SLF4J
    156     */
    157    public boolean isErrorEnabled() {
    158        return slf4jLogger.isErrorEnabled();
    159    }
    160
    161    /**
    162     * Determines whether the priority passed as parameter is enabled in the
    163     * underlying SLF4J logger. Each log4j priority is mapped directly to its
    164     * SLF4J equivalent, except for FATAL which is mapped as ERROR.
    165     *
    166     * @param p
    167     *          the priority to check against
    168     * @return true if this logger is enabled for the given level, false
    169     *         otherwise.
    170     */
    171    public boolean isEnabledFor(Priority p) {
    172        switch (p.level) {
    173        case Level.TRACE_INT:
    174            return slf4jLogger.isTraceEnabled();
    175        case Level.DEBUG_INT:
    176            return slf4jLogger.isDebugEnabled();
    177        case Level.INFO_INT:
    178            return slf4jLogger.isInfoEnabled();
    179        case Level.WARN_INT:
    180            return slf4jLogger.isWarnEnabled();
    181        case Level.ERROR_INT:
    182            return slf4jLogger.isErrorEnabled();
    183        case Priority.FATAL_INT:
    184            return slf4jLogger.isErrorEnabled();
    185        }
    186        return false;
    187    }
    188
    189    void differentiatedLog(Marker marker, String fqcn, int level, Object message, Throwable t) {
    190
    191        String m = convertToString(message);
    192        if (locationAwareLogger != null) {
    193            locationAwareLogger.log(marker, fqcn, level, m, null, t);
    194        } else {
    195            switch (level) {
    196            case LocationAwareLogger.TRACE_INT:
    197                slf4jLogger.trace(marker, m);
    198                break;
    199            case LocationAwareLogger.DEBUG_INT:
    200                slf4jLogger.debug(marker, m);
    201                break;
    202            case LocationAwareLogger.INFO_INT:
    203                slf4jLogger.info(marker, m);
    204                break;
    205            case LocationAwareLogger.WARN_INT:
    206                slf4jLogger.warn(marker, m);
    207                break;
    208            case LocationAwareLogger.ERROR_INT:
    209                slf4jLogger.error(marker, m);
    210                break;
    211            }
    212        }
    213    }
    214
    215    /**
    216     * Delegates to {@link org.slf4j.Logger#debug(String)} method of SLF4J.
    217     */
    218    public void debug(Object message) {
    219        differentiatedLog(null, CATEGORY_FQCN, LocationAwareLogger.DEBUG_INT, message, null);
    220    }
    221
    222    /**
    223     * Delegates to {@link org.slf4j.Logger#debug(String,Throwable)} method in
    224     * SLF4J.
    225     */
    226    public void debug(Object message, Throwable t) {
    227        differentiatedLog(null, CATEGORY_FQCN, LocationAwareLogger.DEBUG_INT, message, t);
    228    }
    229
    230    /**
    231     * Delegates to {@link org.slf4j.Logger#info(String)} method in SLF4J.
    232     */
    233    public void info(Object message) {
    234        differentiatedLog(null, CATEGORY_FQCN, LocationAwareLogger.INFO_INT, message, null);
    235    }
    236
    237    /**
    238     * Delegates to {@link org.slf4j.Logger#info(String,Throwable)} method in
    239     * SLF4J.
    240     */
    241    public void info(Object message, Throwable t) {
    242        differentiatedLog(null, CATEGORY_FQCN, LocationAwareLogger.INFO_INT, message, t);
    243    }
    244
    245    /**
    246     * Delegates to {@link org.slf4j.Logger#warn(String)} method in SLF4J.
    247     */
    248    public void warn(Object message) {
    249        differentiatedLog(null, CATEGORY_FQCN, LocationAwareLogger.WARN_INT, message, null);
    250    }
    251
    252    /**
    253     * Delegates to {@link org.slf4j.Logger#warn(String,Throwable)} method in
    254     * SLF4J.
    255     */
    256    public void warn(Object message, Throwable t) {
    257        differentiatedLog(null, CATEGORY_FQCN, LocationAwareLogger.WARN_INT, message, t);
    258    }
    259
    260    /**
    261     * Delegates to {@link org.slf4j.Logger#error(String)} method in SLF4J.
    262     */
    263    public void error(Object message) {
    264        differentiatedLog(null, CATEGORY_FQCN, LocationAwareLogger.ERROR_INT, message, null);
    265    }
    266
    267    /**
    268     * Delegates to {@link org.slf4j.Logger#error(String,Throwable)} method in
    269     * SLF4J.
    270     */
    271    public void error(Object message, Throwable t) {
    272        differentiatedLog(null, CATEGORY_FQCN, LocationAwareLogger.ERROR_INT, message, t);
    273    }
    274
    275    /**
    276     * Delegates to {@link org.slf4j.Logger#error(String)} method in SLF4J.
    277     */
    278    public void fatal(Object message) {
    279        differentiatedLog(FATAL_MARKER, CATEGORY_FQCN, LocationAwareLogger.ERROR_INT, message, null);
    280    }
    281
    282    /**
    283     * Delegates to {@link org.slf4j.Logger#error(String,Throwable)} method in
    284     * SLF4J. In addition, the call is marked with a marker named "FATAL".
    285     */
    286    public void fatal(Object message, Throwable t) {
    287        differentiatedLog(FATAL_MARKER, CATEGORY_FQCN, LocationAwareLogger.ERROR_INT, message, t);
    288    }
    289
    290    protected void forcedLog(String FQCN, Priority p, Object msg, Throwable t) {
    291        log(FQCN, p, msg, t);
    292    }
    293
    294    // See also http://jira.qos.ch/browse/SLF4J-159
    295    public void log(String FQCN, Priority p, Object msg, Throwable t) {
    296        int levelInt = priorityToLevelInt(p);
    297        differentiatedLog(null, FQCN, levelInt, msg, t);
    298    }
    299
    300    public void log(Priority p, Object message, Throwable t) {
    301        int levelInt = priorityToLevelInt(p);
    302        differentiatedLog(null, CATEGORY_FQCN, levelInt, message, t);
    303    }
    304
    305    public void log(Priority p, Object message) {
    306        int levelInt = priorityToLevelInt(p);
    307        differentiatedLog(null, CATEGORY_FQCN, levelInt, message, null);
    308    }
    309
    310    private int priorityToLevelInt(Priority p) {
    311        switch (p.level) {
    312        case Level.TRACE_INT:
    313        case Level.X_TRACE_INT:
    314            return LocationAwareLogger.TRACE_INT;
    315        case Priority.DEBUG_INT:
    316            return LocationAwareLogger.DEBUG_INT;
    317        case Priority.INFO_INT:
    318            return LocationAwareLogger.INFO_INT;
    319        case Priority.WARN_INT:
    320            return LocationAwareLogger.WARN_INT;
    321        case Priority.ERROR_INT:
    322            return LocationAwareLogger.ERROR_INT;
    323        case Priority.FATAL_INT:
    324            return LocationAwareLogger.ERROR_INT;
    325        default:
    326            throw new IllegalStateException("Unknown Priority " + p);
    327        }
    328    }
    329
    330    protected final String convertToString(Object message) {
    331        if (message == null) {
    332            return (String) message;
    333        } else {
    334            return message.toString();
    335        }
    336    }
    337
    338    public void setAdditivity(boolean additive) {
    339        // nothing to do
    340    }
    341
    342    public void addAppender(Appender newAppender) {
    343        // nothing to do
    344    }
    345
    346    public void setLevel(Level level) {
    347        // nothing to do
    348    }
    349
    350    public boolean getAdditivity() {
    351        return false;
    352    }
    353
    354    public void assertLog(boolean assertion, String msg) {
    355        if (!assertion)
    356            error(msg);
    357    }
    358
    359}