View Javadoc

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