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