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