//package com.knownspace.tools; import java.io.CharArrayWriter; import java.io.PrintWriter; import java.util.StringTokenizer; import java.util.NoSuchElementException; public class Debug { /* A simple debugger to implement breakpoint assertion testing. Public Methods: --------------- assert(booleanCondition) //fires if booleanCondition==false assert(booleanCondition, messageString) //fires if booleanCondition==false //and prints messageString In both cases the debugger prints the offending method's name. Since assert() is a static method, you can call it with "Debug.assert(...)". Every method should have its own assertions to test the state of its arguments on entry into the method. Set DEBUG_MODE to false when you want to turn off assertion testing. (Be absolutely sure that your code is working perfectly first!) */ private final static boolean FATAL_ERROR_LEVEL_SET = false; private final static boolean DEBUG_MODE = true; //number of method calls to step back in the stack to find the offending //method name and line number using the sun JDK private final static int STACK_LEVEL = 2; /////////////////////////////////////////////////////////////////////// public final static void assert(boolean condition) { if (DEBUG_MODE) { if (! condition) printError("assertion failed in: " + getCaller(STACK_LEVEL)); checkFatality(); } } /////////////////////////////////////////////////////////////////////// public final static void assert(boolean condition, String string) { if (DEBUG_MODE) { if (! condition) { printError("assertion failed: " + string); printError("in: " + getCaller(STACK_LEVEL)); } checkFatality(); } } /////////////////////////////////////////////////////////////////////// private final static void printError(String string) { System.out.println(string); } /////////////////////////////////////////////////////////////////////// private final static void checkFatality() { if (FATAL_ERROR_LEVEL_SET) System.exit(1); } /////////////////////////////////////////////////////////////////////// private final static String getCaller(int callerNumber) { /* Determine the callerNumber'th method that called this method and return its name. NOTE: This method may not work with code compiled using a JIT or with a non-JDK JVM since in either case the stack trace format is unspecified in the language spec. Stack trace format assumed: --------------------------- java.lang.Throwable at at (callerNumber == 1) at (callerNumber == 2) at (callerNumber == 3) */ if (callerNumber < 1) return "Debugger"; //transform the caller number into the token number to search for int tokenNumber = (callerNumber * 2) + 3; //create a stream to catch the stack trace CharArrayWriter stream = new CharArrayWriter(); //send the stack trace to the stream Throwable throwable = new Throwable(); throwable.printStackTrace(new PrintWriter(stream)); //parse the stack trace to find the callerNumber'th method call StringTokenizer stackTrace = new StringTokenizer(stream.toString()); String token = ""; try { for (int i = 0; i < tokenNumber; i++) token = stackTrace.nextToken(); } catch (NoSuchElementException ignored) { token = "unknown"; } return token; } }