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