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 it's 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 Convenience method that returns the log named after the <b>package</b> that
180 the specified class belong to. If 2 classes <pre>a.b.Class1</pre> and
181 <pre>a.b.Class2</pre> call this method, they will get the same logger
182 (named <tt>a.b</tt>).
183 <p>
184 If the log does not already exist, creates and returns a new {@link SystemLog}
185 with that name.
186
187 @param c a non-null class
188 */
189 public final static Log get(Class c)
190 {
191 Argcheck.notnull(c, "class parameter was null");
192 final Package p = c.getPackage();
193 final String name = (p == null) ? "default_pkg" : p.toString();
194 return get(name);
195 }
196
197 /**
198 Convenience method that returns a log named after the <b>package</b> that
199 the specified object's class belong to. If 2 objects of class
200 <pre>a.b.Class1</pre> and <pre>a.b.Class2</pre> call this method, they
201 will get the same logger (named <tt>a.b</tt>).
202 <p>
203 If the log does not already exist, creates and returns a new {@link SystemLog}
204 with that name.
205
206 @param obj a non-null object
207 */
208 public final static Log get(Object obj)
209 {
210 Argcheck.notnull(obj, "class parameter was null");
211 return get(obj.getClass().getPackage().toString());
212 }
213
214 /**
215 Returns the default system log. This system log writes to
216 <tt>System.err</tt> and has it's level set to {@link SystemLog#INFO}. This
217 level can be changed to some other level if desired by invoking {@link
218 setLevel()} on the returned object.
219 */
220 public static SystemLog getDefault()
221 {
222 synchronized (Log.class)
223 {
224 if (defaultlog == null) {
225 defaultlog = new SystemLog(
226 "_defaultlog", System.out, SystemLog.INFO);
227 }
228 }
229 return defaultlog;
230 }
231
232
233 /**
234 Returns an iteration containing level names for this log. The names can be in
235 any order.
236 */
237 public Iterator getLevelNames()
238 {
239 Class myclass = getClass();
240 Field[] fields = myclass.getDeclaredFields();
241 Field levelfield = null;
242 List l = new ArrayList();
243 for (int n = 0; n < fields.length; n++)
244 {
245 Field f = fields[n];
246 if (! f.getType().isAssignableFrom(LogLevel.class))
247 continue;
248 l.add(f.getName());
249 }
250 return l.iterator();
251 }
252
253 /*
254 Manually adds the specified log to the list of all logs. If a log with
255 that name already exists, an <tt>IllegalArgumentException</tt> is thrown.
256 <p> This method is useful when creating a new logging object manaually.
257 So for example:
258 <blockquote>
259 <pre>
260 MyLogClass mylog = new MyLogClass("foo.bar");
261 Log.addLog(mylog)
262 </pre>
263 </blockquote>
264 Contrast that with the more usual:
265 <blockquote>
266 <pre>
267 Log.getLog("foo.bar");
268 </pre>
269 </blockquote>
270 <p>
271 <u>Custom log implementations should always call this method in their
272 constructor to add themselves to the list of all logs.</u>
273 */
274 protected static void addLog(Log log)
275 {
276 synchronized(logs)
277 {
278 if (! logs.containsKey(log.name)) {
279 logs.put(log.name, log);
280 }
281 else throw new IllegalArgumentException("Log already exists: " + log);
282 }
283 }
284
285 /**
286 Closes and removes the log with the specified name if it exists
287 */
288 public static void closeLog(String name)
289 {
290 if (logs.containsKey(name)) {
291 Log l = (Log) logs.get(name);
292 l.close();
293 logs.remove(name);
294 }
295 }
296
297 /**
298 Returns the method name, file number and line number
299 of the calling method. Useful for logging/code tracing.
300
301 @param level the level for which this logging call was invoked.
302 @param framenum the method to examine. This method itself
303 has frame number 0, the calling method
304 has frame number 1, it's parent 2 and so on.
305 **/
306 public final String getDebugContext(LogLevel level, int framenum)
307 {
308 if (level.intval < printMethodInfoAtLevel.intval) {
309 return "";
310 }
311
312 StackTraceElement ste[] = new Exception().getStackTrace();
313 if (framenum >= ste.length)
314 throw new IllegalArgumentException(
315 "framenum [" + framenum
316 + "] too large. Max number of record in stack = "
317 + (ste.length - 1));
318
319 //get method that called us, we are ste[0]
320 StackTraceElement st = ste[framenum];
321 String file = st.getFileName();
322 int line = st.getLineNumber();
323 String method = st.getMethodName();
324 String threadname = Thread.currentThread().getName();
325 //String classn = st.getClassName();
326 return method + "() [" + file + ":" + line + "/thread:" + threadname + "]";
327 }
328
329
330 /**
331 If set to true, will print the level name before the logging
332 message. For example, if the level is <code>INFO</code>, the
333 message is <code>foo</code>, then
334 <blockquote>
335 INFO foo
336 </blockquote>
337 will be printed.
338 <p>
339 This is set to <tt>true</tt> by default.
340 */
341 public void printLevelName(boolean printName)
342 {
343 printLevelName = printName;
344 }
345
346 /**
347 Prints a time stamp with every message. By default this
348 is <tt>false</tt>
349
350 @param val specify true to print time stamps, false
351 to not
352 */
353 public void printTimestamp(boolean val) {
354 printTimestamp = val;
355 }
356
357 /**
358 Prints a relative time stamp with every message. By
359 default, printing any timestamp is <tt>false</tt>.
360 <b>
361 Timestamps must first be enabled via the {@link printTimestamp}
362 method before this method can have any effect.
363 </b>
364
365 @param val if true, prints a <b>relative</b> time
366 stamp. An initial timestamp is printed and
367 all succeeding timestamps are second
368 increments from the initial timestamp
369 */
370 public void printRelativeTimestamp(boolean val) {
371 timestampIsRelative = val;
372 last_time = new Date().getTime();
373 }
374
375 /**
376 By default, method, line and thread information is printed wich each
377 logging statement at the DEBUG level. Other levels print only the log
378 message but skip the method/stack information.
379 <p>
380 This method allows method information to be printed at all levels greater
381 than or equal to the specified level.
382 */
383 public void printMethodInfoAtLevel(LogLevel level) {
384 this.printMethodInfoAtLevel = level;
385 }
386
387 /**
388 A default implementation that returns an appropriate timestamp based on the
389 timestamp setttings. <b> Multiple threads must synchronize access to this
390 method </b>. Subclasses should call this method in their logging method
391 implementations in the following way.
392 <blockquote>
393 Suppose the subclass uses an out object as a printwriter. Then
394 <br>
395 <code>
396 <b>...in a synchronized block, typically around the output stream....</b>
397 if (printTimestamp) {
398 out.print(getTS());
399 out.print(" ");
400 }
401 .....
402 </code>
403 </blockquote>
404 Of course subclasses are free to not call this method or
405 print timestamps in some other fashion.
406 */
407 protected final String getTS()
408 {
409 date = new Date();
410 long now = date.getTime();
411
412 if (timestampIsRelative)
413 {
414 return nf.format( ((now - last_time) / 1000) ) ;
415 }
416 else //non relative ts
417 {
418 if (now - last_time >= 1000) {
419 last_time = now;
420 timestr = df.format(date);
421 }
422 }
423
424 return timestr;
425 }
426
427 /**
428 Sets the current logging level for this logger. Each log has a logging
429 level. A message is printed only if the message level is equal to or lower
430 than the current maximum level for that log.
431 <p>
432 Typically, classes that implement a log will define a bunch of static
433 variables of type {@link LogLevel} that list the available levels for that
434 implementation. Clients of a particular log class should use levels
435 defined within only that class.
436 */
437 public void setLevel(LogLevel level) {
438 assert level != null : "specified level was null";
439 currentLevel = level;
440 }
441
442 /**
443 Sets the level of this log based on a level description. This is
444 convenient for when levels are specified in a configuration file. If the
445 specified name cannot be converted into a level, then no change is made.
446
447 @param levelname the level name. For example,
448 <tt>"info"</tt> would set the level of
449 this log to <tt>INFO</tt>. The name
450 is case-<b>in</b>sensitive.
451 */
452 public void setLevel(String levelname)
453 {
454 if (levelname == null) {
455 warn("specified levelname was null, log level will not be changed");
456 return;
457 }
458
459 try {
460 Field levelfield = stringToLevel(levelname);
461 if (levelfield == null) {
462 warn("Specified level", levelname, "is not valid/could not be resolved");
463 return;
464 }
465
466 Method method = Log.class.getMethod("setLevel", new Class[] { LogLevel.class });
467 //System.out.println("got method="+method);
468 method.invoke(this, new Object[] { levelfield.get(this) });
469 info("New log level set to: ", currentLevel);
470 }
471 catch (Exception e) {
472 warn(e);
473 }
474 }
475
476 /*
477 Returns a level field corresponding to the specified case-insensitive
478 string.
479
480 this is kinda overkill but hey: It takes about 5ms so speed
481 isn't an issue and if we ever add more levels, we won't have to
482 update this method.
483 */
484 protected static Field stringToLevel(String levelname)
485 {
486 Field[] fields = Log.class.getDeclaredFields();
487 Field levelfield = null;
488 for (int n = 0; n < fields.length; n++)
489 {
490 Field f = fields[n];
491 if (! f.getType().isAssignableFrom(LogLevel.class))
492 continue;
493 if (f.getName().equalsIgnoreCase(levelname))
494 levelfield = f;
495 }
496 return levelfield;
497 }
498
499 /**
500 Sets the level for all logs whose name <b>contain</b> the specified name.
501 This is convenient when changing log levels for package heirarchies. A
502 empty string (non-null) "" sets the level for all logs.
503
504 @param levelname the level name. For example,
505 <tt>"info"</tt> would set the level of
506 this log to <tt>INFO</tt>. The name
507 is case-<b>in</b>sensitive.
508 */
509 public static void setLevelForAll(String name, LogLevel level)
510 {
511 Iterator i = logs.keySet().iterator();
512 while (i.hasNext()) {
513 String logname = (String) i.next();
514 if (logname.contains(logname)) {
515 ((Log)logs.get(logname)).setLevel(level);
516 }
517 }
518 }
519
520 /**
521 Sets the new default logging level for all new instances of loggers
522 (that are created after this method is invoked).
523 */
524 public static void setDefaultLevel(LogLevel level)
525 {
526 DEFAULT_LEVEL = level;
527 }
528
529 /**
530 Sets the new default logging level for all new instances of loggers
531 (created after this method is invoked).
532 */
533 public static void setDefaultLevel(String level)
534 {
535 if (level == null) {
536 new Exception("the specified level was null, log level will not be changed").printStackTrace();
537 return;
538 }
539
540 try {
541 Field levelfield = stringToLevel(level);
542 if (levelfield == null)
543 return;
544
545 Method method = Log.class.getMethod("setDefaultLevel", new Class[] { LogLevel.class });
546 //System.out.println("got method="+method);
547 method.invoke(null, new Object[] { levelfield.get(null) });
548 }
549 catch (Exception e) {
550 e.printStackTrace();
551 }
552 }
553
554 /**
555 Returns <tt>true</tt> if the log's current level will allow logging
556 messages at the specified logging level.
557 <p>
558 Implementation Note: If the currentLevel is lesser or equal to the
559 specified level returns true, else false. Subclasses can override this
560 method if needed.
561
562 @param level the specified logging level
563 */
564 public boolean canLog(LogLevel level)
565 {
566 assert level != null : "specified level was null";
567 if (level.intval > currentLevel.intval)
568 return false;
569 return true;
570 }
571
572 /**
573 Returns the name of this log.
574 */
575 public String getName() {
576 return name;
577 }
578
579 /**
580 Returns the current level set for this log. Useful when
581 printing out debugging info.
582 */
583 public LogLevel getLevel() {
584 return currentLevel;
585 }
586
587 public void logSystemInfo()
588 {
589 StringBuffer buf = new StringBuffer(1024);
590 Properties p = System.getProperties();
591 Enumeration e = p.propertyNames();
592 while (e.hasMoreElements()) {
593 buf.append(IOUtil.LINE_SEP);
594 String name = (String) e.nextElement();
595
596 buf.append(name).append("=");
597
598 if (name.equals("line.separator"))
599 buf.append(StringUtil.viewableAscii(
600 p.getProperty(name)));
601 else
602 buf.append(p.getProperty(name));
603 }
604 buf.append(IOUtil.LINE_SEP);
605 info(buf.toString());
606 }
607
608 public String toString()
609 {
610 return name + " [" + getClass().getName() +
611 "/currentlevel:" + currentLevel.desc +
612 "/started:" + startTimeString + "]";
613 }
614
615 //--methods for various levels
616 public final void error(final Object str1) {
617 doLog(ERROR, str1);
618 }
619
620 public final void error(final Object str1, final Object str2) {
621 doLog(ERROR, str1, str2);
622 }
623
624 public final void error(final Object str1, final Object str2, final Object str3) {
625 doLog(ERROR, str1, str2, str3);
626 }
627
628 public final void error(final Object str1, final Object str2, final Object str3, final Object str4) {
629 doLog(ERROR, str1, str2, str3, str4);
630 }
631
632 public final void error(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5) {
633 doLog(ERROR, str1, str2, str3, str4, str5);
634 }
635
636 public final void error(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6) {
637 doLog(ERROR, str1, str2, str3, str4, str5, str6);
638 }
639
640 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) {
641 doLog(ERROR, str1, str2, str3, str4, str5, str6, str7);
642 }
643
644 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) {
645 doLog(ERROR, str1, str2, str3, str4, str5, str6, str7, args);
646 }
647
648 public final void warn(final Object str1) {
649 doLog(WARN, str1);
650 }
651
652 public final void warn(final Object str1, final Object str2) {
653 doLog(WARN, str1, str2);
654 }
655
656 public final void warn(final Object str1, final Object str2, final Object str3) {
657 doLog(WARN, str1, str2, str3);
658 }
659
660 public final void warn(final Object str1, final Object str2, final Object str3, final Object str4) {
661 doLog(WARN, str1, str2, str3, str4);
662 }
663
664 public final void warn(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5) {
665 doLog(WARN, str1, str2, str3, str4, str5);
666 }
667
668 public final void warn(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6) {
669 doLog(WARN, str1, str2, str3, str4, str5, str6);
670 }
671
672 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) {
673 doLog(WARN, str1, str2, str3, str4, str5, str6, str7);
674 }
675
676 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) {
677 doLog(WARN, str1, str2, str3, str4, str5, str6, str7, args);
678 }
679
680 public final void info(final Object str1) {
681 doLog(INFO, str1);
682 }
683
684 public final void info(final Object str1, final Object str2) {
685 doLog(INFO, str1, str2);
686 }
687
688 public final void info(final Object str1, final Object str2, final Object str3) {
689 doLog(INFO, str1, str2, str3);
690 }
691
692 public final void info(final Object str1, final Object str2, final Object str3, final Object str4) {
693 doLog(INFO, str1, str2, str3, str4);
694 }
695
696 public final void info(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5) {
697 doLog(INFO, str1, str2, str3, str4, str5);
698 }
699
700 public final void info(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6) {
701 doLog(INFO, str1, str2, str3, str4, str5, str6);
702 }
703
704 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) {
705 doLog(INFO, str1, str2, str3, str4, str5, str6, str7);
706 }
707
708 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) {
709 doLog(INFO, str1, str2, str3, str4, str5, str6, str7, args);
710 }
711
712 public final void debug(final Object str1) {
713 doLog(DEBUG, str1);
714 }
715
716 public final void debug(final Object str1, final Object str2) {
717 doLog(DEBUG, str1, str2);
718 }
719
720 public final void debug(final Object str1, final Object str2, final Object str3) {
721 doLog(DEBUG, str1, str2, str3);
722 }
723
724 public final void debug(final Object str1, final Object str2, final Object str3, final Object str4) {
725 doLog(DEBUG, str1, str2, str3, str4);
726 }
727
728 public final void debug(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5) {
729 doLog(DEBUG, str1, str2, str3, str4, str5);
730 }
731
732 public final void debug(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6) {
733 doLog(DEBUG, str1, str2, str3, str4, str5, str6);
734 }
735
736 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) {
737 doLog(DEBUG, str1, str2, str3, str4, str5, str6, str7);
738 }
739
740 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) {
741 doLog(DEBUG, str1, str2, str3, str4, str5, str6, str7, args);
742 }
743
744 public final void bug(final Object str1) {
745 doLog(DEBUG, str1);
746 }
747
748 public final void bug(final Object str1, final Object str2) {
749 doLog(DEBUG, str1, str2);
750 }
751
752 public final void bug(final Object str1, final Object str2, final Object str3) {
753 doLog(DEBUG, str1, str2, str3);
754 }
755
756 public final void bug(final Object str1, final Object str2, final Object str3, final Object str4) {
757 doLog(DEBUG, str1, str2, str3, str4);
758 }
759
760 public final void bug(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5) {
761 doLog(DEBUG, str1, str2, str3, str4, str5);
762 }
763
764 public final void bug(final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6) {
765 doLog(DEBUG, str1, str2, str3, str4, str5, str6);
766 }
767
768 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) {
769 doLog(DEBUG, str1, str2, str3, str4, str5, str6, str7);
770 }
771
772 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) {
773 doLog(DEBUG, str1, str2, str3, str4, str5, str6, str7, args);
774 }
775
776 final void doLog(final LogLevel level, final Object str1)
777 {
778 if (level.intval > currentLevel.intval)
779 return;
780
781 log(level, getDebugContext(level, 3), str1);
782 }
783
784 final void doLog(final LogLevel level, final Object str1, final Object str2)
785 {
786 if (level.intval > currentLevel.intval)
787 return;
788
789 log(level, getDebugContext(level, 3), str1, str2);
790 }
791
792 final void doLog(final LogLevel level, final Object str1,
793 final Object str2, final Object str3)
794 {
795 if (level.intval > currentLevel.intval)
796 return;
797
798 log(level, getDebugContext(level, 3), str1, str2, str3);
799 }
800
801 final void doLog(final LogLevel level, final Object str1, final Object str2,
802 final Object str3, final Object str4)
803 {
804 if (level.intval > currentLevel.intval)
805 return;
806
807 log(level, getDebugContext(level, 3), str1, str2, str3, str4);
808 }
809
810 final void doLog(final LogLevel level, final Object str1, final Object str2,
811 final Object str3, final Object str4, final Object str5)
812 {
813 if (level.intval > currentLevel.intval)
814 return;
815
816 log(level, getDebugContext(level, 3), str1, str2, str3, str4, str5);
817 }
818
819 final void doLog(final LogLevel level, final Object str1, final Object str2,
820 final Object str3, final Object str4, final Object str5,
821 final Object str6)
822 {
823 if (level.intval > currentLevel.intval)
824 return;
825
826 log(level, getDebugContext(level, 3), str1, str2, str3, str4, str5, str6);
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 final Object str6, final Object str7)
832 {
833 if (level.intval > currentLevel.intval)
834 return;
835
836 log(level, getDebugContext(level, 3), str1, str2, str3, str4, str5, str6, str7);
837 }
838
839 final void doLog(final LogLevel level, final Object str1, final Object str2,
840 final Object str3, final Object str4, final Object str5,
841 final Object str6, final Object str7, Object... args)
842 {
843 if (level.intval > currentLevel.intval)
844 return;
845
846 log(level, getDebugContext(level, 3), str1, str2, str3, str4, str5, str6, str7, args);
847 }
848
849
850 //--abstract methods--
851
852 public abstract void close();
853
854
855 /**
856 @param level the current log level. This can be logged
857 as well.
858 @param str1 unless overridden in a subclass, this is the
859 value returned by {@link getDebugContext} and
860 is generated automatically by the warn(),
861 info(), debug() etc., methods
862 */
863 public abstract void log(LogLevel level, Object str1);
864
865 /**
866 @param level the current log level. This can be logged
867 as well.
868 @param str1 unless overridden in a subclass, this is the
869 value returned by {@link getDebugContext} and
870 is generated automatically by the warn(),
871 info(), debug() etc., methods
872 @param str2_onwards
873 some arbitrary object
874 */
875 public abstract void log(LogLevel level, final Object str1, final Object str2);
876
877 /**
878 @param level the current log level. This can be logged
879 as well.
880 @param str1 unless overridden in a subclass, this is the
881 value returned by {@link getDebugContext} and
882 is generated automatically by the warn(),
883 info(), debug() etc., methods
884 @param str2_onwards
885 some arbitrary object
886 */
887 public abstract void log(LogLevel level, final Object str1, final Object str2, final Object str3);
888
889 /**
890 @param level the current log level. This can be logged
891 as well.
892 @param str1 unless overridden in a subclass, this is the
893 value returned by {@link getDebugContext} and
894 is generated automatically by the warn(),
895 info(), debug() etc., methods
896 @param str2_onwards
897 some arbitrary object
898 */
899 public abstract void log(LogLevel level, final Object str1, final Object str2, final Object str3, final Object str4);
900
901 /**
902 @param level the current log level. This can be logged
903 as well.
904 @param str1 unless overridden in a subclass, this is the
905 value returned by {@link getDebugContext} and
906 is generated automatically by the warn(),
907 info(), debug() etc., methods
908 @param str2_onwards
909 some arbitrary object
910 */
911 public abstract void log(LogLevel level, final Object str1, final Object str2, final Object str3, final Object str4, final Object str5);
912
913 /**
914 @param level the current log level. This can be logged
915 as well.
916 @param str1 unless overridden in a subclass, this is the
917 value returned by {@link getDebugContext} and
918 is generated automatically by the warn(),
919 info(), debug() etc., methods
920 @param str2_onwards
921 some arbitrary object
922 */
923 public abstract void log(LogLevel level, final Object str1, final Object str2, final Object str3, final Object str4, final Object str5, final Object str6);
924
925 /**
926 @param level the current log level. This can be logged
927 as well.
928 @param str1 unless overridden in a subclass, this is the
929 value returned by {@link getDebugContext} and
930 is generated automatically by the warn(),
931 info(), debug() etc., methods
932 @param str2_onwards
933 some arbitrary object
934 */
935 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);
936
937 /**
938 @param level the current log level. This can be logged
939 as well.
940 @param str1 unless overridden in a subclass, this is the
941 value returned by {@link getDebugContext} and
942 is generated automatically by the warn(),
943 info(), debug() etc., methods
944 @param str2_onwards
945 some arbitrary object
946 */
947 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);
948
949 /**
950 @param level the current log level. This can be logged
951 as well.
952 @param str1 unless overridden in a subclass, this is the
953 value returned by {@link getDebugContext} and
954 is generated automatically by the warn(),
955 info(), debug() etc., methods
956 @param str2_onwards
957 some arbitrary object
958 */
959 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);
960 } //~class Log
961
962