001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.common.logging;
017
018import java.util.Locale;
019import java.util.concurrent.atomic.AtomicReference;
020import org.modeshape.common.annotation.ThreadSafe;
021import org.modeshape.common.i18n.I18nResource;
022
023/**
024 * A simple logging interface that is fully compatible with multiple logging implementations. If no specific logging implementation
025 * is found, then its defaulted to the JDK Logger implementation. This interface does take advantage of the variable arguments and
026 * autoboxing features in Java 5, reducing the number of methods that are necessary and allowing callers to supply primitive
027 * values as parameters.
028 */
029@ThreadSafe
030public abstract class Logger {
031
032    public enum Level {
033        OFF,
034        ERROR,
035        WARNING,
036        INFO,
037        DEBUG,
038        TRACE
039    }
040
041    private static final AtomicReference<Locale> LOGGING_LOCALE = new AtomicReference<Locale>(null);
042
043    /**
044     * Get the locale used for the logs. If null, the {@link Locale#getDefault() default locale} is used.
045     * 
046     * @return the current locale used for logging, or null if the system locale is used
047     * @see #setLoggingLocale(Locale)
048     */
049    public static Locale getLoggingLocale() {
050        return LOGGING_LOCALE.get();
051    }
052
053    /**
054     * Set the locale used for the logs. This should be used when the logs are to be written is a specific locale, independent of
055     * the {@link Locale#getDefault() default locale}. To use the default locale, call this method with a null value.
056     * 
057     * @param locale the desired locale to use for the logs, or null if the system locale should be used
058     * @return the previous locale
059     * @see #getLoggingLocale()
060     */
061    public static Locale setLoggingLocale( Locale locale ) {
062        return LOGGING_LOCALE.getAndSet(locale != null ? locale : Locale.getDefault());
063    }
064
065    /**
066     * Return a logger named corresponding to the class passed as parameter.
067     * 
068     * @param clazz the returned logger will be named after clazz
069     * @return logger
070     */
071    public static Logger getLogger( Class<?> clazz ) {
072        return LogFactory.getLogFactory().getLogger(clazz);
073    }
074
075    /**
076     * Return a logger named according to the name parameter.
077     * 
078     * @param name The name of the logger.
079     * @return logger
080     */
081    public static Logger getLogger( String name ) {
082        return LogFactory.getLogFactory().getLogger(name);
083    }
084
085    /**
086     * Return the name of this logger instance.
087     * 
088     * @return the logger's name
089     */
090    public abstract String getName();
091
092    /**
093     * Log a message at the supplied level according to the specified format and (optional) parameters. The message should contain
094     * a pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is
095     * efficient and avoids superfluous object creation when the logger is disabled for the desired level.
096     * 
097     * @param level the level at which to log
098     * @param message the (localized) message string
099     * @param params the parameter values that are to replace the variables in the format string
100     */
101    public void log( Level level,
102                     I18nResource message,
103                     Object... params ) {
104        if (message == null) return;
105        switch (level) {
106            case DEBUG:
107                debug(message.text(LOGGING_LOCALE.get(), params));
108                break;
109            case ERROR:
110                error(message, params);
111                break;
112            case INFO:
113                info(message, params);
114                break;
115            case TRACE:
116                trace(message.text(LOGGING_LOCALE.get(), params));
117                break;
118            case WARNING:
119                warn(message, params);
120                break;
121            case OFF:
122                break;
123        }
124    }
125
126    /**
127     * Log an exception (throwable) at the supplied level with an accompanying message. If the exception is null, then this method
128     * calls {@link #debug(String, Object...)}.
129     * 
130     * @param level the level at which to log
131     * @param t the exception (throwable) to log
132     * @param message the message accompanying the exception
133     * @param params the parameter values that are to replace the variables in the format string
134     */
135    public void log( Level level,
136                     Throwable t,
137                     I18nResource message,
138                     Object... params ) {
139        if (message == null) return;
140        switch (level) {
141            case DEBUG:
142                debug(t, message.text(LOGGING_LOCALE.get(), params));
143                break;
144            case ERROR:
145                error(t, message, params);
146                break;
147            case INFO:
148                info(t, message, params);
149                break;
150            case TRACE:
151                trace(t, message.text(LOGGING_LOCALE.get(), params));
152                break;
153            case WARNING:
154                warn(t, message, params);
155                break;
156            case OFF:
157                break;
158        }
159    }
160
161    /**
162     * Log a message at the DEBUG level according to the specified format and (optional) parameters. The message should contain a
163     * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient
164     * and avoids superfluous object creation when the logger is disabled for the DEBUG level.
165     * 
166     * @param message the message string
167     * @param params the parameter values that are to replace the variables in the format string
168     */
169    public abstract void debug( String message,
170                                Object... params );
171
172    /**
173     * Log an exception (throwable) at the DEBUG level with an accompanying message. If the exception is null, then this method
174     * calls {@link #debug(String, Object...)}.
175     * 
176     * @param t the exception (throwable) to log
177     * @param message the message accompanying the exception
178     * @param params the parameter values that are to replace the variables in the format string
179     */
180    public abstract void debug( Throwable t,
181                                String message,
182                                Object... params );
183
184    /**
185     * Log a message at the ERROR level according to the specified format and (optional) parameters. The message should contain a
186     * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient
187     * and avoids superfluous object creation when the logger is disabled for the ERROR level.
188     *
189     * @param message the message string
190     * @param params the parameter values that are to replace the variables in the format string
191     */
192    public abstract void error( I18nResource message,
193                                Object... params );
194
195    /**
196     * Log an exception (throwable) at the ERROR level with an accompanying message. If the exception is null, then this method
197     * calls {@link #error(org.modeshape.common.i18n.I18nResource, Object...)}.
198     *
199     * @param t the exception (throwable) to log
200     * @param message the message accompanying the exception
201     * @param params the parameter values that are to replace the variables in the format string
202     */
203    public abstract void error( Throwable t,
204                                I18nResource message,
205                                Object... params );
206
207    /**
208     * Log a message at the INFO level according to the specified format and (optional) parameters. The message should contain a
209     * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient
210     * and avoids superfluous object creation when the logger is disabled for the INFO level.
211     *
212     * @param message the message string
213     * @param params the parameter values that are to replace the variables in the format string
214     */
215    public abstract void info( I18nResource message,
216                               Object... params );
217
218    /**
219     * Log an exception (throwable) at the INFO level with an accompanying message. If the exception is null, then this method
220     * calls {@link #info(org.modeshape.common.i18n.I18nResource, Object...)}.
221     *
222     * @param t the exception (throwable) to log
223     * @param message the message accompanying the exception
224     * @param params the parameter values that are to replace the variables in the format string
225     */
226    public abstract void info( Throwable t,
227                               I18nResource message,
228                               Object... params );
229
230    /**
231     * Log a message at the TRACE level according to the specified format and (optional) parameters. The message should contain a
232     * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient
233     * and avoids superfluous object creation when the logger is disabled for the TRACE level.
234     * 
235     * @param message the message string
236     * @param params the parameter values that are to replace the variables in the format string
237     */
238    public abstract void trace( String message,
239                                Object... params );
240
241    /**
242     * Log an exception (throwable) at the TRACE level with an accompanying message. If the exception is null, then this method
243     * calls {@link #trace(String, Object...)}.
244     * 
245     * @param t the exception (throwable) to log
246     * @param message the message accompanying the exception
247     * @param params the parameter values that are to replace the variables in the format string
248     */
249    public abstract void trace( Throwable t,
250                                String message,
251                                Object... params );
252
253    /**
254     * Log a message at the WARNING level according to the specified format and (optional) parameters. The message should contain
255     * a pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is
256     * efficient and avoids superfluous object creation when the logger is disabled for the WARNING level.
257     *
258     * @param message the message string
259     * @param params the parameter values that are to replace the variables in the format string
260     */
261    public abstract void warn( I18nResource message,
262                               Object... params );
263
264    /**
265     * Log an exception (throwable) at the WARNING level with an accompanying message. If the exception is null, then this method
266     * calls {@link #warn(org.modeshape.common.i18n.I18nResource, Object...)}.
267     *
268     * @param t the exception (throwable) to log
269     * @param message the message accompanying the exception
270     * @param params the parameter values that are to replace the variables in the format string
271     */
272    public abstract void warn( Throwable t,
273                               I18nResource message,
274                               Object... params );
275
276    /**
277     * Return whether messages at the INFORMATION level are being logged.
278     * 
279     * @return true if INFORMATION log messages are currently being logged, or false otherwise.
280     */
281    public abstract boolean isInfoEnabled();
282
283    /**
284     * Return whether messages at the WARNING level are being logged.
285     * 
286     * @return true if WARNING log messages are currently being logged, or false otherwise.
287     */
288    public abstract boolean isWarnEnabled();
289
290    /**
291     * Return whether messages at the ERROR level are being logged.
292     * 
293     * @return true if ERROR log messages are currently being logged, or false otherwise.
294     */
295    public abstract boolean isErrorEnabled();
296
297    /**
298     * Return whether messages at the DEBUG level are being logged.
299     * 
300     * @return true if DEBUG log messages are currently being logged, or false otherwise.
301     */
302    public abstract boolean isDebugEnabled();
303
304    /**
305     * Return whether messages at the TRACE level are being logged.
306     * 
307     * @return true if TRACE log messages are currently being logged, or false otherwise.
308     */
309    public abstract boolean isTraceEnabled();
310}