1   /*
2    * Copyright (c) 2004-2008 QOS.ch
3    * All rights reserved.
4    * 
5    * Permission is hereby granted, free  of charge, to any person obtaining
6    * a  copy  of this  software  and  associated  documentation files  (the
7    * "Software"), to  deal in  the Software without  restriction, including
8    * without limitation  the rights to  use, copy, modify,  merge, publish,
9    * distribute,  sublicense, and/or sell  copies of  the Software,  and to
10   * permit persons to whom the Software  is furnished to do so, subject to
11   * the following conditions:
12   * 
13   * The  above  copyright  notice  and  this permission  notice  shall  be
14   * included in all copies or substantial portions of the Software.
15   * 
16   * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
17   * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
18   * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
19   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20   * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21   * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
22   * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23   */
24  
25  
26  package org.slf4j.impl;
27  
28  import java.io.Serializable;
29  
30  import org.apache.log4j.Level;
31  import org.slf4j.Logger;
32  import org.slf4j.Marker;
33  import org.slf4j.helpers.MarkerIgnoringBase;
34  import org.slf4j.helpers.MessageFormatter;
35  import org.slf4j.spi.LocationAwareLogger;
36  
37  /**
38   * A wrapper over {@link org.apache.log4j.Logger org.apache.log4j.Logger} in
39   * conforming to the {@link Logger} interface. 
40   * 
41   * <p>Note that the logging levels mentioned in this class refer to those defined in the <a
42   * href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/Level.html"><code>org.apache.log4j.Level</code></a>
43   * class.
44   * 
45   * <p>
46   * The TRACE level was introduced in log4j version 1.2.12. In order to avoid
47   * crashing the host application, in the case the log4j version in use predates
48   * 1.2.12, the TRACE level will be mapped as DEBUG. See also <a
49   * href="http://bugzilla.slf4j.org/show_bug.cgi?id=68">bug 68</a>.
50   * 
51   * @author Ceki G&uuml;lc&uuml;
52   */
53  public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
54      LocationAwareLogger, Serializable {
55  
56    private static final long serialVersionUID = 6182834493563598289L;
57  
58    final transient org.apache.log4j.Logger logger;
59  
60    /**
61     * Following the pattern discussed in pages 162 through 168 of "The complete
62     * log4j manual".
63     */
64    final static String FQCN = Log4jLoggerAdapter.class.getName();
65  
66    // Does the log4j version in use recognize the TRACE level?
67    // The trace level was introduced in log4j 1.2.12.
68    final boolean traceCapable;
69  
70    // WARN: Log4jLoggerAdapter constructor should have only package access so
71    // that
72    // only Log4jLoggerFactory be able to create one.
73    Log4jLoggerAdapter(org.apache.log4j.Logger logger) {
74      this.logger = logger;
75      this.name = logger.getName();
76      traceCapable = isTraceCapable();
77    }
78  
79    private boolean isTraceCapable() {
80      try {
81        logger.isTraceEnabled();
82        return true;
83      } catch (NoSuchMethodError e) {
84        return false;
85      }
86    }
87  
88    /**
89     * Is this logger instance enabled for the TRACE level?
90     * 
91     * @return True if this Logger is enabled for level TRACE, false otherwise.
92     */
93    public boolean isTraceEnabled() {
94      if (traceCapable) {
95        return logger.isTraceEnabled();
96      } else {
97        return logger.isDebugEnabled();
98      }
99    }
100 
101   /**
102    * Log a message object at level TRACE.
103    * 
104    * @param msg -
105    *                the message object to be logged
106    */
107   public void trace(String msg) {
108     logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msg, null);
109   }
110 
111   /**
112    * Log a message at level TRACE according to the specified format and
113    * argument.
114    * 
115    * <p>
116    * This form avoids superfluous object creation when the logger is disabled
117    * for level TRACE.
118    * </p>
119    * 
120    * @param format
121    *                the format string
122    * @param arg
123    *                the argument
124    */
125   public void trace(String format, Object arg) {
126     if (isTraceEnabled()) {
127       String msgStr = MessageFormatter.format(format, arg);
128       logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msgStr, null);
129     }
130   }
131 
132   /**
133    * Log a message at level TRACE according to the specified format and
134    * arguments.
135    * 
136    * <p>
137    * This form avoids superfluous object creation when the logger is disabled
138    * for the TRACE level.
139    * </p>
140    * 
141    * @param format
142    *                the format string
143    * @param arg1
144    *                the first argument
145    * @param arg2
146    *                the second argument
147    */
148   public void trace(String format, Object arg1, Object arg2) {
149     if (isTraceEnabled()) {
150       String msgStr = MessageFormatter.format(format, arg1, arg2);
151       logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msgStr, null);
152     }
153   }
154 
155   /**
156    * Log a message at level TRACE according to the specified format and
157    * arguments.
158    * 
159    * <p>
160    * This form avoids superfluous object creation when the logger is disabled
161    * for the TRACE level.
162    * </p>
163    * 
164    * @param format
165    *                the format string
166    * @param argArray
167    *                an array of arguments
168    */
169   public void trace(String format, Object[] argArray) {
170     if (isTraceEnabled()) {
171       String msgStr = MessageFormatter.arrayFormat(format, argArray);
172       logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msgStr, null);
173     }
174   }
175 
176   /**
177    * Log an exception (throwable) at level TRACE with an accompanying message.
178    * 
179    * @param msg
180    *                the message accompanying the exception
181    * @param t
182    *                the exception (throwable) to log
183    */
184   public void trace(String msg, Throwable t) {
185     logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msg, t);
186   }
187 
188   /**
189    * Is this logger instance enabled for the DEBUG level?
190    * 
191    * @return True if this Logger is enabled for level DEBUG, false otherwise.
192    */
193   public boolean isDebugEnabled() {
194     return logger.isDebugEnabled();
195   }
196 
197   /**
198    * Log a message object at level DEBUG.
199    * 
200    * @param msg -
201    *                the message object to be logged
202    */
203   public void debug(String msg) {
204     logger.log(FQCN, Level.DEBUG, msg, null);
205   }
206 
207   /**
208    * Log a message at level DEBUG according to the specified format and
209    * argument.
210    * 
211    * <p>
212    * This form avoids superfluous object creation when the logger is disabled
213    * for level DEBUG.
214    * </p>
215    * 
216    * @param format
217    *                the format string
218    * @param arg
219    *                the argument
220    */
221   public void debug(String format, Object arg) {
222     if (logger.isDebugEnabled()) {
223       String msgStr = MessageFormatter.format(format, arg);
224       logger.log(FQCN, Level.DEBUG, msgStr, null);
225     }
226   }
227 
228   /**
229    * Log a message at level DEBUG according to the specified format and
230    * arguments.
231    * 
232    * <p>
233    * This form avoids superfluous object creation when the logger is disabled
234    * for the DEBUG level.
235    * </p>
236    * 
237    * @param format
238    *                the format string
239    * @param arg1
240    *                the first argument
241    * @param arg2
242    *                the second argument
243    */
244   public void debug(String format, Object arg1, Object arg2) {
245     if (logger.isDebugEnabled()) {
246       String msgStr = MessageFormatter.format(format, arg1, arg2);
247       logger.log(FQCN, Level.DEBUG, msgStr, null);
248     }
249   }
250 
251   /**
252    * Log a message at level DEBUG according to the specified format and
253    * arguments.
254    * 
255    * <p>
256    * This form avoids superfluous object creation when the logger is disabled
257    * for the DEBUG level.
258    * </p>
259    * 
260    * @param format
261    *                the format string
262    * @param argArray
263    *                an array of arguments
264    */
265   public void debug(String format, Object[] argArray) {
266     if (logger.isDebugEnabled()) {
267       String msgStr = MessageFormatter.arrayFormat(format, argArray);
268       logger.log(FQCN, Level.DEBUG, msgStr, null);
269     }
270   }
271 
272   /**
273    * Log an exception (throwable) at level DEBUG with an accompanying message.
274    * 
275    * @param msg
276    *                the message accompanying the exception
277    * @param t
278    *                the exception (throwable) to log
279    */
280   public void debug(String msg, Throwable t) {
281     logger.log(FQCN, Level.DEBUG, msg, t);
282   }
283 
284   /**
285    * Is this logger instance enabled for the INFO level?
286    * 
287    * @return True if this Logger is enabled for the INFO level, false otherwise.
288    */
289   public boolean isInfoEnabled() {
290     return logger.isInfoEnabled();
291   }
292 
293   /**
294    * Log a message object at the INFO level.
295    * 
296    * @param msg -
297    *                the message object to be logged
298    */
299   public void info(String msg) {
300     logger.log(FQCN, Level.INFO, msg, null);
301   }
302 
303   /**
304    * Log a message at level INFO according to the specified format and argument.
305    * 
306    * <p>
307    * This form avoids superfluous object creation when the logger is disabled
308    * for the INFO level.
309    * </p>
310    * 
311    * @param format
312    *                the format string
313    * @param arg
314    *                the argument
315    */
316   public void info(String format, Object arg) {
317     if (logger.isInfoEnabled()) {
318       String msgStr = MessageFormatter.format(format, arg);
319       logger.log(FQCN, Level.INFO, msgStr, null);
320     }
321   }
322 
323   /**
324    * Log a message at the INFO level according to the specified format and
325    * arguments.
326    * 
327    * <p>
328    * This form avoids superfluous object creation when the logger is disabled
329    * for the INFO level.
330    * </p>
331    * 
332    * @param format
333    *                the format string
334    * @param arg1
335    *                the first argument
336    * @param arg2
337    *                the second argument
338    */
339   public void info(String format, Object arg1, Object arg2) {
340     if (logger.isInfoEnabled()) {
341       String msgStr = MessageFormatter.format(format, arg1, arg2);
342       logger.log(FQCN, Level.INFO, msgStr, null);
343     }
344   }
345 
346   /**
347    * Log a message at level INFO according to the specified format and
348    * arguments.
349    * 
350    * <p>
351    * This form avoids superfluous object creation when the logger is disabled
352    * for the INFO level.
353    * </p>
354    * 
355    * @param format
356    *                the format string
357    * @param argArray
358    *                an array of arguments
359    */
360   public void info(String format, Object[] argArray) {
361     if (logger.isInfoEnabled()) {
362       String msgStr = MessageFormatter.arrayFormat(format, argArray);
363       logger.log(FQCN, Level.INFO, msgStr, null);
364     }
365   }
366 
367   /**
368    * Log an exception (throwable) at the INFO level with an accompanying
369    * message.
370    * 
371    * @param msg
372    *                the message accompanying the exception
373    * @param t
374    *                the exception (throwable) to log
375    */
376   public void info(String msg, Throwable t) {
377     logger.log(FQCN, Level.INFO, msg, t);
378   }
379 
380   /**
381    * Is this logger instance enabled for the WARN level?
382    * 
383    * @return True if this Logger is enabled for the WARN level, false otherwise.
384    */
385   public boolean isWarnEnabled() {
386     return logger.isEnabledFor(Level.WARN);
387   }
388 
389   /**
390    * Log a message object at the WARN level.
391    * 
392    * @param msg -
393    *                the message object to be logged
394    */
395   public void warn(String msg) {
396     logger.log(FQCN, Level.WARN, msg, null);
397   }
398 
399   /**
400    * Log a message at the WARN level according to the specified format and
401    * argument.
402    * 
403    * <p>
404    * This form avoids superfluous object creation when the logger is disabled
405    * for the WARN level.
406    * </p>
407    * 
408    * @param format
409    *                the format string
410    * @param arg
411    *                the argument
412    */
413   public void warn(String format, Object arg) {
414     if (logger.isEnabledFor(Level.WARN)) {
415       String msgStr = MessageFormatter.format(format, arg);
416       logger.log(FQCN, Level.WARN, msgStr, null);
417     }
418   }
419 
420   /**
421    * Log a message at the WARN level according to the specified format and
422    * arguments.
423    * 
424    * <p>
425    * This form avoids superfluous object creation when the logger is disabled
426    * for the WARN level.
427    * </p>
428    * 
429    * @param format
430    *                the format string
431    * @param arg1
432    *                the first argument
433    * @param arg2
434    *                the second argument
435    */
436   public void warn(String format, Object arg1, Object arg2) {
437     if (logger.isEnabledFor(Level.WARN)) {
438       String msgStr = MessageFormatter.format(format, arg1, arg2);
439       logger.log(FQCN, Level.WARN, msgStr, null);
440     }
441   }
442 
443   /**
444    * Log a message at level WARN according to the specified format and
445    * arguments.
446    * 
447    * <p>
448    * This form avoids superfluous object creation when the logger is disabled
449    * for the WARN level.
450    * </p>
451    * 
452    * @param format
453    *                the format string
454    * @param argArray
455    *                an array of arguments
456    */
457   public void warn(String format, Object[] argArray) {
458     if (logger.isEnabledFor(Level.WARN)) {
459       String msgStr = MessageFormatter.arrayFormat(format, argArray);
460       logger.log(FQCN, Level.WARN, msgStr, null);
461     }
462   }
463 
464   /**
465    * Log an exception (throwable) at the WARN level with an accompanying
466    * message.
467    * 
468    * @param msg
469    *                the message accompanying the exception
470    * @param t
471    *                the exception (throwable) to log
472    */
473   public void warn(String msg, Throwable t) {
474     logger.log(FQCN, Level.WARN, msg, t);
475   }
476 
477   /**
478    * Is this logger instance enabled for level ERROR?
479    * 
480    * @return True if this Logger is enabled for level ERROR, false otherwise.
481    */
482   public boolean isErrorEnabled() {
483     return logger.isEnabledFor(Level.ERROR);
484   }
485 
486   /**
487    * Log a message object at the ERROR level.
488    * 
489    * @param msg -
490    *                the message object to be logged
491    */
492   public void error(String msg) {
493     logger.log(FQCN, Level.ERROR, msg, null);
494   }
495 
496   /**
497    * Log a message at the ERROR level according to the specified format and
498    * argument.
499    * 
500    * <p>
501    * This form avoids superfluous object creation when the logger is disabled
502    * for the ERROR level.
503    * </p>
504    * 
505    * @param format
506    *                the format string
507    * @param arg
508    *                the argument
509    */
510   public void error(String format, Object arg) {
511     if (logger.isEnabledFor(Level.ERROR)) {
512       String msgStr = MessageFormatter.format(format, arg);
513       logger.log(FQCN, Level.ERROR, msgStr, null);
514     }
515   }
516 
517   /**
518    * Log a message at the ERROR level according to the specified format and
519    * arguments.
520    * 
521    * <p>
522    * This form avoids superfluous object creation when the logger is disabled
523    * for the ERROR level.
524    * </p>
525    * 
526    * @param format
527    *                the format string
528    * @param arg1
529    *                the first argument
530    * @param arg2
531    *                the second argument
532    */
533   public void error(String format, Object arg1, Object arg2) {
534     if (logger.isEnabledFor(Level.ERROR)) {
535       String msgStr = MessageFormatter.format(format, arg1, arg2);
536       logger.log(FQCN, Level.ERROR, msgStr, null);
537     }
538   }
539 
540   /**
541    * Log a message at level ERROR according to the specified format and
542    * arguments.
543    * 
544    * <p>
545    * This form avoids superfluous object creation when the logger is disabled
546    * for the ERROR level.
547    * </p>
548    * 
549    * @param format
550    *                the format string
551    * @param argArray
552    *                an array of arguments
553    */
554   public void error(String format, Object[] argArray) {
555     if (logger.isEnabledFor(Level.ERROR)) {
556       String msgStr = MessageFormatter.arrayFormat(format, argArray);
557       logger.log(FQCN, Level.ERROR, msgStr, null);
558     }
559   }
560 
561   /**
562    * Log an exception (throwable) at the ERROR level with an accompanying
563    * message.
564    * 
565    * @param msg
566    *                the message accompanying the exception
567    * @param t
568    *                the exception (throwable) to log
569    */
570   public void error(String msg, Throwable t) {
571     logger.log(FQCN, Level.ERROR, msg, t);
572   }
573 
574   public void log(Marker marker, String callerFQCN, int level, String msg,
575       Throwable t) {
576     Level log4jLevel;
577     switch (level) {
578     case LocationAwareLogger.TRACE_INT:
579       log4jLevel = traceCapable ? Level.TRACE : Level.DEBUG;
580       break;
581     case LocationAwareLogger.DEBUG_INT:
582       log4jLevel = Level.DEBUG;
583       break;
584     case LocationAwareLogger.INFO_INT:
585       log4jLevel = Level.INFO;
586       break;
587     case LocationAwareLogger.WARN_INT:
588       log4jLevel = Level.WARN;
589       break;
590     case LocationAwareLogger.ERROR_INT:
591       log4jLevel = Level.ERROR;
592       break;
593     default:
594       throw new IllegalStateException("Level number " + level
595           + " is not recognized.");
596     }
597     logger.log(callerFQCN, log4jLevel, msg, t);
598   }
599 
600 }