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 006package fc.io; 007 008import java.text.*; 009import java.util.*; 010import java.lang.reflect.*; 011 012import fc.util.*; 013 014/** 015A system wide logging facility. Clearer and more elegant 016semantics/nomenclature than <tt>java.util.logging</tt>. 017<p> 018Logs messages to some user specified destination(s). Each log has a 019<b>name</b> and a <b>log level</b>. 020<p> 021The names are arbitrary (hopefully descriptive) names, per your liking. Many 022different logs can be created and then later retrieved by their 023name as needed. 024<p> 025The 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> 031The above levels are self-explanatory. 032<p> 033Convenience methods with names equal to a <b>level</b> name are provided. 034So for example, instead of saying: 035 <blockquote> 036 <tt>log(<b>LogLevel.warn</b>, "the message");</tt> 037 </blockquote> 038one 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;"> 044A little historical quirk. For the debug level <tt>LogLevel.debug</b></tt>, 045one 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> 055A default logger of type {@link fc.io.SystemLog} is provided for 056convenience in this class and can be retrieved by calling the {@link 057#getDefault()} method. 058<p> 059The {@link #closeLog(String)} method is called on all logs 060at 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 064prints 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 068return a new log object of that subclass type. These getter methods 069should be static for convenience. Also, the implementation of the 070<tt>subclass.getLog(...)</tt> methods in subclasses is expected by 071convention. 072<p> 073Thread Safety: This class <tt>is</tt> Threadsafe and all its methods can 074be used concurrently. 075 076@author hursh jain 077**/ 078public abstract class Log 079{ 080//--static variables-- 081public static final LogLevel OFF = new LogLevel("OFF", 0); 082public static final LogLevel ERROR = new LogLevel("ERROR", 1); 083public static final LogLevel WARN = new LogLevel("WARN", 2); 084public static final LogLevel INFO = new LogLevel("INFO", 3); 085public static final LogLevel DEBUG = new LogLevel("DEBUG", 4); 086 087/** 088The default level used for new logs. Subclasses should (by default) 089create logs using this level. 090*/ 091public static LogLevel DEFAULT_LEVEL = INFO; 092 093protected static final byte[] linesepbytes = 094 System.getProperty("line.separator").getBytes(); 095 096 //synchronized map needed 097protected static SystemLog defaultlog; 098protected static final Map logs = new Hashtable(); 099 100//--instance variables apply to a particular logger 101protected String name; 102protected LogLevel currentLevel; 103protected long startTime; 104protected String startTimeString; //for toString() 105protected boolean printLevelName = true; 106protected boolean printTimestamp = false; 107protected boolean timestampIsRelative = false; 108protected LogLevel printMethodInfoAtLevel = DEBUG; 109 110//default timestamp data 111protected final SimpleDateFormat df 112 = new SimpleDateFormat("MMM dd H:m:s z"); 113protected final NumberFormat nf 114 = NumberFormat.getNumberInstance(); 115 116protected Date date = new Date(); 117protected long last_time = date.getTime(); 118protected String timestr = df.format(date); 119 120//Add shutdown hook to close all open logs 121static 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/** 137Constructs 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*/ 144protected 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/** 156Returns a {@link SystemLog} with the specified name. If the log does not already 157exist, creates and returns a new SystemLog with that name. 158<p> 159The system log created will have a default destination of <tt>System.err</tt> 160and a default level of {@link Log#INFO}. 161<p> 162To obtain logs with a different destination, create a SystemLog directly. 163*/ 164public 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/** 180An alias for method {@link #get(String)}. 181<p> 182Returns a {@link SystemLog} with the specified name. If the log does not already 183exist, creates and returns a new SystemLog with that name. 184<p> 185The system log created will have a default destination of <tt>System.err</tt> 186and a default level of {@link Log#INFO}. 187<p> 188To obtain logs with a different destination, create a SystemLog directly. 189*/ 190public static Log getLog(String name) 191 { 192 return get(name); 193 } 194 195 196/** 197Convenience method that returns the log named after the <b>package</b> that 198the 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> 202If the log does not already exist, creates and returns a new {@link SystemLog} 203with that name. 204 205@param c a non-null class 206*/ 207public 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/** 216Convenience method that returns a log named after the <b>package</b> that 217the 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 219will get the same logger (named <tt>a.b</tt>). 220<p> 221If the log does not already exist, creates and returns a new {@link SystemLog} 222with that name. 223 224@param obj a non-null object 225*/ 226public 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/** 233Returns 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 235level can be changed to some other level if desired by invoking {@link 236setLevel()} on the returned object. 237*/ 238public 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/** 252Returns an iteration containing level names for this log. The names can be in 253any order. 254*/ 255public 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/* 272Manually adds the specified log to the list of all logs. If a log with 273that name already exists, an <tt>IllegalArgumentException</tt> is thrown. 274<p> This method is useful when creating a new logging object manaually. 275So for example: 276 <blockquote> 277 <pre> 278 MyLogClass mylog = new MyLogClass("foo.bar"); 279 Log.addLog(mylog) 280 </pre> 281 </blockquote> 282Contrast 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 290constructor to add themselves to the list of all logs.</u> 291*/ 292protected 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/** 304Closes and removes the log with the specified name if it exists 305*/ 306public 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/** 316Returns the method name, file number and line number 317of 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**/ 324public 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/** 349If set to true, will print the level name before the logging 350message. For example, if the level is <code>INFO</code>, the 351message is <code>foo</code>, then 352 <blockquote> 353 INFO foo 354 </blockquote> 355will be printed. 356<p> 357This is set to <tt>true</tt> by default. 358*/ 359public void printLevelName(boolean printName) 360 { 361 printLevelName = printName; 362 } 363 364/** 365Prints a time stamp with every message. By default this 366is <tt>false</tt> 367 368@param val specify true to print time stamps, false 369 to not 370*/ 371public void printTimestamp(boolean val) { 372 printTimestamp = val; 373 } 374 375/** 376Prints a relative time stamp with every message. By 377default, printing any timestamp is <tt>false</tt>. 378<b> 379Timestamps must first be enabled via the {@link printTimestamp} 380method 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*/ 388public void printRelativeTimestamp(boolean val) { 389 timestampIsRelative = val; 390 last_time = new Date().getTime(); 391 } 392 393/** 394By default, method, line and thread information is printed wich each 395logging statement at the DEBUG level. Other levels print only the log 396message but skip the method/stack information. 397<p> 398This method allows method information to be printed at all levels greater 399than or equal to the specified level. 400*/ 401public void printMethodInfoAtLevel(LogLevel level) { 402 this.printMethodInfoAtLevel = level; 403 } 404 405/** 406A default implementation that returns an appropriate timestamp based on the 407timestamp setttings. <b> Multiple threads must synchronize access to this 408method </b>. Subclasses should call this method in their logging method 409implementations in the following way. 410<blockquote> 411Suppose 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> 415if (printTimestamp) { 416 out.print(getTS()); 417 out.print(" "); 418 } 419..... 420</code> 421</blockquote> 422Of course subclasses are free to not call this method or 423print timestamps in some other fashion. 424*/ 425protected 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/** 446Sets the current logging level for this logger. Each log has a logging 447level. A message is printed only if the message level is equal to or lower 448than the current maximum level for that log. 449<p> 450Typically, classes that implement a log will define a bunch of static 451variables of type {@link LogLevel} that list the available levels for that 452implementation. Clients of a particular log class should use levels 453defined within only that class. 454*/ 455public void setLevel(LogLevel level) { 456 assert level != null : "specified level was null"; 457 currentLevel = level; 458 } 459 460/** 461Sets the level of this log based on a level description. This is 462convenient for when levels are specified in a configuration file. If the 463specified 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*/ 470public 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/* 495Returns a level field corresponding to the specified case-insensitive 496string. 497 498this is kinda overkill but hey: It takes about 5ms so speed 499isn't an issue and if we ever add more levels, we won't have to 500update this method. 501*/ 502protected 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/** 518Sets the level for all logs whose name <b>contain</b> the specified name. 519This is convenient when changing log levels for package heirarchies. A 520empty 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*/ 527public 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/** 539Sets the new default logging level for all new instances of loggers 540(that are created after this method is invoked). 541*/ 542public static void setDefaultLevel(LogLevel level) 543 { 544 DEFAULT_LEVEL = level; 545 } 546 547/** 548Sets the new default logging level for all new instances of loggers 549(created after this method is invoked). 550*/ 551public 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/** 573Returns <tt>true</tt> if the log's current level will allow logging 574messages at the specified logging level. 575<p> 576Implementation Note: If the currentLevel is lesser or equal to the 577specified level returns true, else false. Subclasses can override this 578method if needed. 579 580@param level the specified logging level 581*/ 582public 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/** 591Returns the name of this log. 592*/ 593public String getName() { 594 return name; 595 } 596 597/** 598Returns the current level set for this log. Useful when 599printing out debugging info. 600*/ 601public LogLevel getLevel() { 602 return currentLevel; 603 } 604 605public 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 627public String toString() 628 { 629 return name + " [" + getClass().getName() + 630 "/currentlevel:" + currentLevel.desc + 631 "/started:" + startTimeString + "]"; 632 } 633 634//--methods for various levels 635public final void error(final Object str1) { 636 doLog(ERROR, str1); 637 } 638 639public final void error(final Object str1, final Object str2) { 640 doLog(ERROR, str1, str2); 641 } 642 643public final void error(final Object str1, final Object str2, final Object str3) { 644 doLog(ERROR, str1, str2, str3); 645 } 646 647public final void error(final Object str1, final Object str2, final Object str3, final Object str4) { 648 doLog(ERROR, str1, str2, str3, str4); 649 } 650 651public 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 655public 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 659public 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 663public 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 667public final void warn(final Object str1) { 668 doLog(WARN, str1); 669 } 670 671public final void warn(final Object str1, final Object str2) { 672 doLog(WARN, str1, str2); 673 } 674 675public final void warn(final Object str1, final Object str2, final Object str3) { 676 doLog(WARN, str1, str2, str3); 677 } 678 679public final void warn(final Object str1, final Object str2, final Object str3, final Object str4) { 680 doLog(WARN, str1, str2, str3, str4); 681 } 682 683public 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 687public 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 691public 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 695public 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 699public final void info(final Object str1) { 700 doLog(INFO, str1); 701 } 702 703public final void info(final Object str1, final Object str2) { 704 doLog(INFO, str1, str2); 705 } 706 707public final void info(final Object str1, final Object str2, final Object str3) { 708 doLog(INFO, str1, str2, str3); 709 } 710 711public final void info(final Object str1, final Object str2, final Object str3, final Object str4) { 712 doLog(INFO, str1, str2, str3, str4); 713 } 714 715public 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 719public 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 723public 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 727public 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 731public final void debug(final Object str1) { 732 doLog(DEBUG, str1); 733 } 734 735public final void debug(final Object str1, final Object str2) { 736 doLog(DEBUG, str1, str2); 737 } 738 739public final void debug(final Object str1, final Object str2, final Object str3) { 740 doLog(DEBUG, str1, str2, str3); 741 } 742 743public final void debug(final Object str1, final Object str2, final Object str3, final Object str4) { 744 doLog(DEBUG, str1, str2, str3, str4); 745 } 746 747public 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 751public 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 755public 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 759public 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 763public final void bug(final Object str1) { 764 doLog(DEBUG, str1); 765 } 766 767public final void bug(final Object str1, final Object str2) { 768 doLog(DEBUG, str1, str2); 769 } 770 771public final void bug(final Object str1, final Object str2, final Object str3) { 772 doLog(DEBUG, str1, str2, str3); 773 } 774 775public final void bug(final Object str1, final Object str2, final Object str3, final Object str4) { 776 doLog(DEBUG, str1, str2, str3, str4); 777 } 778 779public 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 783public 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 787public 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 791public 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 795final 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 803final 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 811final 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 820final 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 829final 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 838final 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 848final 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 858final 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 871public 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*/ 882public 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*/ 894public 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*/ 906public 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*/ 918public 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*/ 930public 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*/ 942public 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*/ 954public 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*/ 966public 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*/ 978public 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