KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > grlea > log > SimpleLogger


1 package org.grlea.log;
2
3 // $Id: SimpleLogger.java,v 1.12 2006/07/13 12:40:06 grlea Exp $
4
// Copyright (c) 2004-2006 Graham Lea. All rights reserved.
5

6 // Licensed under the Apache License, Version 2.0 (the "License");
7
// you may not use this file except in compliance with the License.
8
// You may obtain a copy of the License at
9
//
10
// http://www.apache.org/licenses/LICENSE-2.0
11
//
12
// Unless required by applicable law or agreed to in writing, software
13
// distributed under the License is distributed on an "AS IS" BASIS,
14
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
// See the License for the specific language governing permissions and
16
// limitations under the License.
17

18 import java.text.MessageFormat JavaDoc;
19 import java.util.Date JavaDoc;
20
21 /**
22  * <p>Used to create log messages for a single class or instance of a class.</p>
23  *
24  * <p><code>SimpleLogger</code> is where it all happens, from a client's perspective.<br>
25  * The easiest way to use Simple Log is to create one <code>SimpleLogger</code> for each class and
26  * then log to it!</p>
27  *
28  * <p>1. Create a logger like this:<pre>
29  * private static final SimpleLogger log = new SimpleLogger(HelloWorld.class);
30  * </pre></p>
31  *
32  * <p>2. And then use it like this:<pre>
33  * log.entry("main()");
34  * log.debugObject("argv", argv);
35  * if (argv.length == 0)
36  * {
37  * log.info("No arguments. Using defaults.");
38  * ...
39  * }
40  * ...
41  * log.exit("main()");
42  * </pre></p>
43  *
44  * <p>
45  * <code>SimpleLogger</code> provides for four types of log messages:
46  * <ul>
47  * <li>
48  * "db" = Debug (see {@link #db SimpleLogger.db()})<br>
49  * Lets you log a simple log message, e.g. "Got to the point where you thought it wasn't
50  * getting to."
51  * </li><br><br>
52  * <li>
53  * "dbo" = Debug Object
54  * (see {@link #dbo(DebugLevel,String,Object) SimpleLogger.dbo()})
55  * <br>
56  * Debugs the name and value of an object. Specially handled variants exist for all primitives,
57  * Object[], byte[] and char[].
58  * </li><br><br>
59  * <li>
60  * "dbe" = Debug Exception (see {@link #dbe SimpleLogger.dbe()})<br>
61  * Special handling of exceptions that will print a stack trace (can be turned off).
62  * </li><br><br>
63  * <li>
64  * Tracing (see {@link #entry SimpleLogger.entry()} and {@link #exit SimpleLogger.exit()})<br>
65  * Logs entry to and exit from a method. Can be turned on/off independent of debug level.<br>
66  * </li>
67  * </ul>
68  *
69  * as well as convenience methods, named after the various levels, as shortcuts to the above methods.
70  * </p>
71  *
72  * <p>
73  * Instance-based <code>SimpleLogger</code>s can be used to determine, from the log output,
74  * exactly which object a log statement is coming from. This is useful when many objects of the same
75  * class are all performing logging and it is crucial to analysis to know which object logged any
76  * given message.<br><br>
77  *
78  * Here is an example of how an instance-based logger would be used:<pre>
79  * public class
80  * Test
81  * {
82  * private final SimpleLogger log;
83  *
84  * private final String id;
85  *
86  * public
87  * Test(String id)
88  * {
89  * log = new SimpleLogger(Test.class, id);
90  * this.id = id;
91  * }
92  * }</pre>
93  * Note the following important features of this pattern and instance-based logs in general:
94  * <ul>
95  * <li>The <code>log</code> field is <i>not</i> static. There is one per instance.</li>
96  * <li><code>&lt;ClassName&gt;.class</code> is used rather than <code>getClass()</code>. Otherwise,
97  * if this class were subclassed, logging statements would appear with the subclass's name as the
98  * source.</li>
99  * <li>There are separate log formats for instance-based logs in the properties file.</li>
100  * </ul>
101  * </p>
102  *
103  * @version $Revision: 1.12 $
104  * @author $Author: grlea $
105  */

106 public class
107 SimpleLogger
108 {
109    /**
110     * The characters to use to represent the values of a byte.
111     */

112    private static final char[] BYTE_CHARS =
113       {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
114
115    /**
116     * The log that this logger logs to.
117     */

118    private final SimpleLog log;
119
120    /**
121     * The class that this SimpleLogger instance belongs to.
122     */

123    private final Class JavaDoc sourceClass;
124
125    /**
126     * The fully-qualified name of the class that this SimpleLogger instance belongs to.
127     */

128    private final String JavaDoc className;
129
130    /**
131     * The short name (ie. no package) of the class that this SimpleLogger instance belongs to.
132     */

133    private final String JavaDoc classNameShort;
134
135    /**
136     * The instance identifier for this <code>SimpleLogger</code>, or <code>null</code> if this
137     * instance is for a class, not an instance.
138     */

139    private Object JavaDoc instanceId;
140
141    /**
142     * A boolean indicating whether this SimpleLogger object contains an instanceId.
143     */

144    private final boolean isInstanceDebugger;
145
146    /**
147     * A boolean indicating whether trace/debug messages through this SimpleLogger object should
148     * have the fully-qualified (long) name of the class printed.
149     */

150    private final boolean useLongName;
151
152    /**
153     * <p>
154     * The name used to specify and look up the configuration of this <code>SimpleLogger</code>.
155     * </p>
156     *
157     * <p>
158     * The config name is the fully-qualified name of the source class of the logger, plus, if the
159     * logger is an instance logger, a period followed by the string representation
160     * ({@link Object#toString() toString()}) of the logger's instance ID. Additionally, any dollar
161     * signs appearing in the name are changed to periods.
162     * </p>
163     */

164    private String JavaDoc configName;
165
166    /**
167     * The current debug level for this <code>SimpleLogger</code>.
168     */

169    private DebugLevel debugLevel;
170
171    /**
172     * Whether this logger is currently reporting tracing or not.
173     */

174    private boolean tracing;
175
176    /**
177     * <p>Creates a new <code>SimpleLogger</code> for the specified Class using the default
178     * <code>SimpleLog</code>.</p>
179     *
180     * <p>This constructor is the equivalent of calling:<br>
181     * {@link #SimpleLogger(SimpleLog,Class) new SimpleLogger(SimpleLog.defaultInstance(), sourceClass)}
182     * </p>
183     *
184     * @param sourceClass The class that this SimpleLogger object is for, the name of which will be
185     * printed out as part of every message.
186     */

187    public
188    SimpleLogger(Class JavaDoc sourceClass)
189    {
190       this(SimpleLog.defaultInstance(), sourceClass);
191    }
192
193    /**
194     * <p>Creates a new <code>SimpleLogger</code> for the specified Class using the default
195     * <code>SimpleLog</code>.</p>
196     *
197     * <p>This constructor is the equivalent of calling:<br>
198     * {@link #SimpleLogger(SimpleLog,Class,Object)
199     * new SimpleLogger(SimpleLog.defaultInstance(), sourceClass, instanceId)}
200     * </p>
201     *
202     * @param sourceClass The class that this SimpleLogger object is for, the name of which will be
203     * printed out as part of every message.
204     *
205     * @param instanceId An object uniquely identifying the instance of <code><i>sourceClass</i></code>
206     * that this <code>SimpleLogger</code> is specifically for. Can be <code>null</code> if this
207     * <code>SimpleLogger</code> instance is for all instances of <code><i>sourceClass</i></code>
208     * rather than for a particular instance (this is the norm).
209     */

210    public
211    SimpleLogger(Class JavaDoc sourceClass, Object JavaDoc instanceId)
212    {
213       this(SimpleLog.defaultInstance(), sourceClass, instanceId);
214    }
215
216    /**
217     * <p>Creates a new <code>SimpleLogger</code> for the specified Class using the default
218     * <code>SimpleLog</code>.</p>
219     *
220     * <p>This constructor is the equivalent of calling:<br>
221     * {@link #SimpleLogger(SimpleLog,Class,boolean)
222     * new SimpleLogger(SimpleLog.defaultInstance(), sourceClass, useLongName)}
223     * </p>
224     *
225     * @param sourceClass The class that this SimpleLogger object is for, the name of which will be
226     * printed out as part of every message.
227     *
228     * @param useLongName A boolean indicating whether the fully-qualified name of the specified
229     * class should be printed in each message (when set to <code>true</code>), or just the name of
230     * the class within it's package (ie. the package will not be printed when set to
231     * <code>false</code>).
232     */

233    public
234    SimpleLogger(Class JavaDoc sourceClass, boolean useLongName)
235    {
236       this(SimpleLog.defaultInstance(), sourceClass, useLongName);
237    }
238
239    /**
240     * <p>Creates a new <code>SimpleLogger</code> for the specified Class using the default
241     * <code>SimpleLog</code>.</p>
242     *
243     * <p>This constructor is the equivalent of calling:<br>
244     * {@link #SimpleLogger(SimpleLog,Class,Object,boolean)
245     * new SimpleLogger(SimpleLog.defaultInstance(), sourceClass, instanceId, useLongName)}
246     * </p>
247     *
248     * @param sourceClass The class that this SimpleLogger object is for, the name of which will be
249     * printed out as part of every message.
250     *
251     * @param instanceId An object uniquely identifying the instance of <code><i>sourceClass</i></code>
252     * that this <code>SimpleLogger</code> is specifically for. Can be <code>null</code> if this
253     * <code>SimpleLogger</code> instance is for all instances of <code><i>sourceClass</i></code>
254     * rather than for a particular instance (this is the norm).
255     *
256     * @param useLongName A boolean indicating whether the fully-qualified name of the specified
257     * class should be printed in each message (when set to <code>true</code>), or just the name of
258     * the class within it's package (ie. the package will not be printed when set to
259     * <code>false</code>).
260     */

261    public
262    SimpleLogger(Class JavaDoc sourceClass, Object JavaDoc instanceId, boolean useLongName)
263    {
264       this(SimpleLog.defaultInstance(), sourceClass, instanceId, useLongName);
265    }
266
267    /**
268     * <p>Creates a new <code>SimpleLogger</code> for the specified Class that will log to, and be
269     * configured by, the provided <code>SimpleLog</code>.</p>
270     *
271     * <p>This constructor is the equivalent of calling:<br>
272     * {@link #SimpleLogger(SimpleLog,Class,boolean)
273     * new SimpleLogger(log, sourceClass, false)}
274     * </p>
275     *
276     * @param log the <code>SimpleLog</code> instance that this <code>SimpleLogger</code> should log
277     * to and be configured by.
278     *
279     * @param sourceClass The class that this SimpleLogger object is for, the name of which will be
280     * printed out as part of every message.
281     */

282    public
283    SimpleLogger(SimpleLog log, Class JavaDoc sourceClass)
284    {
285       this(log, sourceClass, false);
286    }
287
288    /**
289     * <p>Creates a new <code>SimpleLogger</code> for the specified Class that will log to, and be
290     * configured by, the provided <code>SimpleLog</code>.</p>
291     *
292     * <p>This constructor is the equivalent of calling:<br>
293     * {@link #SimpleLogger(SimpleLog,Class,Object,boolean)
294     * new SimpleLogger(SimpleLog.defaultInstance(), sourceClass, instanceId, false)}
295     * </p>
296     *
297     * @param log the <code>SimpleLog</code> instance that this <code>SimpleLogger</code> should log
298     * to and be configured by.
299     *
300     * @param sourceClass The class that this SimpleLogger object is for, the name of which will be
301     * printed out as part of every message.
302     *
303     * @param instanceId An object uniquely identifying the instance of <code><i>sourceClass</i></code>
304     * that this <code>SimpleLogger</code> is specifically for. Can be <code>null</code> if this
305     * <code>SimpleLogger</code> instance is for all instances of <code><i>sourceClass</i></code>
306     * rather than for a particular instance (this is the norm).
307     */

308    public
309    SimpleLogger(SimpleLog log, Class JavaDoc sourceClass, Object JavaDoc instanceId)
310    {
311       this(log, sourceClass, instanceId, false);
312    }
313
314    /**
315     * <p>Creates a new <code>SimpleLogger</code> for the specified Class that will log to, and be
316     * configured by, the provided <code>SimpleLog</code>.</p>
317     *
318     * <p>This constructor is the equivalent of calling:<br>
319     * {@link #SimpleLogger(SimpleLog,Class,Object,boolean)
320     * new SimpleLogger(SimpleLog.defaultInstance(), sourceClass, null, useLongName)}
321     * </p>
322     *
323     * @param log the <code>SimpleLog</code> instance that this <code>SimpleLogger</code> should log
324     * to and be configured by.
325     *
326     * @param sourceClass The class that this SimpleLogger object is for, the name of which will be
327     * printed out as part of every message.
328     *
329     * @param useLongName A boolean indicating whether the fully-qualified name of the specified
330     * class should be printed in each message (when set to <code>true</code>), or just the name of
331     * the class within it's package (ie. the package will not be printed when set to
332     * <code>false</code>).
333     */

334    public
335    SimpleLogger(SimpleLog log, Class JavaDoc sourceClass, boolean useLongName)
336    {
337       this(log, sourceClass, null, useLongName);
338    }
339
340    /**
341     * <p>Creates a new <code>SimpleLogger</code> for the specified Class that will log to, and be
342     * configured by, the provided <code>SimpleLog</code>.</p>
343     *
344     * @param log the <code>SimpleLog</code> instance that this <code>SimpleLogger</code> should log
345     * to and be configured by.
346     *
347     * @param sourceClass The class that this SimpleLogger object is for, the name of which will be
348     * printed out as part of every message.
349     *
350     * @param instanceId An object uniquely identifying the instance of <code><i>sourceClass</i></code>
351     * that this <code>SimpleLogger</code> is specifically for. Can be <code>null</code> if this
352     * <code>SimpleLogger</code> instance is for all instances of <code><i>sourceClass</i></code>
353     * rather than for a particular instance (this is the norm).
354     *
355     * @param useLongName A boolean indicating whether the fully-qualified name of the specified
356     * class should be printed in each message (when set to <code>true</code>), or just the name of
357     * the class within it's package (ie. the package will not be printed when set to
358     * <code>false</code>).
359     */

360    public
361    SimpleLogger(SimpleLog log, Class JavaDoc sourceClass, Object JavaDoc instanceId, boolean useLongName)
362    {
363       this.log = log;
364       this.sourceClass = sourceClass;
365       this.instanceId = instanceId;
366       this.isInstanceDebugger = instanceId != null;
367       this.useLongName = useLongName;
368       this.className = sourceClass.getName();
369       this.classNameShort = createClassNameShort(sourceClass);
370
371       generateConfigName();
372
373       log.register(this);
374    }
375
376    /**
377     * Creates and sets this <code>SimpleLogger</code>'s {@link #configName}.
378     */

379    private void
380    generateConfigName()
381    {
382       String JavaDoc loggerName = sourceClass.getName();
383
384       if (isInstanceDebugger)
385       {
386          loggerName = loggerName + '.' + instanceId;
387       }
388
389       if (loggerName.indexOf('$') != -1)
390       {
391          loggerName = loggerName.replace('$', '.');
392       }
393
394       this.configName = loggerName;
395    }
396
397    /**
398     * Determines and returns the short name (i.e. without the package) of the given class.
399     *
400     * @param sourceClass the class to retrieve the short name of
401     *
402     * @return the class's short name.
403     */

404    private String JavaDoc
405    createClassNameShort(Class JavaDoc sourceClass)
406    {
407       if (className.indexOf('.') == -1)
408       {
409          return className;
410       }
411
412       if (sourceClass.getPackage() != null && sourceClass.getPackage().getName() != null)
413       {
414          return className.substring(sourceClass.getPackage().getName().length() + 1);
415       }
416
417       // We have to do this trickery to make sure inner classes have their whole name (I think?)
418
String JavaDoc packageName = className;
419       boolean packageNameIsAClass = true;
420       int lastPeriod = packageName.indexOf('.');
421       while (packageNameIsAClass && lastPeriod != -1)
422       {
423          packageName = packageName.substring(0, lastPeriod);
424          try
425          {
426             Class.forName(packageName);
427             packageNameIsAClass = true;
428          }
429          catch (Throwable JavaDoc e)
430          {
431             packageNameIsAClass = false;
432          }
433          lastPeriod = packageName.lastIndexOf('.');
434       }
435
436       if (packageName.length() == 0)
437       {
438          return className;
439       }
440       else
441       {
442          return className.substring(packageName.length() + 1);
443       }
444    }
445
446    /**
447     * Returns <code>true</code> if this <code>SimpleLogger</code> is a logger for one instance of
448     * the source class rather than for the class as a whole.
449     */

450    public boolean
451    isInstanceDebugger()
452    {
453       return isInstanceDebugger;
454    }
455
456    /**
457     * Returns the {@link #instanceId} of this <code>SimpleLogger</code>, or <code>null</code> if it
458     * does not have one (i.e. it is a class logger, not an instance logger).
459     */

460    public Object JavaDoc
461    getInstanceID()
462    {
463       return instanceId;
464    }
465
466    /**
467     * Sets the {@link #instanceId} of this <code>SimpleLogger</code> instance.
468     *
469     * @throws IllegalArgumentException if <code>instanceId</code> is <code>null</code>
470     *
471     * @throws IllegalStateException if this <code>SimpleLogger</code> is for a class, not an
472     * instance. (See the javadoc for the class for more information.)
473     */

474    public void
475    setInstanceID(Object JavaDoc instanceId)
476    {
477       if (!isInstanceDebugger)
478       {
479          throw new IllegalStateException JavaDoc("This is not an instance debugger.");
480       }
481       if (instanceId == null)
482       {
483          throw new IllegalArgumentException JavaDoc("instanceId cannot be null.");
484       }
485       this.instanceId = instanceId;
486
487       generateConfigName();
488    }
489
490    /**
491     * <p>
492     * Returns this <code>SimpleLogger</code>'s config name, the name used to specify and look up
493     * its configuration.
494     * </p>
495     *
496     * <p>
497     * Currently, the config name is the fully-qualified name of the source class of the logger,
498     * plus, if the logger is an instance logger, a period ('.') followed by the string
499     * representation ({@link Object#toString() toString()}) of the logger's instance ID.
500     * Additionally, any dollar signs appearing in the name are changed to periods.
501     * </p>
502     */

503    public String JavaDoc
504    getConfigName()
505    {
506       return configName;
507    }
508
509    /**
510     * Returns the current debug level of this <code>SimpleLogger</code>.
511     */

512    public DebugLevel
513    getDebugLevel()
514    {
515       return debugLevel;
516    }
517
518    /**
519     * A convenience method for testing whether a message logged at the specified level would be
520     * logged by this <code>SimpleLogger</code>.
521     *
522     * @param level the level of the hypothetical message being logged
523     *
524     * @return <code>true</code> if a message at the specified level would be logged given this
525     * <code>SimpleLogger</code>'s current log level, <code>false</code> if it would not.
526     *
527     * @see #getDebugLevel
528     * @see DebugLevel#shouldLog
529     */

530    public boolean
531    wouldLog(DebugLevel level)
532    {
533       return log.isOutputting() && getDebugLevel().shouldLog(level);
534    }
535
536    /**
537     * Sets the current debug level of this <code>SimpleLogger</code>.
538     *
539     * @param debugLevel the new debug level
540     *
541     * @throws IllegalArgumentException if <code>debugLevel</code> is <code>null</code>.
542     */

543    public void
544    setDebugLevel(DebugLevel debugLevel)
545    {
546       if (debugLevel == null)
547       {
548          throw new IllegalArgumentException JavaDoc("debugLevel cannot be null.");
549       }
550       this.debugLevel = debugLevel;
551    }
552
553    /**
554     * Returns whether this <code>SimpleLogger</code> is currently reporting tracing or not.
555     *
556     * @return <code>true</code> if this logger is reporting tracing, false otherwise.
557     */

558    public boolean
559    isTracing()
560    {
561       return tracing;
562    }
563
564    /**
565     * Sets this <code>SimpleLogger</code>'s tracing flag.
566     *
567     * @param tracing <code>true</code> if this logger should report tracing, false if it should not.
568     */

569    public void
570    setTracing(boolean tracing)
571    {
572       this.tracing = tracing;
573    }
574
575    /**
576     * Returns the source class of this <code>SimpleLogger</code>.
577     */

578    public Class JavaDoc
579    getSourceClass()
580    {
581       return sourceClass;
582    }
583
584    /**
585     * Creates an array of data containing the standard arguments for a log message, plus empty
586     * array slots for the specified number of arguments.
587     *
588     * @param level the level at which this data is going to be logged.
589     *
590     * @param extraArguments the number of empty slots to create at the end of the array.
591     *
592     * @return the newly created array of objects.
593     */

594    private Object JavaDoc[]
595    createData(DebugLevel level, int extraArguments)
596    {
597       Object JavaDoc[] result = new Object JavaDoc[5 + extraArguments];
598       result[0] = new Date JavaDoc();
599       result[1] = Thread.currentThread().getName();
600       result[2] = useLongName ? className : classNameShort;
601       result[3] = instanceId;
602       result[4] = level;
603       return result;
604    }
605
606    /**
607     * Logs a debug message at the {@link DebugLevel#L1_FATAL Fatal} level.
608     *
609     * @param message the message to log.
610     *
611     * @see #db
612     */

613    public void
614    fatal(String JavaDoc message)
615    {
616       db(DebugLevel.L1_FATAL, message);
617    }
618
619    /**
620     * Logs a debug message at the {@link DebugLevel#L2_ERROR Error} level.
621     *
622     * @param message the message to log.
623     *
624     * @see #db
625     */

626    public void
627    error(String JavaDoc message)
628    {
629       db(DebugLevel.L2_ERROR, message);
630    }
631
632    /**
633     * Logs a debug message at the {@link DebugLevel#L3_WARN Warn} level.
634     *
635     * @param message the message to log.
636     *
637     * @see #db
638     */

639    public void
640    warn(String JavaDoc message)
641    {
642       db(DebugLevel.L3_WARN, message);
643    }
644
645    /**
646     * Logs a debug message at the {@link DebugLevel#L4_INFO Info} level.
647     *
648     * @param message the message to log.
649     *
650     * @see #db
651     */

652    public void
653    info(String JavaDoc message)
654    {
655       db(DebugLevel.L4_INFO, message);
656    }
657
658    /**
659     * Logs a debug message at the {@link DebugLevel#L5_DEBUG Debug} level.
660     *
661     * @param message the message to log.
662     *
663     * @see #db
664     */

665    public void
666    debug(String JavaDoc message)
667    {
668       db(DebugLevel.L5_DEBUG, message);
669    }
670
671    /**
672     * Logs a debug message at the {@link DebugLevel#L6_VERBOSE Verbose} level.
673     *
674     * @param message the message to log.
675     *
676     * @see #db
677     */

678    public void
679    verbose(String JavaDoc message)
680    {
681       db(DebugLevel.L6_VERBOSE, message);
682    }
683
684    /**
685     * Logs a debug message at the {@link DebugLevel#L7_LUDICROUS Ludicrous} level.
686     *
687     * @param message the message to log.
688     *
689     * @see #db
690     */

691    public void
692    ludicrous(String JavaDoc message)
693    {
694       db(DebugLevel.L7_LUDICROUS, message);
695    }
696
697    /**
698     * <p>Logs a simple debug message.</p>
699     *
700     * <p>The message will be printed if the given debug level is less than or equal to the current
701     * debug level of this <code>SimpleLogger</code>.</p>
702     *
703     * @param message The debug message to print.
704     *
705     * @see #fatal
706     * @see #error
707     * @see #warn
708     * @see #info
709     * @see #debug
710     * @see #verbose
711     */

712    public void
713    db(DebugLevel level, String JavaDoc message)
714    {
715       if (!log.isOutputting() || !debugLevel.shouldLog(level))
716       {
717          return;
718       }
719
720       Object JavaDoc[] data = createData(level, 1);
721       data[data.length - 1] = message;
722       MessageFormat JavaDoc format =
723          isInstanceDebugger ? log.getDebugInstanceFormat() : log.getDebugFormat();
724       log.println(format.format(data));
725    }
726
727    /**
728     * <p>Logs a message containing an object's name and value.</p>
729     *
730     * <p>The object name and value will be printed only if the given debug level is less than or
731     * equal to the current debug level of this <code>SimpleLogger</code>.</p>
732     *
733     * <p>Note that, if the given object is an instance of <code>Object[]</code>, <code>byte[]</code>
734     * or <code>char[]</code>, this method will route the call to the corresponding variation of
735     * <code>dbo()</code> (each of which performs special formatting for the particualr type),
736     * eliminating the need to perform pre-logging type checks and casts.</p>
737     *
738     * <p>Note that passing a {@link Throwable} to this method does not behave in the same way as
739     * {@link #dbe}. I.e. passing an exception in as the object value will not result in a stack
740     * trace being printed.</p>
741     *
742     * @param objectName The name of the object whose value is being given.
743     *
744     * @param value The value of the object.
745     */

746    public void
747    dbo(DebugLevel level, String JavaDoc objectName, Object JavaDoc value)
748    {
749       if (wouldLog(level))
750       {
751          if (value instanceof Object JavaDoc[])
752          {
753             dbo(level, objectName, (Object JavaDoc[]) value);
754          }
755          else if (value instanceof byte[])
756          {
757             dbo(level, objectName, (byte[]) value);
758          }
759          else if (value instanceof char[])
760          {
761             dbo(level, objectName, (char[]) value);
762          }
763          else
764          {
765             dboNoCheck(level, objectName, value);
766          }
767       }
768    }
769
770    /**
771     * The same as {@link #dbo(DebugLevel,String,Object)} but without the debug level check.
772     * This method is used by all the primitive- and array-typed variants of <code>dbo()</code>,
773     * which do their own checks before calling this method.
774     */

775    private void
776    dboNoCheck(DebugLevel level, String JavaDoc objectName, Object JavaDoc val)
777    {
778       Object JavaDoc[] data = createData(level, 2);
779       data[data.length - 2] = objectName;
780       data[data.length - 1] = val;
781       MessageFormat JavaDoc format = isInstanceDebugger ? log.getDebugObjectInstanceFormat() :
782                                                            log.getDebugObjectFormat();
783       log.println(format.format(data));
784    }
785
786    /**
787     * <p>Logs a message containing an object array's name and value.</p>
788     *
789     * <p>The array name and value will be printed only if the given debug level is less than or
790     * equal to the current debug level of this <code>SimpleLogger</code>.</p>
791     *
792     * @param objectName The name of the array whose value is being given.
793     *
794     * @param val The array.
795     */

796    public void
797    dbo(DebugLevel level, String JavaDoc objectName, Object JavaDoc[] val)
798    {
799       if (!log.isOutputting() || !debugLevel.shouldLog(level))
800       {
801          return;
802       }
803
804       StringBuffer JavaDoc stringValue = new StringBuffer JavaDoc("[");
805       for (int i = 0; i < val.length; i++)
806       {
807          if (i == 0)
808          {
809             stringValue.append(val[i]);
810          }
811          else
812          {
813             stringValue.append(", ").append(val[i]);
814          }
815       }
816       stringValue.append("]");
817
818       dboNoCheck(level, objectName, stringValue);
819    }
820
821    /**
822     * <p>Logs a message containing a <code>short</code>'s name and value.</p>
823     *
824     * @see #dbo(DebugLevel,String,Object)
825     */

826    public void
827    dbo(DebugLevel level, String JavaDoc objectName, short val)
828    {
829       if (!log.isOutputting() || !debugLevel.shouldLog(level))
830       {
831          return;
832       }
833
834       dboNoCheck(level, objectName, String.valueOf(val));
835    }
836
837    /**
838     * <p>Logs a message containing an <code>int</code>'s name and value.</p>
839     *
840     * @see #dbo(DebugLevel,String,Object)
841     */

842    public void
843    dbo(DebugLevel level, String JavaDoc objectName, int val)
844    {
845       if (!log.isOutputting() || !debugLevel.shouldLog(level))
846       {
847          return;
848       }
849
850       dboNoCheck(level, objectName, String.valueOf(val));
851    }
852
853    /**
854     * <p>Logs a message containing a <code>long</code>'s name and value.</p>
855     *
856     * @see #dbo(DebugLevel,String,Object)
857     */

858    public void
859    dbo(DebugLevel level, String JavaDoc objectName, long val)
860    {
861       if (!log.isOutputting() || !debugLevel.shouldLog(level))
862       {
863          return;
864       }
865
866       dboNoCheck(level, objectName, String.valueOf(val));
867    }
868
869    /**
870     * <p>Logs a message containing a <code>boolean</code>'s name and value.</p>
871     *
872     * @see #dbo(DebugLevel,String,Object)
873     */

874    public void
875    dbo(DebugLevel level, String JavaDoc objectName, boolean val)
876    {
877       if (!log.isOutputting() || !debugLevel.shouldLog(level))
878       {
879          return;
880       }
881
882       dboNoCheck(level, objectName, String.valueOf(val));
883    }
884
885    /**
886     * <p>Logs a message containing a <code>float</code>'s name and value.</p>
887     *
888     * @see #dbo(DebugLevel,String,Object)
889     */

890    public void
891    dbo(DebugLevel level, String JavaDoc objectName, float val)
892    {
893       if (!log.isOutputting() || !debugLevel.shouldLog(level))
894       {
895          return;
896       }
897
898       dboNoCheck(level, objectName, String.valueOf(val));
899    }
900
901    /**
902     * <p>Logs a message containing a <code>double</code>'s name and value.</p>
903     *
904     * @see #dbo(DebugLevel,String,Object)
905     */

906    public void
907    dbo(DebugLevel level, String JavaDoc objectName, double val)
908    {
909       if (!log.isOutputting() || !debugLevel.shouldLog(level))
910       {
911          return;
912       }
913
914       dboNoCheck(level, objectName, String.valueOf(val));
915    }
916
917    /**
918     * <p>Logs a message containing a <code>byte</code>'s name and value.</p>
919     *
920     * @see #dbo(DebugLevel,String,Object)
921     */

922    public void
923    dbo(DebugLevel level, String JavaDoc objectName, byte val)
924    {
925       if (!log.isOutputting() || !debugLevel.shouldLog(level))
926       {
927          return;
928       }
929
930       dboNoCheck(level, objectName, toString(val));
931    }
932
933    /**
934     * <p>Logs a message containing a <code>byte</code> array's name and value.</p>
935     *
936     * @see #dbo(DebugLevel,String,Object)
937     */

938    public void
939    dbo(DebugLevel level, String JavaDoc objectName, byte[] val)
940    {
941       if (!log.isOutputting() || !debugLevel.shouldLog(level))
942       {
943          return;
944       }
945
946       dboNoCheck(level, objectName, toString(val));
947    }
948
949    /**
950     * <p>Logs a message containing a <code>char</code>'s name and value.</p>
951     *
952     * @see #dbo(DebugLevel,String,Object)
953     */

954    public void
955    dbo(DebugLevel level, String JavaDoc objectName, char val)
956    {
957       if (!log.isOutputting() || !debugLevel.shouldLog(level))
958       {
959          return;
960       }
961
962       dboNoCheck(level, objectName, String.valueOf(val));
963    }
964
965    /**
966     * <p>Logs a message containing a <code>char</code> array's name and value.</p>
967     *
968     * @see #dbo(DebugLevel,String,Object)
969     */

970    public void
971    dbo(DebugLevel level, String JavaDoc objectName, char[] val)
972    {
973       if (!log.isOutputting() || !debugLevel.shouldLog(level))
974       {
975          return;
976       }
977
978       dboNoCheck(level, objectName, String.valueOf(val));
979    }
980
981    /**
982     * Convenience method for logging an object's name and value at the {@link DebugLevel#L4_INFO
983     * Info} level.
984     *
985     * @see #dbo(DebugLevel,String,Object)
986     */

987    public void
988    infoObject(String JavaDoc objectName, Object JavaDoc val)
989    {
990       dbo(DebugLevel.L4_INFO, objectName, val);
991    }
992
993    /**
994     * Convenience method for logging a <code>boolean</code>'s name and value at the {@link
995     * DebugLevel#L4_INFO Info} level.
996     *
997     * @see #dbo(DebugLevel,String,boolean)
998     */

999    public void
1000   infoObject(String JavaDoc objectName, boolean val)
1001   {
1002      dbo(DebugLevel.L4_INFO, objectName, val);
1003   }
1004
1005   /**
1006    * Convenience method for logging an <code>int</code>'s name and value at the
1007    * {@link DebugLevel#L4_INFO Info} level.
1008    *
1009    * @see #dbo(DebugLevel,String,int)
1010    */

1011   public void
1012   infoObject(String JavaDoc objectName, int val)
1013   {
1014      dbo(DebugLevel.L4_INFO, objectName, val);
1015   }
1016
1017   /**
1018    * Convenience method for logging an object's name and value at the
1019    * {@link DebugLevel#L5_DEBUG Debug} level.
1020    *
1021    * @see #dbo(DebugLevel,String,Object)
1022    */

1023   public void
1024   debugObject(String JavaDoc objectName, Object JavaDoc val)
1025   {
1026      dbo(DebugLevel.L5_DEBUG, objectName, val);
1027   }
1028
1029   /**
1030    * Convenience method for logging a <code>boolean</code>'s name and value at the
1031    * {@link DebugLevel#L5_DEBUG Debug} level.
1032    *
1033    * @see #dbo(DebugLevel,String,boolean)
1034    */

1035   public void
1036   debugObject(String JavaDoc objectName, boolean val)
1037   {
1038      dbo(DebugLevel.L5_DEBUG, objectName, val);
1039   }
1040
1041   /**
1042    * Convenience method for logging an <code>int</code>'s name and value at the
1043    * {@link DebugLevel#L5_DEBUG Debug} level.
1044    *
1045    * @see #dbo(DebugLevel,String,int)
1046    */

1047   public void
1048   debugObject(String JavaDoc objectName, int val)
1049   {
1050      dbo(DebugLevel.L5_DEBUG, objectName, val);
1051   }
1052
1053   /**
1054    * Convenience method for logging an object's name and value at the
1055    * {@link DebugLevel#L6_VERBOSE Verbose} level.
1056    *
1057    * @see #dbo(DebugLevel,String,Object)
1058    */

1059   public void
1060   verboseObject(String JavaDoc objectName, Object JavaDoc val)
1061   {
1062      dbo(DebugLevel.L6_VERBOSE, objectName, val);
1063   }
1064
1065   /**
1066    * Convenience method for logging a <code>boolean</code>'s name and value at the
1067    * {@link DebugLevel#L6_VERBOSE Verbose} level.
1068    *
1069    * @see #dbo(DebugLevel,String,boolean)
1070    */

1071   public void
1072   verboseObject(String JavaDoc objectName, boolean val)
1073   {
1074      dbo(DebugLevel.L6_VERBOSE, objectName, val);
1075   }
1076
1077   /**
1078    * Convenience method for logging an <code>int</code>'s name and value at the
1079    * {@link DebugLevel#L6_VERBOSE Verbose} level.
1080    *
1081    * @see #dbo(DebugLevel,String,int)
1082    */

1083   public void
1084   verboseObject(String JavaDoc objectName, int val)
1085   {
1086      dbo(DebugLevel.L6_VERBOSE, objectName, val);
1087   }
1088
1089   /**
1090    * Convenience method for logging an object's name and value at the
1091    * {@link DebugLevel#L7_LUDICROUS Ludicrous} level.
1092    *
1093    * @see #dbo(DebugLevel,String,Object)
1094    */

1095   public void
1096   ludicrousObject(String JavaDoc objectName, Object JavaDoc val)
1097   {
1098      dbo(DebugLevel.L7_LUDICROUS, objectName, val);
1099   }
1100
1101   /**
1102    * Convenience method for logging a <code>boolean</code>'s name and value at the
1103    * {@link DebugLevel#L7_LUDICROUS Ludicrous} level.
1104    *
1105    * @see #dbo(DebugLevel,String,boolean)
1106    */

1107   public void
1108   ludicrousObject(String JavaDoc objectName, boolean val)
1109   {
1110      dbo(DebugLevel.L7_LUDICROUS, objectName, val);
1111   }
1112
1113   /**
1114    * Convenience method for logging an <code>int</code>'s name and value at the
1115    * {@link DebugLevel#L7_LUDICROUS Ludicrous} level.
1116    *
1117    * @see #dbo(DebugLevel,String,int)
1118    */

1119   public void
1120   ludicrousObject(String JavaDoc objectName, int val)
1121   {
1122      dbo(DebugLevel.L7_LUDICROUS, objectName, val);
1123   }
1124
1125   /**
1126    * <p>Logs a message containing an exception (or throwable).</p>
1127    *
1128    * <p>The exception will be printed only if the given debug level is less than or
1129    * equal to the current debug level of this <code>SimpleLogger</code>. This method will result in
1130    * the stack trace of the exception being printed if this option is turned on in the properties
1131    * (which it is by default).</p>
1132    *
1133    * @param t the throwable to log.
1134    */

1135   public void
1136   dbe(DebugLevel level, Throwable JavaDoc t)
1137   {
1138      if (!log.isOutputting() || !debugLevel.shouldLog(level))
1139      {
1140         return;
1141      }
1142
1143      Object JavaDoc[] data = createData(level, 1);
1144      data[data.length - 1] = t;
1145      MessageFormat JavaDoc format = isInstanceDebugger ? log.getDebugExceptionInstanceFormat() :
1146                                                           log.getDebugExceptionFormat();
1147      log.println(format.format(data));
1148   }
1149
1150   /**
1151    * Convenience method for logging an exception (or throwable) at the
1152    * {@link DebugLevel#L1_FATAL Fatal} level.
1153    *
1154    * @see #dbe(DebugLevel,Throwable)
1155    */

1156   public void
1157   fatalException(Throwable JavaDoc t)
1158   {
1159      dbe(DebugLevel.L1_FATAL, t);
1160   }
1161
1162   /**
1163    * Convenience method for logging an exception (or throwable) at the
1164    * {@link DebugLevel#L2_ERROR Error} level.
1165    *
1166    * @see #dbe(DebugLevel,Throwable)
1167    */

1168   public void
1169   errorException(Throwable JavaDoc t)
1170   {
1171      dbe(DebugLevel.L2_ERROR, t);
1172   }
1173
1174   /**
1175    * Convenience method for logging an exception (or throwable) at the
1176    * {@link DebugLevel#L3_WARN Warn} level.
1177    *
1178    * @see #dbe(DebugLevel,Throwable)
1179    */

1180   public void
1181   warnException(Throwable JavaDoc t)
1182   {
1183      dbe(DebugLevel.L3_WARN, t);
1184   }
1185
1186   /**
1187    * <p>Logs an entry message.</p>
1188    *
1189    * <p>The message will be printed only if the this <code>SimpleLogger</code>'s tracing flag is
1190    * set to <code>true</code>.</p>
1191
1192    * @param methodName The method name to include in the entry message.
1193    */

1194   public void
1195   entry(String JavaDoc methodName)
1196   {
1197      if (!log.isOutputting() || !tracing)
1198      {
1199         return;
1200      }
1201
1202      Object JavaDoc[] data = createData(DebugLevel.FAKE_TRACE, 1);
1203      data[data.length - 1] = methodName;
1204      MessageFormat JavaDoc format = isInstanceDebugger ? log.getEntryInstanceFormat() :
1205                                                           log.getEntryFormat();
1206      log.println(format.format(data));
1207   }
1208
1209   /**
1210    * <p>Logs an exit message.</p>
1211    *
1212    * <p>The message will be printed only if the this <code>SimpleLogger</code>'s tracing flag is
1213    * set to <code>true</code>.</p>
1214    */

1215   public void
1216   exit(String JavaDoc methodName)
1217   {
1218      if (!log.isOutputting() || !tracing)
1219      {
1220         return;
1221      }
1222
1223      Object JavaDoc[] data = createData(DebugLevel.FAKE_TRACE, 1);
1224      data[data.length - 1] = methodName;
1225      MessageFormat JavaDoc format = isInstanceDebugger ? log.getExitInstanceFormat() :
1226                                                           log.getExitFormat();
1227      log.println(format.format(data));
1228   }
1229
1230   /**
1231    * Converts a <code>byte</code> to a hex string.
1232    *
1233    * @param b the byte
1234    *
1235    * @return the string
1236    */

1237   private static String JavaDoc
1238   toString(byte b)
1239   {
1240      return "0x" + byteString(b);
1241   }
1242
1243   /**
1244    * Converts an array of bytes to a string of two-character hex values.
1245    *
1246    * @param bytes the byte array
1247    *
1248    * @return the string
1249    */

1250   private static String JavaDoc
1251   toString(byte[] bytes)
1252   {
1253      if (bytes == null)
1254      {
1255         return "null";
1256      }
1257
1258      StringBuffer JavaDoc buf = new StringBuffer JavaDoc(bytes.length * 4);
1259      buf.append("0x[");
1260      boolean first = true;
1261      for (int i = 0; i < bytes.length; i++)
1262      {
1263         if (first && !(first = false))
1264         {
1265            buf.append(byteString(bytes[i]));
1266         }
1267         else
1268         {
1269            buf.append(", ").append(byteString(bytes[i]));
1270         }
1271      }
1272      buf.append(']');
1273      return buf.toString();
1274   }
1275
1276   /**
1277    * Returns the two hex characters that represent the given byte.
1278    *
1279    * @param b the byte
1280    *
1281    * @return the two hex characters that represent the byte.
1282    */

1283   private static String JavaDoc
1284   byteString(byte b)
1285   {
1286      return new String JavaDoc(new char[] {BYTE_CHARS[(b >> 4) & 0x0F], BYTE_CHARS[b & 0x0F]});
1287   }
1288}
Popular Tags