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