1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.configuration2.io;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.apache.commons.logging.impl.NoOpLog;
23
24 /**
25 * <p>
26 * A class providing basic logging capabilities.
27 * </p>
28 * <p>
29 * When reading configuration files in complex scenarios having log output is useful for diagnostic purposes. Therefore,
30 * <em>Commons Configuration</em> produces some logging output. As concrete projects have different requirements on the
31 * amount and detail of logging, there is a way of configuring logging: All classes derived from
32 * {@link org.apache.commons.configuration2.AbstractConfiguration} can be assigned a logger which is then used for all
33 * log statements generated.
34 * </p>
35 * <p>
36 * Allowing a logger object to be passed to a configuration creates a direct dependency to a concrete logging framework
37 * in the configuration API. This would make it impossible to switch to an alternative logging framework without
38 * breaking backwards compatibility. To avoid this, the {@code ConfigurationLogger} class is introduced. It is a minimum
39 * abstraction over a logging framework offering only very basic logging capabilities. The methods defined in this class
40 * are used by configuration implementations to produce their logging statements. Client applications can create
41 * specialized instances and pass them to configuration objects without having to deal with a concrete logging
42 * framework. It is even possible to create a subclass that uses a completely different logging framework.
43 * </p>
44 *
45 * @since 2.0
46 */
47 public class ConfigurationLogger {
48 /**
49 * Creates an internal logger for the given class. Throws an exception if the class is undefined.
50 *
51 * @param cls the logger class
52 * @return the logger object
53 * @throws IllegalArgumentException if the logger class is undefined
54 */
55 private static Log createLoggerForClass(final Class<?> cls) {
56 if (cls == null) {
57 throw new IllegalArgumentException("Logger class must not be null!");
58 }
59 return LogFactory.getLog(cls);
60 }
61
62 /**
63 * Creates an internal logger for the given name. Throws an exception if the name is undefined.
64 *
65 * @param name the name of the logger
66 * @return the logger object
67 * @throws IllegalArgumentException if the logger name is undefined
68 */
69 private static Log createLoggerForName(final String name) {
70 if (name == null) {
71 throw new IllegalArgumentException("Logger name must not be null!");
72 }
73 return LogFactory.getLog(name);
74 }
75
76 /**
77 * Creates a new dummy logger which produces no output. If such a logger is passed to a configuration object, logging is
78 * effectively disabled.
79 *
80 * @return the new dummy logger
81 */
82 public static ConfigurationLogger newDummyLogger() {
83 return new ConfigurationLogger(new NoOpLog());
84 }
85
86 /** The internal logger. */
87 private final Log log;
88
89 /**
90 * Creates a new, uninitialized instance of {@code ConfigurationLogger}. This constructor can be used by derived classes
91 * that implement their own specific logging mechanism. Such classes must override all methods because the default
92 * implementations do not work in this uninitialized state.
93 */
94 protected ConfigurationLogger() {
95 this((Log) null);
96 }
97
98 /**
99 * 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 <strong>null</strong>)
103 * @throws IllegalArgumentException if the logger class is <strong>null</strong>
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 <strong>null</strong>)
122 * @throws IllegalArgumentException if the logger name is <strong>null</strong>
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 <strong>true</strong> if debug logging is enabled, <strong>false</strong> 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 <strong>true</strong> if debug logging is enabled, <strong>false</strong> 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 }