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 */ 25package org.slf4j.impl; 26 27import java.util.logging.Level; 28import java.util.logging.LogRecord; 29 30import org.slf4j.Logger; 31import org.slf4j.Marker; 32import org.slf4j.helpers.FormattingTuple; 33import org.slf4j.helpers.MarkerIgnoringBase; 34import org.slf4j.helpers.MessageFormatter; 35import 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 */ 46public 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} 652