Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

org.dinopolis.util
Class Debug  view Debug download Debug.java

java.lang.Object
  extended byorg.dinopolis.util.Debug

public class Debug
extends java.lang.Object

Debug helps the programmer to print various debug messages. This class is a frontend to the org.dinopolis.util.debug.Debug class. Its only purpose is to ease the use of the mentioned class. All methods in this class are static so the usage simply is Debug.methodName(arguments). No instance must be handed from one class to the other.

Debug Levels

The Debug class provides the possibility to print debug messages depending on the debug level. There is a status for a given debug level that indicates if messages for this level should be put out or not. This status can be requested from the debug class. A shortcut in the method that prints the debug message will be provided.

Change Settings

The settings of the debug class (e.g. enable/disable debug messages for a debug-level, ...) can be set using different ways:
  • Hardcoded in the application that should be debugged: The debug methods that change the settings can be invoked within the code of the application.
  • In the configuration file of the debug class: All settings can be written into a configuration file. This file is read by the debug class when the application uses a debug method for the first time. If wanted, the debug class rereads this file periodically, so any changes made in this file are applied directly.
  • The debug class provides a way to set debug settings first and then directly start a given application, so the settings stay valid for the application.

Redirect Output

The debug class is able to write the debug messages to any stream. By default this stream is set to System.err, but can easily be set to a file or to a network stream.

Format of Debug Message

The format of the debug message is freely configurable. The debug message format definition is parsed for keywords (Keywords are delimitered by a special character.). A factory creates objects by using the keyword as a part of the classname. On request, these objects return a String-value which replaces the keyword in the debug message format definition. E.g. for the keyword %date%, an object of the class org.dinopolis.util.debug.DebugMessageDATE is created.

For performance reasons these objects are crated only when the format definiation changes and are then reused for every debug message. This implies that these objects are stateless.

Timer

A simple timer functionality is provided. The timer objects are named and the name is then used to retrieve the time or to stop the timer. The timer object is never handed to the user; it is only possible to obtain a string representation that holds the current time and the time spent since the timer was started.

The timer does not subtract the time spent inside the debug class. So timings may vary depending on the debug levels enabled/disabled.

StackTrace

The debug class provides methods to obtain a string representation of the stack trace, so any calling hierarchies can be made visible easily. Alternatively only one line of the stack trace can be requested. This line indicates the class and linenumber (if available) of the caller.

As Java offers only stacktraces of Exceptions/Throwables, a new Throwable is created and its stacktrace is used. Any traces from the Debug class itself are removed.

Print Various Objects Types

A static method is provided that returns the string representation of arrays of objects as well as of objects. In the case of objects, the toString() method is called. In the case of arrays, for each element in the array the static method is recursivly called. Using this way, string representations of arrays that hold arrays can be returned as well.

Remove Debug Code

The Debug class holds a static final boolean variable. If this variable is used in a conditional statement, the Java compiler is able to decide that the code is written into the class file or not during compilation. For better understanding, an example is given:
 if (Debug.DEBUG)
 {
   // this code will only be in the class file, 
   // if Debug.DEBUG is set to true!
 }
 

Static and non-static class

There are two different ways to use the Debug class. This class with static methods is for comfortable use by applications. This is the class normal users will use. Some situations may ask for independent Debug objects, so an instance of org.dinopolis.util.debug.Debug may be used for these purposes. The 'static' Debug class uses one instance of the 'instance' Debug class.

Message Format Objects

Message Format Objects are created by org.dinopolis.util.debug.DebugMessageFormatFactory and are used for formatting the debug message depending on the debug message format definition. All Format Objects must implement the interface org.dinopolis.util.debug.DebugMessageFormatObject

Usage

The static methods of Debug makes them easy to use.

The easiest way to to print a messages:

 Debug.println("this is a debug message");
 
Generally this does not really make sense, as no differentiation can be made. The only exception is when debug messages should not be printed on the console but to a file or a network connection. All debug messages can be printed to any java.io.Writer (see method setWriter(java.io.Writer) 55 ). For simplicity, a special method is provided that faciliates the output to files:
 Debug.setWriterToFile("/log/debug.log")
 Debug.println("this is a debug message sent to file '/log/debug.log'");
 
Different debug levels let the user decide what type of debug messages should be printed, and which shouldn't:
 Debug.println("test-level",
                "this is a debug message for debug level 'test-level'");
 
In this example the debug message is only printed when the given debug level was enabled before:
 Debug.addLevelsToPrint("test-level");
 
Of course it is possible to enable more than one level at a time. Debug levels can be separated by space, comma, newlines or tabs.
 Debug.addLevelsToPrint("test-level, another-level a_third_level");
 
One way to use these levels in the println method was shown above. Another is to use it in a conditional statement. This is very handy in the case when more than one debug message should be printed.
 if (Debug.isEnabled("test-level"))
 {
   Debug.println("this a debug message, printed only when "
                 +"the debug level 'test-level' is enabled.");
       // do something else
   Debug.println("this another debug message, printed only when "
                 +"the debug level 'test-level' is enabled.");
 }
 
This method is slightly more to type, but peforms better, if the debug message has to be created first:
 Object object = new Integer(2);
 Debug.println("test-level","variable object="+object.toString());
 
In the statement above the debug message has to be created from the given string and from the result of object.toString(). If the debug-level 'test-level' is not enabled, the creation was done for nothing and performance is wasted.

Another way to increase performance is the following: Debug has a final static variable named DEBUG 55 . If set to false, any conditional statements using this are evaluated to false already at compile time! When creating a version of an application that should not have any debug information, simply set DEBUG 55 to false (in the classfile) and recompile Debug and the whole application. For best usage always use the Debug methods like this:

 if (Debug.DEBUG)
 {
   Debug.println("test-level",
                  "this part of source code will not make it into "
                  +"the class file when Debug.DEBUG is set to false!");
 }
 
There are other helpful methods in the Debug class. How often is it necessary to print the content of an array for debugging reasons. The java method toString() does not work in this case. objectToString(Object) 55 handles nearly all objects and returns a human readable output:
 Object[] obj_array = new Object[]{"one", new Integer(2), "three"};
 if (Debug.DEBUG && Debug.isEnabled("test-level"))
 {
   Debug.println("content of string_array = "
           +Debug.objectToString(obj_array));
 }
 
Sometimes it is interesting to measure how long a method takes to execute. Debug offers a simple way to measure time:
 Debug.startTimer("timer_name");
     // ----------------
     // execute method 1
     // ----------------
 Debug.println("test-level",Debug.getTimer("timer_name"));
     // ----------------
     // execute method 2
     // ----------------
 Debug.println("test-level",Debug.stopTimer("timer_name"));
 
getTimer(String) 55 returns a String but does not stop (and remove) the timer, whereas stopTimer(String) 55 returns the String and removes the timer from memory.

Sometimes it is usefull to know exactly where a debug output is created. The StackTrace-methods of Debug help here: getStackTrace() 55 returns a complete StackTrace, so the calling hierarchy is visible, whereas getStackTraceLine() 55 returns only the line, from which the command was invoked:

 if (Debug.isEnabled("test_level"))
 {
   Debug.println("complete stacktrace: "
                  +Debug.getStackTrace());
   Debug.println("only a line of the stacktrace: "
                  +Debug.getStackTraceLine());
 }
 
The format of the debug message is widely configurable. A message format string consists of strings and keywords. The command below sets the format of all debug messages to the given format. All keywords (words between '%') are replaced by their value, the rest is left unchanged:
 Debug.setMessageFormat("DEBUG: %date% \"%message%\" (Thread: %thread%)");
 Debug.println("this message is in a different format now.");
 
Available keywords are:
  • %date%: actual date
  • %milliseconds%: the actual milliseconds
  • %diffmilliseconds%: the time difference since the last debug message was printed (in milliseconds)
  • %level%: the levelname of the debugmessage
  • %stacktrace%: a stacktrace to ever msg
  • %stacktraceline%: last line in stacktrace (caller)
  • %thread%: the string rep of the thread of the caller
  • %threadname%: the name of the thread of the caller
  • %threadgroup%: the name of the threadgroup of the caller
  • %message%: the debug message itself
You can also insert '\n' (and others) e.g. to force a new line or '\t' to divide the output in columns. The key words are replaced by their value, the rest is left unchanged.

debug.properties file

All settings of the Debug-class can be set through method calls from the application or by editing the config-file named 'debug.properties' in the directory returned by a call to System.getProperties().get("user.home"). Using java in a Unix environment this is normally the home directory of the user (under Windows, I don't know, sorry!).

The second way to set debug options has the advantage that the settings can be changed without restarting the application. This makes it possible to change e.g. the debug-level or the debug-message-format when necessary. An example of such a properties file is given here (everything behind a '#' is taken as a comment):

 # ---------- debug.properties start --------------
 # enable debug messages
 Debug.enabled=true
 
 # debug levels to print
 Debug.printLevels=debug_test, debug_start_application
 
 # set to true, if you want to see all level output
 #Debug.printAllLevels=true
 
 # set this, if you want the output logged in a file:
 #Debug.fileName=/home/cdaller/tmp/debug.log
 
 # reload this file every xxx milliseconds 
 # (if xxx == 0, no thread is started.)
 Debug.refreshPropertyTime=5000
 
 # Set the format of the debug messages.
 Debug.messageFormat=DEBUG: "%message%" (L:%level%)
 # ---------- debug.properties end --------------
 
Especially the 'Debug.refreshPropertyTime' is worth taking a closer look. It determines that Debug rereads the property file every 5 seconds, so any changes in the file become applied at least 5 seconds after saving it. Therefore the user may change the debug levels to be printed without the need to restart the application!

Another comfortable way to set debug options without hardcoding the calls to debug methods into the application is the following: The main(String[]) 55 method can be used to set Debug options and then start a given application.

To let an applicaton be started by Debug, main(String[]) 55 accepts some debug-specific options and the classname (and its arguments) of the application.

Debug specific options are:

  • --debuglevels : adds one or more debug levels (if there are any levels set in the property file, they are added).
  • --debugmessage : sets the format of the debug messages. Please see method setMessageFormat(String) 55 for details.
  • --debugfilename : sets the name of the file the debug messages are written to.
  • --debugrefresh : sets the refresh time for the thread that rereads the properties-file.
  • --debugpropertiesfile : sets the name of the properties-file.
An example that sets two debug levels and the messageformat and then starts the class test.TestApplication:
 java org.dinopolis.util.Debug --debuglevels "level1, level2" \
   --debugmessage "DEBUG: %message% (Thread: %thread%)" \ 
   "test.Application argument1 argument2 --option value"
 
Note: The class that should be started and its arguments are put inside double quotes, otherwise its arguments are taken as arguments for Debug. The backslash at the end of the lines indicates that the line is continued in the next one. Another example shows how to redirect the debug messages to a file and how to set the properties-file:
 java org.dinopolis.util.Debug  --debugfile my_debug_output.txt \ 
   --debugproperiesfile "my_debug.properties" \
   "test.Application argument1 argument2 --option value"
 
*

Version:
$Id: Debug.java,v 1.2 2003/02/18 08:10:20 cdaller Exp $

Field Summary
static boolean DEBUG
           
private static org.dinopolis.util.debug.Debug debug_instance_
           
 
Constructor Summary
Debug()
           
 
Method Summary
static void addLevelsToPrint(java.lang.String levels)
          adds one or more levels, for which messages should be printed (levels can be separated by space, tab, newline or comma).
static void enable(boolean flag)
          Denable/disable debug output.
static java.lang.String getStackTrace()
          Returns a stacktrace.
static java.lang.String getStackTrace(java.lang.Throwable throwable)
          Returns the stacktrace of throwable.
static java.lang.String getStackTraceLine()
          Returns the line of the source code from which this method was called.
static java.lang.String getTimer(java.lang.String name)
          Returns the string representation of the named timer, but does not stop it.
static java.io.Writer getWriter()
          Returns the Writer, where the debug messages are written to.
static boolean isEnabled()
          Returns true, if debug output is enabled.
static boolean isEnabled(java.lang.String level)
          Return true, if debug output is enabled for the given level.
static void main(java.lang.String[] args)
          The main method can be used to set Debug options and then start a given application.
static java.lang.String objectToString(java.lang.Object obj)
          Returns a String representation of the object, this method also handles primitive arrays and object arrays.
static void print(java.lang.Object obj)
          Prints an object (its string-representation).
static void print(java.lang.String level, java.lang.Object obj)
          Prints an object (its string-representation) using the given debug-level.
static void printAllLevels(boolean print_all)
          Should all debug messages be printed, ignoring the level?
static void println(java.lang.Object obj)
          Prints an object (its string-representation).
static void println(java.lang.String level, java.lang.Object obj)
          Prints an object (its string-representation) using the given debug-level.
static void removeAllLevelsToPrint()
          removes all levels, for which messages should be printed
static void removeLevelsToPrint(java.lang.String levels)
          removes one or more levels, for which messages should be printed (levels can be separated by space, tab, newline or comma).
static void setMessageFormat(java.lang.String format_string)
          Set the format of the debug messages.
static void setWriter(java.io.Writer out)
          Sets the writer the debug messages are written to.
static void setWriterToFile(java.lang.String filename)
          Writes all messages to a file.
static void startRefreshPropertiesThread(long refresh_time)
          The Debug Util class is able to reread its property-file from an * independent thread, so any changes in the file (e.g.
static void startTimer(java.lang.String name)
          Creates a new Timer and names it.
static void stopRefreshPropertiesThread()
          The thread that rereads the debug property file is stopped, so any changes in the file are ignored.
static java.lang.String stopTimer(java.lang.String name)
          Stops the named timer and returns the string representation of it.
static void waitEnterPressed()
          Stops the program and waits for a 'enter' on System.in.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

DEBUG

public static final boolean DEBUG
See Also:
Constant Field Values

debug_instance_

private static org.dinopolis.util.debug.Debug debug_instance_
Constructor Detail

Debug

public Debug()
Method Detail

setMessageFormat

public static void setMessageFormat(java.lang.String format_string)
Set the format of the debug messages. Key words are delimited by '%' and are replaced at run-time. Valid key words are: %date% - prints actual date //%count% - prints the debug message counter %milliseconds% - prints the actual milliseconds %diffmilliseconds% - prints the time difference since the last debug message was printed (in milliseconds) %level% - prints the levelname of the debugmessage %stacktrace% - prints a stacktrace to ever msg %stacktraceline% - prints last line in stacktrace (caller) %thread% - prints the string rep of the thread of the caller %threadgroup% - prints the name of the threadgroup of the caller %threadname% - prints the name of the thread of the caller %message% - prints the debug message itself You can also insert '\n' (and others) e.g. to force a new line or '\t' to divide the output in columns. The key words are replaced by their value, the rest is left unchanged. Example:
"DEBUG L=%level%: %message%" prints "DEBUG L=defaultlevel: debug message"


printAllLevels

public static void printAllLevels(boolean print_all)
Should all debug messages be printed, ignoring the level?


addLevelsToPrint

public static void addLevelsToPrint(java.lang.String levels)
adds one or more levels, for which messages should be printed (levels can be separated by space, tab, newline or comma).


removeLevelsToPrint

public static void removeLevelsToPrint(java.lang.String levels)
removes one or more levels, for which messages should be printed (levels can be separated by space, tab, newline or comma).


removeAllLevelsToPrint

public static void removeAllLevelsToPrint()
removes all levels, for which messages should be printed


startTimer

public static void startTimer(java.lang.String name)
Creates a new Timer and names it. The timer starts at zero.


stopTimer

public static java.lang.String stopTimer(java.lang.String name)
Stops the named timer and returns the string representation of it.


getTimer

public static java.lang.String getTimer(java.lang.String name)
Returns the string representation of the named timer, but does not stop it.


enable

public static void enable(boolean flag)
Denable/disable debug output.


isEnabled

public static boolean isEnabled()
Returns true, if debug output is enabled.


isEnabled

public static boolean isEnabled(java.lang.String level)
Return true, if debug output is enabled for the given level. If debug output is disabled in general, this method returns false.


print

public static void print(java.lang.Object obj)
Prints an object (its string-representation). There is no newline added to the debug message.


print

public static void print(java.lang.String level,
                         java.lang.Object obj)
Prints an object (its string-representation) using the given debug-level. There is no newline added to the debug message.


println

public static void println(java.lang.Object obj)
Prints an object (its string-representation). There is a newline added to the debug message.


println

public static void println(java.lang.String level,
                           java.lang.Object obj)
Prints an object (its string-representation) using the given debug-level. There is a newline added to the debug message.


getStackTrace

public static java.lang.String getStackTrace()
Returns a stacktrace. It returned does not include the trace inside the Debug class.


getStackTrace

public static java.lang.String getStackTrace(java.lang.Throwable throwable)
Returns the stacktrace of throwable.


getStackTraceLine

public static java.lang.String getStackTraceLine()
Returns the line of the source code from which this method was called.


objectToString

public static java.lang.String objectToString(java.lang.Object obj)
Returns a String representation of the object, this method also handles primitive arrays and object arrays.


waitEnterPressed

public static void waitEnterPressed()
Stops the program and waits for a 'enter' on System.in. Actually, it waits for any character, but System.in is flushed only on 'enter', so any characters typed before might stay in the keyboard buffer.


startRefreshPropertiesThread

public static void startRefreshPropertiesThread(long refresh_time)
The Debug Util class is able to reread its property-file from an * independent thread, so any changes in the file (e.g. additional * debug-levels set) are reflected in the behaviour of the Debug Util class.


stopRefreshPropertiesThread

public static void stopRefreshPropertiesThread()
The thread that rereads the debug property file is stopped, so any changes in the file are ignored.


setWriterToFile

public static void setWriterToFile(java.lang.String filename)
Writes all messages to a file.


setWriter

public static void setWriter(java.io.Writer out)
Sets the writer the debug messages are written to. The default is System.err.


getWriter

public static java.io.Writer getWriter()
Returns the Writer, where the debug messages are written to.


main

public static void main(java.lang.String[] args)
The main method can be used to set Debug options and then start a given application. After execution of the application the thread that rereads the properties is stopped.

Valid options are:

  • --debuglevels level1,level2: sets one or more debug levels.
  • --debugmessage "messageformat": sets the format of the debug messages. Please see method setMessageFormat for details.
  • --debugfilename debugfile.log: sets the name of the file the debug messages are written to.
  • --debugrefresh milliseconds: sets the refresh time for the thread that rereads the properties-file.
  • --debugpropertiesfile filename: sets the name of the properties-file.

One(!) argument must hold the classname to start and the arguments that should be handed to the main method of the class. To ensure that it is only one argument, put the whole command line in quotes.

E.g. javac org.dinopolis.util.Debug --debuglevels test-level --debugrefresh 5000 --debugfilename debug.log "org.testpackage.testclass argument1 argument2 'argument with space in single quote' --option1"