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ülcü
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 }