001 // Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 002 // The Molly framework is freely distributable under the terms of an 003 // MIT-style license. For details, see the molly pages web site at: 004 // http://www.mollypages.org/. Use, modify, have fun ! 005 006 package fc.io; 007 008 import java.text.*; 009 import java.util.*; 010 import java.lang.reflect.*; 011 012 import fc.util.*; 013 014 /** 015 A system wide logging facility. Clearer and more elegant 016 semantics/nomenclature than <tt>java.util.logging</tt>. 017 <p> 018 Logs messages to some user specified destination(s). Each log has a 019 <b>name</b> and a <b>log level</b>. 020 <p> 021 The names are arbitrary (hopefully descriptive) names, per your liking. Many 022 different logs can be created and then later retrieved by their 023 name as needed. 024 <p> 025 The levels provided by this class have the order: 026 <blockquote> 027 <tt> 028 OFF <b><</b> ERROR <b>< </b>WARN <b><</b> INFO <b><</b> DEBUG 029 </tt> 030 </blockquote> 031 The above levels are self-explanatory. 032 <p> 033 Convenience methods with names equal to a <b>level</b> name are provided. 034 So for example, instead of saying: 035 <blockquote> 036 <tt>log(<b>LogLevel.warn</b>, "the message");</tt> 037 </blockquote> 038 one can say: 039 <blockquote> 040 <tt>log.<b>warn</b>("the message");</tt> 041 </blockquote> 042 <p> 043 <div style="border: 1px solid #ccc; padding: 1em;"> 044 A little historical quirk. For the debug level <tt>LogLevel.debug</b></tt>, 045 one can say: 046 <blockquote> 047 <pre> 048 <tt>log.<b>debug</b>("the message");</tt> 049 --<b>or</b>-- 050 <tt>log.<b>bug</b>("the message");</tt> 051 </pre> 052 </blockquote> 053 </div> 054 <p> 055 A default logger of type {@link fc.io.SystemLog} is provided for 056 convenience in this class and can be retrieved by calling the {@link 057 #getDefault()} method. 058 <p> 059 The {@link #closeLog(String)} method is called on all logs 060 at JVM shutdown. 061 <p> 062 <b>Note:</b>To log a full stack traces, pass the string obtained by the 063 {@link IOUtil#throwableToString} method. (by default, an exception simply 064 prints its message but not the full stack trace) 065 <p> 066 <b>Implementation Note</b>: subclasses should implement static 067 <tt>getLog(..)</tt> type methods. These that create, as needed, and 068 return a new log object of that subclass type. These getter methods 069 should be static for convenience. Also, the implementation of the 070 <tt>subclass.getLog(...)</tt> methods in subclasses is expected by 071 convention. 072 <p> 073 Thread Safety: This class <tt>is</tt> Threadsafe and all its methods can 074 be used concurrently. 075 076 @author hursh jain 077 **/ 078 public abstract class Log 079 { 080 //--static variables-- 081 public static final LogLevel OFF = new LogLevel("OFF", 0); 082 public static final LogLevel ERROR = new LogLevel("ERROR", 1); 083 public static final LogLevel WARN = new LogLevel("WARN", 2); 084 public static final LogLevel INFO = new LogLevel("INFO", 3); 085 public static final LogLevel DEBUG = new LogLevel("DEBUG", 4); 086 087 /** 088 The default level used for new logs. Subclasses should (by default) 089 create logs using this level. 090 */ 091 public static LogLevel DEFAULT_LEVEL = INFO; 092 093 protected static final byte[] linesepbytes = 094 System.getProperty("line.separator").getBytes(); 095 096 //synchronized map needed 097 protected static SystemLog defaultlog; 098 protected static final Map logs = new Hashtable(); 099 100 //--instance variables apply to a particular logger 101 protected String name; 102 protected LogLevel currentLevel; 103 protected long startTime; 104 protected String startTimeString; //for toString() 105 protected boolean printLevelName = true; 106 protected boolean printTimestamp = false; 107 protected boolean timestampIsRelative = false; 108 protected LogLevel printMethodInfoAtLevel = DEBUG; 109 110 //default timestamp data 111 protected final SimpleDateFormat df 112 = new SimpleDateFormat("MMM dd H:m:s z"); 113 protected final NumberFormat nf 114 = NumberFormat.getNumberInstance(); 115 116 protected Date date = new Date(); 117 protected long last_time = date.getTime(); 118 protected String timestr = df.format(date); 119 120 //Add shutdown hook to close all open logs 121 static 122 { 123 Runtime.getRuntime().addShutdownHook(new Thread("fc.io.Log.Shutdown") { 124 public void run() 125 { 126 System.out.println("JVM shutdown: fc.io.Log - closing all logs..."); 127 Iterator i = logs.values().iterator(); 128 while (i.hasNext()) 129 ((Log)i.next()).close(); 130 System.out.println(); 131 } 132 }); 133 } 134 135 136 /** 137 Constructs a new Log. Can only be called from subclasses. 138 139 @param name the name for the log -- any arbitrary 140 string denoting a conceptual category, 141 destination, whatever 142 @param level the initial logging level for this log 143 */ 144 protected Log(String name, LogLevel level) 145 { 146 assert name != null : "name was null"; 147 assert level != null : "level was null" ; 148 this.name = name; 149 this.currentLevel = level; 150 this.startTime = System.currentTimeMillis(); 151 this.startTimeString = new Date(startTime).toString(); 152 } 153 154 155 /** 156 Returns a {@link SystemLog} with the specified name. If the log does not already 157 exist, creates and returns a new SystemLog with that name. 158 <p> 159 The system log created will have a default destination of <tt>System.err</tt> 160 and a default level of {@link Log#INFO}. 161 <p> 162 To obtain logs with a different destination, create a SystemLog directly. 163 */ 164 public static Log get(String name) 165 { 166 Log log = (Log) logs.get(name); 167 if (log != null) 168 return log; 169 170 synchronized(logs) { 171 log = new SystemLog(name); 172 logs.put(name, log); 173 } 174 175 return log; 176 } 177 178 179 /** 180 An alias for method {@link #get(String)}. 181 <p> 182 Returns a {@link SystemLog} with the specified name. If the log does not already 183 exist, creates and returns a new SystemLog with that name. 184 <p> 185 The system log created will have a default destination of <tt>System.err</tt> 186 and a default level of {@link Log#INFO}. 187 <p> 188 To obtain logs with a different destination, create a SystemLog directly. 189 */ 190 public static Log getLog(String name) 191 { 192 return get(name); 193 } 194 195 196 /** 197 Convenience method that returns the log named after the <b>package</b> that 198 the specified class belong to. If 2 classes <pre>a.b.Class1</pre> and 199 <pre>a.b.Class2</pre> call this method, they will get the same logger 200 (named <tt>a.b</tt>). 201 <p> 202 If the log does not already exist, creates and returns a new {@link SystemLog} 203 with that name. 204 205 @param c a non-null class 206 */ 207 public final static Log get(Class c) 208 { 209 Argcheck.notnull(c, "class parameter was null"); 210 final Package p = c.getPackage(); 211 final String name = (p == null) ? "default_pkg" : p.toString(); 212 return get(name); 213 } 214 215 /** 216 Convenience method that returns a log named after the <b>package</b> that 217 the specified object's class belong to. If 2 objects of class 218 <pre>a.b.Class1</pre> and <pre>a.b.Class2</pre> call this method, they 219 will get the same logger (named <tt>a.b</tt>). 220 <p> 221 If the log does not already exist, creates and returns a new {@link SystemLog} 222 with that name. 223 224 @param obj a non-null object 225 */ 226 public final static Log get(Object obj) 227 { 228 Argcheck.notnull(obj, "class parameter was null"); 229 return get(obj.getClass().getPackage().toString()); 230 } 231 232 /** 233 Returns the default system log. This system log writes to 234 <tt>System.err</tt> and has it's level set to {@link SystemLog#INFO}. This 235 level can be changed to some other level if desired by invoking {@link 236 setLevel()} on the returned object. 237 */ 238 public static SystemLog getDefault() 239 { 240 synchronized (Log.class) 241 { 242 if (defaultlog == null) { 243 defaultlog = new SystemLog( 244 "_defaultlog", System.out, SystemLog.INFO); 245 } 246 } 247 return defaultlog; 248 } 249 250 251 /** 252 Returns an iteration containing level names for this log. The names can be in 253 any order. 254 */ 255 public Iterator getLevelNames() 256 { 257 Class myclass = getClass(); 258 Field[] fields = myclass.getDeclaredFields(); 259 Field levelfield = null; 260 List l = new ArrayList(); 261 for (int n = 0; n < fields.length; n++) 262 { 263 Field f = fields[n]; 264 if (! f.getType().isAssignableFrom(LogLevel.class)) 265 continue; 266 l.add(f.getName()); 267 } 268 return l.iterator(); 269 } 270 271 /* 272 Manually adds the specified log to the list of all logs. If a log with 273 that name already exists, an <tt>IllegalArgumentException</tt> is thrown. 274 <p> This method is useful when creating a new logging object manaually. 275 So for example: 276 <blockquote> 277 <pre> 278 MyLogClass mylog = new MyLogClass("foo.bar"); 279 Log.addLog(mylog) 280 </pre> 281 </blockquote> 282 Contrast that with the more usual: 283 <blockquote> 284 <pre> 285 Log.getLog("foo.bar"); 286 </pre> 287 </blockquote> 288 <p> 289 <u>Custom log implementations should always call this method in their 290 constructor to add themselves to the list of all logs.</u> 291 */ 292 protected static void addLog(Log log) 293 { 294 synchronized(logs) 295 { 296 if (! logs.containsKey(log.name)) { 297 logs.put(log.name, log); 298 } 299 else throw new IllegalArgumentException("Log already exists: " + log); 300 } 301 } 302 303 /** 304 Closes and removes the log with the specified name if it exists 305 */ 306 public static void closeLog(String name) 307 { 308 if (logs.containsKey(name)) { 309 Log l = (Log) logs.get(name); 310 l.close(); 311 logs.remove(name); 312 } 313 } 314 315 /** 316 Returns the method name, file number and line number 317 of the calling method. Useful for logging/code tracing. 318 319 @param level the level for which this logging call was invoked. 320 @param framenum the method to examine. This method itself 321 has frame number 0, the calling method 322 has frame number 1, it's parent 2 and so on. 323 **/ 324 public final String getDebugContext(LogLevel level, int framenum) 325 { 326 if (level.intval < printMethodInfoAtLevel.intval) { 327 return ""; 328 } 329 330 StackTraceElement ste[] = new Exception().getStackTrace(); 331 if (framenum >= ste.length) 332 throw new IllegalArgumentException( 333 "framenum [" + framenum 334 + "] too large. Max number of record in stack = " 335 + (ste.length - 1)); 336 337 //get method that called us, we are ste[0] 338 StackTraceElement st = ste[framenum]; 339 String file = st.getFileName(); 340 int line = st.getLineNumber(); 341 String method = st.getMethodName(); 342 String threadname = Thread.currentThread().getName(); 343 //String classn = st.getClassName(); 344 return method + "() [" + file + ":" + line + "/thread:" + threadname + "]"; 345 } 346 347 348 /** 349 If set to true, will print the level name before the logging 350 message. For example, if the level is <code>INFO</code>, the 351 message is <code>foo</code>, then 352 <blockquote> 353 INFO foo 354 </blockquote> 355 will be printed. 356 <p> 357 This is set to <tt>true</tt> by default. 358 */ 359 public void printLevelName(boolean printName) 360 { 361 printLevelName = printName; 362 } 363 364 /** 365 Prints a time stamp with every message. By default this 366 is <tt>false</tt> 367 368 @param val specify true to print time stamps, false 369 to not 370 */ 371 public void printTimestamp(boolean val) { 372 printTimestamp = val; 373 } 374 375 /** 376 Prints a relative time stamp with every message. By 377 default, printing any timestamp is <tt>false</tt>. 378 <b> 379 Timestamps must first be enabled via the {@link printTimestamp} 380 method before this method can have any effect. 381 </b> 382 383 @param val if true, prints a <b>relative</b> time 384 stamp. An initial timestamp is printed and 385 all succeeding timestamps are second 386 increments from the initial timestamp 387 */ 388 public void printRelativeTimestamp(boolean val) { 389 timestampIsRelative = val; 390 last_time = new Date().getTime(); 391 } 392 393 /** 394 By default, method, line and thread information is printed wich each 395 logging statement at the DEBUG level. Other levels print only the log 396 message but skip the method/stack information. 397 <p> 398 This method allows method information to be printed at all levels greater 399 than or equal to the specified level. 400 */ 401 public void printMethodInfoAtLevel(LogLevel level) { 402 this.printMethodInfoAtLevel = level; 403 } 404 405 /** 406 A default implementation that returns an appropriate timestamp based on the 407 timestamp setttings. <b> Multiple threads must synchronize access to this 408 method </b>. Subclasses should call this method in their logging method 409 implementations in the following way. 410 <blockquote> 411 Suppose the subclass uses an out object as a printwriter. Then 412 <br> 413 <code> 414 <b>...in a synchronized block, typically around the output stream....</b> 415 if (printTimestamp) { 416 out.print(getTS()); 417 out.print(" "); 418 } 419 ..... 420 </code> 421 </blockquote> 422 Of course subclasses are free to not call this method or 423 print timestamps in some other fashion. 424 */ 425 protected final String getTS() 426 { 427 date = new Date(); 428 long now = date.getTime(); 429 430 if (timestampIsRelative) 431 { 432 return nf.format( ((now - last_time) / 1000) ) ; 433 } 434 else //non relative ts 435 { 436 if (now - last_time >= 1000) { 437 last_time = now; 438 timestr = df.format(date); 439 } 440 } 441 442 return timestr; 443 } 444 445 /** 446 Sets the current logging level for this logger. Each log has a logging 447 level. A message is printed only if the message level is equal to or lower 448 than the current maximum level for that log. 449 <p> 450 Typically, classes that implement a log will define a bunch of static 451 variables of type {@link LogLevel} that list the available levels for that 452 implementation. Clients of a particular log class should use levels 453 defined within only that class. 454 */ 455 public void setLevel(LogLevel level) { 456 assert level != null : "specified level was null"; 457 currentLevel = level; 458 } 459 460 /** 461 Sets the level of this log based on a level description. This is 462 convenient for when levels are specified in a configuration file. If the 463 specified name cannot be converted into a level, then no change is made. 464 465 @param levelname the level name. For example, 466 <tt>"info"</tt> would set the level of 467 this log to <tt>INFO</tt>. The name 468 is case-<b>in</b>sensitive. 469 */ 470 public void setLevel(String levelname) 471 { 472 if (levelname == null) { 473 warn("specified levelname was null, log level will not be changed"); 474 return; 475 } 476 477 try { 478 Field levelfield = stringToLevel(levelname); 479 if (levelfield == null) { 480 warn("Specified level", levelname, "is not valid/could not be resolved"); 481 return; 482 } 483 484 Method method = Log.class.getMethod("setLevel", new Class[] { LogLevel.class }); 485 //System.out.println("got method="+method); 486 method.invoke(this, new Object[] { levelfield.get(this) }); 487 info("New log level for log=[", name ,"] set to: ", currentLevel); 488 } 489 catch (Exception e) { 490 warn(e); 491 } 492 } 493 494 /* 495 Returns a level field corresponding to the specified case-insensitive 496 string. 497 498 this is kinda overkill but hey: It takes about 5ms so speed 499 isn't an issue and if we ever add more levels, we won't have to 500 update this method. 501 */ 502 protected static Field stringToLevel(String levelname) 503 { 504 Field[] fields = Log.class.getDeclaredFields(); 505 Field levelfield = null; 506 for (int n = 0; n < fields.length; n++) 507 { 508 Field f = fields[n]; 509 if (! f.getType().isAssignableFrom(LogLevel.class)) 510 continue; 511 if (f.getName().equalsIgnoreCase(levelname)) 512 levelfield = f; 513 } 514 return levelfield; 515 } 516 517 /** 518 Sets the level for all logs whose name <b>contain</b> the specified name. 519 This is convenient when changing log levels for package heirarchies. A 520 empty string (non-null) "" sets the level for all logs. 521 522 @param levelname the level name. For example, 523 <tt>"info"</tt> would set the level of 524 this log to <tt>INFO</tt>. The name 525 is case-<b>in</b>sensitive. 526 */ 527 public static void setLevelForAll(String name, LogLevel level) 528 { 529 Iterator i = logs.keySet().iterator(); 530 while (i.hasNext()) { 531 String logname = (String) i.next(); 532 if (logname.contains(logname)) { 533 ((Log)logs.get(logname)).setLevel(level); 534 } 535 } 536 } 537 538 /** 539 Sets the new default logging level for all new instances of loggers 540 (that are created after this method is invoked). 541 */ 542 public static void setDefaultLevel(LogLevel level) 543 { 544 DEFAULT_LEVEL = level; 545 } 546 547 /** 548 Sets the new default logging level for all new instances of loggers 549 (created after this method is invoked). 550 */ 551 public static void setDefaultLevel(String level) 552 { 553 if (level == null) { 554 new Exception("the specified level was null, log level will not be changed").printStackTrace(); 555 return; 556 } 557 558 try { 559 Field levelfield = stringToLevel(level); 560 if (levelfield == null) 561 return; 562 563 Method method = Log.class.getMethod("setDefaultLevel", new Class[] { LogLevel.class }); 564 //System.out.println("got method="+method); 565 method.invoke(null, new Object[] { levelfield.get(null) }); 566 } 567 catch (Exception e) { 568 e.printStackTrace(); 569 } 570 } 571 572 /** 573 Returns <tt>true</tt> if the log's current level will allow logging 574 messages at the specified logging level. 575 <p> 576 Implementation Note: If the currentLevel is lesser or equal to the 577 specified level returns true, else false. Subclasses can override this 578 method if needed. 579 580 @param level the specified logging level 581 */ 582 public boolean canLog(LogLevel level) 583 { 584 assert level != null : "specified level was null"; 585 if (level.intval > currentLevel.intval) 586 return false; 587 return true; 588 } 589 590 /** 591 Returns the name of this log. 592 */ 593 public String getName() { 594 return name; 595 } 596 597 /** 598 Returns the current level set for this log. Useful when 599 printing out debugging info. 600 */ 601 public LogLevel getLevel() { 602 return currentLevel; 603 } 604 605 public void logSystemInfo() 606 { 607 StringBuffer buf = new StringBuffer(1024); 608 Properties p = System.getProperties(); 609 Enumeration e = p.propertyNames(); 610 while (e.hasMoreElements()) { 611 buf.append(IOUtil.LINE_SEP); 612 String name = (String) e.nextElement(); 613 614 buf.append(name).append("="); 615 616 if (name.equals("line.separator")) { 617 buf.append(StringUtil.viewableAscii(p.getProperty(name))); 618 } 619 else{ 620 buf.append(p.getProperty(name)); 621 } 622 } 623 buf.append(IOUtil.LINE_SEP); 624 info(buf.toString()); 625 } 626 627 public String toString() 628 { 629 return name + " [" + getClass().getName() + 630 "/currentlevel:" + currentLevel.desc + 631 "/started:" + startTimeString + "]"; 632 } 633 634 //--methods for various levels 635 public final void error(final Object str1) { 636 doLog(ERROR, str1); 637 } 638 639 public final void error(final Object str1, final Object str2) { 640 doLog(ERROR, str1, str2); 641 } 642 643 public final void error(final Object str1, final Object str2, final Object str3) { 644 doLog(ERROR, str1, str2, str3); 645 } 646 647 public final void error(final Object str1, final Object str2, final Object str3, final Object str4) { 648 doLog(ERROR, str1, str2, str3, str4); 649 } 650 651 public final void error(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5) { 652 doLog(ERROR, str1, str2, str3, str4, str5); 653 } 654 655 public final void error(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6) { 656 doLog(ERROR, str1, str2, str3, str4, str5, str6); 657 } 658 659 public final void error(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7) { 660 doLog(ERROR, str1, str2, str3, str4, str5, str6, str7); 661 } 662 663 public final void error(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7, Object... args) { 664 doLog(ERROR, str1, str2, str3, str4, str5, str6, str7, args); 665 } 666 667 public final void warn(final Object str1) { 668 doLog(WARN, str1); 669 } 670 671 public final void warn(final Object str1, final Object str2) { 672 doLog(WARN, str1, str2); 673 } 674 675 public final void warn(final Object str1, final Object str2, final Object str3) { 676 doLog(WARN, str1, str2, str3); 677 } 678 679 public final void warn(final Object str1, final Object str2, final Object str3, final Object str4) { 680 doLog(WARN, str1, str2, str3, str4); 681 } 682 683 public final void warn(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5) { 684 doLog(WARN, str1, str2, str3, str4, str5); 685 } 686 687 public final void warn(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6) { 688 doLog(WARN, str1, str2, str3, str4, str5, str6); 689 } 690 691 public final void warn(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7) { 692 doLog(WARN, str1, str2, str3, str4, str5, str6, str7); 693 } 694 695 public final void warn(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7, Object... args) { 696 doLog(WARN, str1, str2, str3, str4, str5, str6, str7, args); 697 } 698 699 public final void info(final Object str1) { 700 doLog(INFO, str1); 701 } 702 703 public final void info(final Object str1, final Object str2) { 704 doLog(INFO, str1, str2); 705 } 706 707 public final void info(final Object str1, final Object str2, final Object str3) { 708 doLog(INFO, str1, str2, str3); 709 } 710 711 public final void info(final Object str1, final Object str2, final Object str3, final Object str4) { 712 doLog(INFO, str1, str2, str3, str4); 713 } 714 715 public final void info(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5) { 716 doLog(INFO, str1, str2, str3, str4, str5); 717 } 718 719 public final void info(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6) { 720 doLog(INFO, str1, str2, str3, str4, str5, str6); 721 } 722 723 public final void info(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7) { 724 doLog(INFO, str1, str2, str3, str4, str5, str6, str7); 725 } 726 727 public final void info(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7, Object... args) { 728 doLog(INFO, str1, str2, str3, str4, str5, str6, str7, args); 729 } 730 731 public final void debug(final Object str1) { 732 doLog(DEBUG, str1); 733 } 734 735 public final void debug(final Object str1, final Object str2) { 736 doLog(DEBUG, str1, str2); 737 } 738 739 public final void debug(final Object str1, final Object str2, final Object str3) { 740 doLog(DEBUG, str1, str2, str3); 741 } 742 743 public final void debug(final Object str1, final Object str2, final Object str3, final Object str4) { 744 doLog(DEBUG, str1, str2, str3, str4); 745 } 746 747 public final void debug(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5) { 748 doLog(DEBUG, str1, str2, str3, str4, str5); 749 } 750 751 public final void debug(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6) { 752 doLog(DEBUG, str1, str2, str3, str4, str5, str6); 753 } 754 755 public final void debug(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7) { 756 doLog(DEBUG, str1, str2, str3, str4, str5, str6, str7); 757 } 758 759 public final void debug(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7, Object... args) { 760 doLog(DEBUG, str1, str2, str3, str4, str5, str6, str7, args); 761 } 762 763 public final void bug(final Object str1) { 764 doLog(DEBUG, str1); 765 } 766 767 public final void bug(final Object str1, final Object str2) { 768 doLog(DEBUG, str1, str2); 769 } 770 771 public final void bug(final Object str1, final Object str2, final Object str3) { 772 doLog(DEBUG, str1, str2, str3); 773 } 774 775 public final void bug(final Object str1, final Object str2, final Object str3, final Object str4) { 776 doLog(DEBUG, str1, str2, str3, str4); 777 } 778 779 public final void bug(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5) { 780 doLog(DEBUG, str1, str2, str3, str4, str5); 781 } 782 783 public final void bug(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6) { 784 doLog(DEBUG, str1, str2, str3, str4, str5, str6); 785 } 786 787 public final void bug(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7) { 788 doLog(DEBUG, str1, str2, str3, str4, str5, str6, str7); 789 } 790 791 public final void bug(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7, Object... args) { 792 doLog(DEBUG, str1, str2, str3, str4, str5, str6, str7, args); 793 } 794 795 final void doLog(final LogLevel level, final Object str1) 796 { 797 if (level.intval > currentLevel.intval) 798 return; 799 800 log(level, getDebugContext(level, 3), str1); 801 } 802 803 final void doLog(final LogLevel level, final Object str1, final Object str2) 804 { 805 if (level.intval > currentLevel.intval) 806 return; 807 808 log(level, getDebugContext(level, 3), str1, str2); 809 } 810 811 final void doLog(final LogLevel level, final Object str1, 812 final Object str2, final Object str3) 813 { 814 if (level.intval > currentLevel.intval) 815 return; 816 817 log(level, getDebugContext(level, 3), str1, str2, str3); 818 } 819 820 final void doLog(final LogLevel level, final Object str1, final Object str2, 821 final Object str3, final Object str4) 822 { 823 if (level.intval > currentLevel.intval) 824 return; 825 826 log(level, getDebugContext(level, 3), str1, str2, str3, str4); 827 } 828 829 final void doLog(final LogLevel level, final Object str1, final Object str2, 830 final Object str3, final Object str4, final Object str5) 831 { 832 if (level.intval > currentLevel.intval) 833 return; 834 835 log(level, getDebugContext(level, 3), str1, str2, str3, str4, str5); 836 } 837 838 final void doLog(final LogLevel level, final Object str1, final Object str2, 839 final Object str3, final Object str4, final Object str5, 840 final Object str6) 841 { 842 if (level.intval > currentLevel.intval) 843 return; 844 845 log(level, getDebugContext(level, 3), str1, str2, str3, str4, str5, str6); 846 } 847 848 final void doLog(final LogLevel level, final Object str1, final Object str2, 849 final Object str3, final Object str4, final Object str5, 850 final Object str6, final Object str7) 851 { 852 if (level.intval > currentLevel.intval) 853 return; 854 855 log(level, getDebugContext(level, 3), str1, str2, str3, str4, str5, str6, str7); 856 } 857 858 final void doLog(final LogLevel level, final Object str1, final Object str2, 859 final Object str3, final Object str4, final Object str5, 860 final Object str6, final Object str7, Object... args) 861 { 862 if (level.intval > currentLevel.intval) 863 return; 864 865 log(level, getDebugContext(level, 3), str1, str2, str3, str4, str5, str6, str7, args); 866 } 867 868 869 //--abstract methods-- 870 871 public abstract void close(); 872 873 874 /** 875 @param level the current log level. This can be logged 876 as well. 877 @param str1 unless overridden in a subclass, this is the 878 value returned by {@link getDebugContext} and 879 is generated automatically by the warn(), 880 info(), debug() etc., methods 881 */ 882 public abstract void log(LogLevel level, Object str1); 883 884 /** 885 @param level the current log level. This can be logged 886 as well. 887 @param str1 unless overridden in a subclass, this is the 888 value returned by {@link getDebugContext} and 889 is generated automatically by the warn(), 890 info(), debug() etc., methods 891 @param str2_onwards 892 some arbitrary object 893 */ 894 public abstract void log(LogLevel level, final Object str1, final Object str2); 895 896 /** 897 @param level the current log level. This can be logged 898 as well. 899 @param str1 unless overridden in a subclass, this is the 900 value returned by {@link getDebugContext} and 901 is generated automatically by the warn(), 902 info(), debug() etc., methods 903 @param str2_onwards 904 some arbitrary object 905 */ 906 public abstract void log(LogLevel level, final Object str1, final Object str2, final Object str3); 907 908 /** 909 @param level the current log level. This can be logged 910 as well. 911 @param str1 unless overridden in a subclass, this is the 912 value returned by {@link getDebugContext} and 913 is generated automatically by the warn(), 914 info(), debug() etc., methods 915 @param str2_onwards 916 some arbitrary object 917 */ 918 public abstract void log(LogLevel level, final Object str1, final Object str2, final Object str3, final Object str4); 919 920 /** 921 @param level the current log level. This can be logged 922 as well. 923 @param str1 unless overridden in a subclass, this is the 924 value returned by {@link getDebugContext} and 925 is generated automatically by the warn(), 926 info(), debug() etc., methods 927 @param str2_onwards 928 some arbitrary object 929 */ 930 public abstract void log(LogLevel level, final Object str1, final Object str2, final Object str3, final Object str4, final Object str5); 931 932 /** 933 @param level the current log level. This can be logged 934 as well. 935 @param str1 unless overridden in a subclass, this is the 936 value returned by {@link getDebugContext} and 937 is generated automatically by the warn(), 938 info(), debug() etc., methods 939 @param str2_onwards 940 some arbitrary object 941 */ 942 public abstract void log(LogLevel level, final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6); 943 944 /** 945 @param level the current log level. This can be logged 946 as well. 947 @param str1 unless overridden in a subclass, this is the 948 value returned by {@link getDebugContext} and 949 is generated automatically by the warn(), 950 info(), debug() etc., methods 951 @param str2_onwards 952 some arbitrary object 953 */ 954 public abstract void log(LogLevel level, final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7); 955 956 /** 957 @param level the current log level. This can be logged 958 as well. 959 @param str1 unless overridden in a subclass, this is the 960 value returned by {@link getDebugContext} and 961 is generated automatically by the warn(), 962 info(), debug() etc., methods 963 @param str2_onwards 964 some arbitrary object 965 */ 966 public abstract void log(LogLevel level, final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7, Object str8); 967 968 /** 969 @param level the current log level. This can be logged 970 as well. 971 @param str1 unless overridden in a subclass, this is the 972 value returned by {@link getDebugContext} and 973 is generated automatically by the warn(), 974 info(), debug() etc., methods 975 @param str2_onwards 976 some arbitrary object 977 */ 978 public abstract void log(LogLevel level, final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6, final Object str7, Object str8, Object... args); 979 } //~class Log 980 981