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