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
030 * useful for diagnostic purposes. Therefore, <em>Commons Configuration</em>
031 * produces some logging output. As concrete projects have different
032 * requirements on the amount and detail of logging, there is a way of
033 * configuring logging: All classes derived from
034 * {@link org.apache.commons.configuration2.AbstractConfiguration}
035 * can be assigned a logger which is then used for all log statements generated.
036 * </p>
037 * <p>
038 * Allowing a logger object to be passed to a configuration creates a direct
039 * dependency to a concrete logging framework in the configuration API. This
040 * would make it impossible to switch to an alternative logging framework
041 * without breaking backwards compatibility. To avoid this, the
042 * {@code ConfigurationLogger} class is introduced. It is a minimum abstraction
043 * over a logging framework offering only very basic logging capabilities. The
044 * methods defined in this class are used by configuration implementations to
045 * produce their logging statements. Client applications can create specialized
046 * instances and pass them to configuration objects without having to deal with
047 * a concrete logging framework. It is even possible to create a subclass that
048 * uses a completely different logging framework.
049 * </p>
050 *
051 * @version $Id: ConfigurationLogger.java 1735903 2016-03-20 20:47:23Z oheger $
052 * @since 2.0
053 */
054public class ConfigurationLogger
055{
056    /** The internal logger. */
057    private final Log log;
058
059    /**
060     * Creates a new instance of {@code ConfigurationLogger} that uses the
061     * specified logger name.
062     *
063     * @param loggerName the logger name (must not be <b>null</b>)
064     * @throws IllegalArgumentException if the logger name is <b>null</b>
065     */
066    public ConfigurationLogger(String loggerName)
067    {
068        this(createLoggerForName(loggerName));
069    }
070
071    /**
072     * Creates a new instance of {@code ConfigurationLogger} that uses a logger
073     * whose name is derived from the provided class.
074     *
075     * @param logCls the class whose name is to be used for logging (must not be
076     *        <b>null</b>)
077     * @throws IllegalArgumentException if the logger class is <b>null</b>
078     */
079    public ConfigurationLogger(Class<?> logCls)
080    {
081        this(createLoggerForClass(logCls));
082    }
083
084    /**
085     * Creates a new, uninitialized instance of {@code ConfigurationLogger}.
086     * This constructor can be used by derived classes that implement their own
087     * specific logging mechanism. Such classes must override all methods
088     * because the default implementations do not work in this uninitialized
089     * state.
090     */
091    protected ConfigurationLogger()
092    {
093        this((Log) null);
094    }
095
096    /**
097     * Creates a new instance of {@code ConfigurationLogger} which wraps the
098     * specified logger.
099     *
100     * @param wrapped the logger to be wrapped
101     */
102    ConfigurationLogger(Log wrapped)
103    {
104        log = wrapped;
105    }
106
107    /**
108     * Creates a new dummy logger which produces no output. If such a logger is
109     * passed to a configuration object, logging is effectively disabled.
110     *
111     * @return the new dummy logger
112     */
113    public static ConfigurationLogger newDummyLogger()
114    {
115        return new ConfigurationLogger(new NoOpLog());
116    }
117
118    /**
119     * Returns a flag whether logging on debug level is enabled.
120     *
121     * @return <b>true</b> if debug logging is enabled, <b>false</b> otherwise
122     */
123    public boolean isDebugEnabled()
124    {
125        return getLog().isDebugEnabled();
126    }
127
128    /**
129     * Logs the specified message on debug level.
130     *
131     * @param msg the message to be logged
132     */
133    public void debug(String msg)
134    {
135        getLog().debug(msg);
136    }
137
138    /**
139     * Returns a flag whether logging on info level is enabled.
140     *
141     * @return <b>true</b> if debug logging is enabled, <b>false</b> otherwise
142     */
143    public boolean isInfoEnabled()
144    {
145        return getLog().isInfoEnabled();
146    }
147
148    /**
149     * Logs the specified message on info level.
150     *
151     * @param msg the message to be logged
152     */
153    public void info(String msg)
154    {
155        getLog().info(msg);
156    }
157
158    /**
159     * Logs the specified message on warn level.
160     *
161     * @param msg the message to be logged
162     */
163    public void warn(String msg)
164    {
165        getLog().warn(msg);
166    }
167
168    /**
169     * Logs the specified exception on warn level.
170     *
171     * @param msg the message to be logged
172     * @param ex the exception to be logged
173     */
174    public void warn(String msg, Throwable ex)
175    {
176        getLog().warn(msg, ex);
177    }
178
179    /**
180     * Logs the specified message on error level.
181     *
182     * @param msg the message to be logged
183     */
184    public void error(String msg)
185    {
186        getLog().error(msg);
187    }
188
189    /**
190     * Logs the specified exception on error level.
191     *
192     * @param msg the message to be logged
193     * @param ex the exception to be logged
194     */
195    public void error(String msg, Throwable ex)
196    {
197        getLog().error(msg, ex);
198    }
199
200    /**
201     * Returns the internal logger.
202     *
203     * @return the internal logger
204     */
205    Log getLog()
206    {
207        return log;
208    }
209
210    /**
211     * Creates an internal logger for the given name. Throws an exception if the
212     * name is undefined.
213     *
214     * @param name the name of the logger
215     * @return the logger object
216     * @throws IllegalArgumentException if the logger name is undefined
217     */
218    private static Log createLoggerForName(String name)
219    {
220        if (name == null)
221        {
222            throw new IllegalArgumentException("Logger name must not be null!");
223        }
224        return LogFactory.getLog(name);
225    }
226
227    /**
228     * Creates an internal logger for the given class. Throws an exception if
229     * the class is undefined.
230     *
231     * @param cls the logger class
232     * @return the logger object
233     * @throws IllegalArgumentException if the logger class is undefined
234     */
235    private static Log createLoggerForClass(Class<?> cls)
236    {
237        if (cls == null)
238        {
239            throw new IllegalArgumentException(
240                    "Logger class must not be null!");
241        }
242        return LogFactory.getLog(cls);
243    }
244}