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 /**
50 * Creates an internal logger for the given class. Throws an exception if the class is undefined.
51 *
52 * @param cls the logger class
53 * @return the logger object
54 * @throws IllegalArgumentException if the logger class is undefined
55 */
56 private static Log createLoggerForClass(final Class<?> cls) {
57 if (cls == null) {
58 throw new IllegalArgumentException("Logger class must not be null!");
59 }
60 return LogFactory.getLog(cls);
61 }
62
63 /**
64 * Creates an internal logger for the given name. Throws an exception if the name is undefined.
65 *
66 * @param name the name of the logger
67 * @return the logger object
68 * @throws IllegalArgumentException if the logger name is undefined
69 */
70 private static Log createLoggerForName(final String name) {
71 if (name == null) {
72 throw new IllegalArgumentException("Logger name must not be null!");
73 }
74 return LogFactory.getLog(name);
75 }
76
77 /**
78 * Creates a new dummy logger which produces no output. If such a logger is passed to a configuration object, logging is
79 * effectively disabled.
80 *
81 * @return the new dummy logger
82 */
83 public static ConfigurationLogger newDummyLogger() {
84 return new ConfigurationLogger(new NoOpLog());
85 }
86
87 /** The internal logger. */
88 private final Log log;
89
90 /**
91 * Creates a new, uninitialized instance of {@code ConfigurationLogger}. This constructor can be used by derived classes
92 * that implement their own specific logging mechanism. Such classes must override all methods because the default
93 * implementations do not work in this uninitialized state.
94 */
95 protected ConfigurationLogger() {
96 this((Log) null);
97 }
98
99 /**
100 * Creates a new instance of {@code ConfigurationLogger} that uses a logger whose name is derived from the provided
101 * class.
102 *
103 * @param logCls the class whose name is to be used for logging (must not be <strong>null</strong>)
104 * @throws IllegalArgumentException if the logger class is <strong>null</strong>
105 */
106 public ConfigurationLogger(final Class<?> logCls) {
107 this(createLoggerForClass(logCls));
108 }
109
110 /**
111 * Creates a new instance of {@code ConfigurationLogger} which wraps the specified logger.
112 *
113 * @param wrapped the logger to be wrapped
114 */
115 ConfigurationLogger(final Log wrapped) {
116 log = wrapped;
117 }
118
119 /**
120 * Creates a new instance of {@code ConfigurationLogger} that uses the specified logger name.
121 *
122 * @param loggerName the logger name (must not be <strong>null</strong>)
123 * @throws IllegalArgumentException if the logger name is <strong>null</strong>
124 */
125 public ConfigurationLogger(final String loggerName) {
126 this(createLoggerForName(loggerName));
127 }
128
129 /**
130 * Logs the specified message on debug level.
131 *
132 * @param msg the message to be logged
133 */
134 public void debug(final String msg) {
135 getLog().debug(msg);
136 }
137
138 /**
139 * Logs the specified message on error level.
140 *
141 * @param msg the message to be logged
142 */
143 public void error(final String msg) {
144 getLog().error(msg);
145 }
146
147 /**
148 * Logs the specified exception on error level.
149 *
150 * @param msg the message to be logged
151 * @param ex the exception to be logged
152 */
153 public void error(final String msg, final Throwable ex) {
154 getLog().error(msg, ex);
155 }
156
157 /**
158 * Gets the internal logger.
159 *
160 * @return the internal logger
161 */
162 Log getLog() {
163 return log;
164 }
165
166 /**
167 * Logs the specified message on info level.
168 *
169 * @param msg the message to be logged
170 */
171 public void info(final String msg) {
172 getLog().info(msg);
173 }
174
175 /**
176 * Returns a flag whether logging on debug level is enabled.
177 *
178 * @return <strong>true</strong> if debug logging is enabled, <strong>false</strong> otherwise
179 */
180 public boolean isDebugEnabled() {
181 return getLog().isDebugEnabled();
182 }
183
184 /**
185 * Returns a flag whether logging on info level is enabled.
186 *
187 * @return <strong>true</strong> if debug logging is enabled, <strong>false</strong> otherwise
188 */
189 public boolean isInfoEnabled() {
190 return getLog().isInfoEnabled();
191 }
192
193 /**
194 * Logs the specified message on warn level.
195 *
196 * @param msg the message to be logged
197 */
198 public void warn(final String msg) {
199 getLog().warn(msg);
200 }
201
202 /**
203 * Logs the specified exception on warn level.
204 *
205 * @param msg the message to be logged
206 * @param ex the exception to be logged
207 */
208 public void warn(final String msg, final Throwable ex) {
209 getLog().warn(msg, ex);
210 }
211 }