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 * @since 2.0
052 */
053public class ConfigurationLogger
054{
055    /** The internal logger. */
056    private final Log log;
057
058    /**
059     * Creates a new instance of {@code ConfigurationLogger} that uses the
060     * specified logger name.
061     *
062     * @param loggerName the logger name (must not be <b>null</b>)
063     * @throws IllegalArgumentException if the logger name is <b>null</b>
064     */
065    public ConfigurationLogger(final String loggerName)
066    {
067        this(createLoggerForName(loggerName));
068    }
069
070    /**
071     * Creates a new instance of {@code ConfigurationLogger} that uses a logger
072     * whose name is derived from the provided class.
073     *
074     * @param logCls the class whose name is to be used for logging (must not be
075     *        <b>null</b>)
076     * @throws IllegalArgumentException if the logger class is <b>null</b>
077     */
078    public ConfigurationLogger(final Class<?> logCls)
079    {
080        this(createLoggerForClass(logCls));
081    }
082
083    /**
084     * Creates a new, uninitialized instance of {@code ConfigurationLogger}.
085     * This constructor can be used by derived classes that implement their own
086     * specific logging mechanism. Such classes must override all methods
087     * because the default implementations do not work in this uninitialized
088     * state.
089     */
090    protected ConfigurationLogger()
091    {
092        this((Log) null);
093    }
094
095    /**
096     * Creates a new instance of {@code ConfigurationLogger} which wraps the
097     * specified logger.
098     *
099     * @param wrapped the logger to be wrapped
100     */
101    ConfigurationLogger(final Log wrapped)
102    {
103        log = wrapped;
104    }
105
106    /**
107     * Creates a new dummy logger which produces no output. If such a logger is
108     * passed to a configuration object, logging is effectively disabled.
109     *
110     * @return the new dummy logger
111     */
112    public static ConfigurationLogger newDummyLogger()
113    {
114        return new ConfigurationLogger(new NoOpLog());
115    }
116
117    /**
118     * Returns a flag whether logging on debug level is enabled.
119     *
120     * @return <b>true</b> if debug logging is enabled, <b>false</b> otherwise
121     */
122    public boolean isDebugEnabled()
123    {
124        return getLog().isDebugEnabled();
125    }
126
127    /**
128     * Logs the specified message on debug level.
129     *
130     * @param msg the message to be logged
131     */
132    public void debug(final String msg)
133    {
134        getLog().debug(msg);
135    }
136
137    /**
138     * Returns a flag whether logging on info level is enabled.
139     *
140     * @return <b>true</b> if debug logging is enabled, <b>false</b> otherwise
141     */
142    public boolean isInfoEnabled()
143    {
144        return getLog().isInfoEnabled();
145    }
146
147    /**
148     * Logs the specified message on info level.
149     *
150     * @param msg the message to be logged
151     */
152    public void info(final String msg)
153    {
154        getLog().info(msg);
155    }
156
157    /**
158     * Logs the specified message on warn level.
159     *
160     * @param msg the message to be logged
161     */
162    public void warn(final String msg)
163    {
164        getLog().warn(msg);
165    }
166
167    /**
168     * Logs the specified exception on warn level.
169     *
170     * @param msg the message to be logged
171     * @param ex the exception to be logged
172     */
173    public void warn(final String msg, final Throwable ex)
174    {
175        getLog().warn(msg, ex);
176    }
177
178    /**
179     * Logs the specified message on error level.
180     *
181     * @param msg the message to be logged
182     */
183    public void error(final String msg)
184    {
185        getLog().error(msg);
186    }
187
188    /**
189     * Logs the specified exception on error level.
190     *
191     * @param msg the message to be logged
192     * @param ex the exception to be logged
193     */
194    public void error(final String msg, final Throwable ex)
195    {
196        getLog().error(msg, ex);
197    }
198
199    /**
200     * Returns the internal logger.
201     *
202     * @return the internal logger
203     */
204    Log getLog()
205    {
206        return log;
207    }
208
209    /**
210     * Creates an internal logger for the given name. Throws an exception if the
211     * name is undefined.
212     *
213     * @param name the name of the logger
214     * @return the logger object
215     * @throws IllegalArgumentException if the logger name is undefined
216     */
217    private static Log createLoggerForName(final String name)
218    {
219        if (name == null)
220        {
221            throw new IllegalArgumentException("Logger name must not be null!");
222        }
223        return LogFactory.getLog(name);
224    }
225
226    /**
227     * Creates an internal logger for the given class. Throws an exception if
228     * the class is undefined.
229     *
230     * @param cls the logger class
231     * @return the logger object
232     * @throws IllegalArgumentException if the logger class is undefined
233     */
234    private static Log createLoggerForClass(final Class<?> cls)
235    {
236        if (cls == null)
237        {
238            throw new IllegalArgumentException(
239                    "Logger class must not be null!");
240        }
241        return LogFactory.getLog(cls);
242    }
243}