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