    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *     http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017
    018package org.apache.commons.configuration2.io;
    019
    020import org.apache.commons.logging.Log;
    021import org.apache.commons.logging.LogFactory;
    022import org.apache.commons.logging.impl.NoOpLog;
    023
    024/**
    025 * <p>
    026 * A class providing basic logging capabilities.
    027 * </p>
    028 * <p>
    029 * When reading configuration files in complex scenarios having log output is useful for diagnostic purposes. Therefore,
    030 * <em>Commons Configuration</em> produces some logging output. As concrete projects have different requirements on the
    031 * amount and detail of logging, there is a way of configuring logging: All classes derived from
    032 * {@link org.apache.commons.configuration2.AbstractConfiguration} can be assigned a logger which is then used for all
    033 * log statements generated.
    034 * </p>
    035 * <p>
    036 * Allowing a logger object to be passed to a configuration creates a direct dependency to a concrete logging framework
    037 * in the configuration API. This would make it impossible to switch to an alternative logging framework without
    038 * breaking backwards compatibility. To avoid this, the {@code ConfigurationLogger} class is introduced. It is a minimum
    039 * abstraction over a logging framework offering only very basic logging capabilities. The methods defined in this class
    040 * are used by configuration implementations to produce their logging statements. Client applications can create
    041 * specialized instances and pass them to configuration objects without having to deal with a concrete logging
    042 * framework. It is even possible to create a subclass that uses a completely different logging framework.
    043 * </p>
    044 *
    045 * @since 2.0
    046 */
    047public class ConfigurationLogger {
    048    /** The internal logger. */
    049    private final Log log;
    050
    051    /**
    052     * Creates a new instance of {@code ConfigurationLogger} that uses the specified logger name.
    053     *
    054     * @param loggerName the logger name (must not be <b>null</b>)
    055     * @throws IllegalArgumentException if the logger name is <b>null</b>
    056     */
    057    public ConfigurationLogger(final String loggerName) {
    058        this(createLoggerForName(loggerName));
    059    }
    060
    061    /**
    062     * Creates a new instance of {@code ConfigurationLogger} that uses a logger whose name is derived from the provided
    063     * class.
    064     *
    065     * @param logCls the class whose name is to be used for logging (must not be <b>null</b>)
    066     * @throws IllegalArgumentException if the logger class is <b>null</b>
    067     */
    068    public ConfigurationLogger(final Class<?> logCls) {
    069        this(createLoggerForClass(logCls));
    070    }
    071
    072    /**
    073     * Creates a new, uninitialized instance of {@code ConfigurationLogger}. This constructor can be used by derived classes
    074     * that implement their own specific logging mechanism. Such classes must override all methods because the default
    075     * implementations do not work in this uninitialized state.
    076     */
    077    protected ConfigurationLogger() {
    078        this((Log) null);
    079    }
    080
    081    /**
    082     * Creates a new instance of {@code ConfigurationLogger} which wraps the specified logger.
    083     *
    084     * @param wrapped the logger to be wrapped
    085     */
    086    ConfigurationLogger(final Log wrapped) {
    087        log = wrapped;
    088    }
    089
    090    /**
    091     * Creates a new dummy logger which produces no output. If such a logger is passed to a configuration object, logging is
    092     * effectively disabled.
    093     *
    094     * @return the new dummy logger
    095     */
    096    public static ConfigurationLogger newDummyLogger() {
    097        return new ConfigurationLogger(new NoOpLog());
    098    }
    099
    100    /**
    101     * Returns a flag whether logging on debug level is enabled.
    102     *
    103     * @return <b>true</b> if debug logging is enabled, <b>false</b> otherwise
    104     */
    105    public boolean isDebugEnabled() {
    106        return getLog().isDebugEnabled();
    107    }
    108
    109    /**
    110     * Logs the specified message on debug level.
    111     *
    112     * @param msg the message to be logged
    113     */
    114    public void debug(final String msg) {
    115        getLog().debug(msg);
    116    }
    117
    118    /**
    119     * Returns a flag whether logging on info level is enabled.
    120     *
    121     * @return <b>true</b> if debug logging is enabled, <b>false</b> otherwise
    122     */
    123    public boolean isInfoEnabled() {
    124        return getLog().isInfoEnabled();
    125    }
    126
    127    /**
    128     * Logs the specified message on info level.
    129     *
    130     * @param msg the message to be logged
    131     */
    132    public void info(final String msg) {
    133        getLog().info(msg);
    134    }
    135
    136    /**
    137     * Logs the specified message on warn level.
    138     *
    139     * @param msg the message to be logged
    140     */
    141    public void warn(final String msg) {
    142        getLog().warn(msg);
    143    }
    144
    145    /**
    146     * Logs the specified exception on warn level.
    147     *
    148     * @param msg the message to be logged
    149     * @param ex the exception to be logged
    150     */
    151    public void warn(final String msg, final Throwable ex) {
    152        getLog().warn(msg, ex);
    153    }
    154
    155    /**
    156     * Logs the specified message on error level.
    157     *
    158     * @param msg the message to be logged
    159     */
    160    public void error(final String msg) {
    161        getLog().error(msg);
    162    }
    163
    164    /**
    165     * Logs the specified exception on error level.
    166     *
    167     * @param msg the message to be logged
    168     * @param ex the exception to be logged
    169     */
    170    public void error(final String msg, final Throwable ex) {
    171        getLog().error(msg, ex);
    172    }
    173
    174    /**
    175     * Returns the internal logger.
    176     *
    177     * @return the internal logger
    178     */
    179    Log getLog() {
    180        return log;
    181    }
    182
    183    /**
    184     * Creates an internal logger for the given name. Throws an exception if the name is undefined.
    185     *
    186     * @param name the name of the logger
    187     * @return the logger object
    188     * @throws IllegalArgumentException if the logger name is undefined
    189     */
    190    private static Log createLoggerForName(final String name) {
    191        if (name == null) {
    192            throw new IllegalArgumentException("Logger name must not be null!");
    193        }
    194        return LogFactory.getLog(name);
    195    }
    196
    197    /**
    198     * Creates an internal logger for the given class. Throws an exception if the class is undefined.
    199     *
    200     * @param cls the logger class
    201     * @return the logger object
    202     * @throws IllegalArgumentException if the logger class is undefined
    203     */
    204    private static Log createLoggerForClass(final Class<?> cls) {
    205        if (cls == null) {
    206            throw new IllegalArgumentException("Logger class must not be null!");
    207        }
    208        return LogFactory.getLog(cls);
    209    }
    210}