001: package net.xoetrope.debug;
002:
003: import java.io.StringWriter;
004:
005: import net.xoetrope.data.XDataSource;
006: import net.xoetrope.xui.build.BuildProperties;
007: import net.xoetrope.xui.data.XModel;
008:
009: /**
010: * Keep track of errors and waranings. The class is implemented as a singleton
011: * so that it can count the errors and warnings and give some statistics when
012: * the application shutsdown as a debugging aid.
013: * <p>Copyright (c) Xoetrope Ltd., 2002-2004</p>
014: * $Revision: 1.20 $
015: */
016: public class DebugLogger {
017: public static final int SILENT = -1;
018: public static final int NORMAL = 0;
019: public static final int DEBUG = 1;
020: public static final int VERBOSE = 2;
021: public static final int PARANOID = 3;
022:
023: private static int numErrors;
024: private static int numWarnings;
025: private static DebugLogger logger;
026: private static int level = NORMAL;
027:
028: private static XLogListener logListener;
029:
030: protected DebugLogger() {
031: if (BuildProperties.DEBUG) {
032: numErrors = 0;
033: numWarnings = 0;
034: level = VERBOSE;
035: }
036: }
037:
038: /**
039: * On exit this method will dump the contents of the debug log and close the VM
040: */
041: public static void exitApplication() {
042: if (BuildProperties.DEBUG)
043: net.xoetrope.debug.DebugLogger.dump();
044: System.exit(0);
045: }
046:
047: /**
048: * Display log counts for warnings and errors
049: */
050: public static void dump() {
051: if (BuildProperties.DEBUG) {
052: writeLine("================================================================================");
053: writeLine("There were " + numErrors + " errors logged");
054: writeLine("There were " + numWarnings + " warnings logged");
055: writeLine("================================================================================");
056: }
057: }
058:
059: /**
060: * Get the logger instance
061: * @return the DebugLogger instance
062: */
063: public static DebugLogger getInstance() {
064: if (logger == null)
065: logger = new DebugLogger();
066: return logger;
067: }
068:
069: /**
070: * Write an error message to the error stream. Errors are logged unless the
071: * logLevel is SILENT
072: * @param error the error message
073: */
074: public static void logError(String error) {
075: if (level > SILENT) {
076: getInstance();
077: writeErrorLine("ERROR: " + error);
078: numErrors++;
079: }
080: }
081:
082: /**
083: * Write a warning message to the console. Warnings are logged unless the
084: * logLevel is less than DEBUG or unless the DEBUG build property is set to false
085: * @param warning the warning message
086: */
087: public static void logWarning(String warning) {
088: if (BuildProperties.DEBUG) {
089: getInstance();
090: if (level >= DEBUG) {
091: writeLine("WARNING: " + warning);
092: numWarnings++;
093: }
094: }
095: }
096:
097: /**
098: * Write a message to the log
099: * @param msg the message to log
100: */
101: public static void log(String msg) {
102: getInstance();
103: writeLine(msg);
104: }
105:
106: /**
107: * Write a message to the console. Trace messages are logged unless the
108: * logLevel is less than VERBOSE or unless the DEBUG build property is set to false
109: * @param msg the log message
110: */
111: public static void trace(String msg) {
112: if (BuildProperties.DEBUG) {
113: getInstance();
114: if (level >= VERBOSE)
115: writeLine("TRACE: " + msg);
116: }
117: }
118:
119: /**
120: * Write a message to the console. The message is assumed to have a substitution
121: * for a numeric value e.g. 'TRACE: The X value is VALUE: 1.09'
122: * Trace messages are logged unless the logLevel is less than VERBOSE or
123: * unless the DEBUG build property is set to false
124: * @param msg the log message
125: * @param value the value causing the trace
126: */
127: public static void trace(String msg, double value) {
128: if (BuildProperties.DEBUG) {
129: getInstance();
130: if (level >= VERBOSE)
131: writeLine("TRACE: " + msg + " VALUE: " + value);
132: }
133: }
134:
135: /**
136: * Write a snapshot of a model or model fragment to the log
137: * @param model the model node to log
138: */
139: public static void trace(XModel model) {
140: if (BuildProperties.DEBUG) {
141: getInstance();
142: if (level >= VERBOSE) {
143: writeLine("TRACE: model type - "
144: + model.getClass().getName() + "["
145: + model.getNumChildren() + ","
146: + model.getNumAttributes() + "]");
147: writeLine("--------------------------------------------------------------------------------");
148:
149: StringWriter sw = new StringWriter();
150: XDataSource os = new XDataSource();
151: if (model instanceof DumpWriter)
152: ((DumpWriter) model).dump(sw);
153: else
154: os.outputModel(sw, model);
155: System.out.print(sw.toString());
156: writeLine("--------------------------------------------------------------------------------");
157: }
158: }
159: }
160:
161: /**
162: * Write a representation of the model to the console.
163: * @param model
164: */
165: public static void dumpModel(XModel model) {
166: if (BuildProperties.DEBUG) {
167: if (model != null) {
168: try {
169: writeLine(model.getTagName() + ":" + model.getId()
170: + ":" + model.get());
171: } catch (Exception ex) {
172: writeLine(model.toString());
173: }
174: for (int i = 0; i < model.getNumChildren(); i++) {
175: try {
176: dumpModel((XModel) model.get(i));
177: } catch (Exception ex1) {
178: writeLine(new Integer(i).toString());
179: }
180: }
181: if (model.getNumChildren() != 0)
182: writeLine("--------------------------------------------------------------------------------");
183: }
184: }
185: }
186:
187: /**
188: * Set the logging level, by default the level is verbose<br>
189: * NORMAL = 0, only output error messages<br>
190: * DEBUG = 1, output errors, dumps and exit messages<br>
191: * VERBOSE = 2, output debug messages, errors, dumps, exit massages, traces and log values<br>
192: * PARANOID = 3, output all logging information<br>
193: * @param newLevel the new log level
194: */
195: public static void setDebugLevel(int newLevel) {
196: level = newLevel;
197: }
198:
199: /**
200: * Set the logging level, by default the level is verbose<br>
201: * SILENT = -1, do not log anything
202: * NORMAL = 0, only output error messages<br>
203: * DEBUG = 1, output errors, dumps and exit messages<br>
204: * VERBOSE = 2, output debug messages, errors, dumps, exit massages, traces and log values<br>
205: * PARANOID = 3, output all logging information<br>
206: * @param newLevel the new log level
207: */
208: public static void setDebugLevel(String newLevel) {
209: try {
210: if (newLevel != null)
211: level = new Integer(newLevel).intValue();
212: } catch (NumberFormatException ex) {
213: logError("Unable to set the logging level, invalid value: "
214: + newLevel);
215: }
216: }
217:
218: /**
219: * Write a line to the system output and log the message
220: * @param line the message to log
221: */
222: protected static void writeLine(String line) {
223: if (logListener != null)
224: logListener.addMessage(line);
225: System.out.println(line);
226: }
227:
228: /**
229: * Write an error line to the system error stream and log the message
230: * @param line the message to log
231: */
232: protected static void writeErrorLine(String line) {
233: if (logListener != null)
234: logListener.addError(line);
235: System.err.println(line);
236: }
237:
238: /**
239: * Set a listener for log messsages
240: * @param logger the listener
241: */
242: public static void setLogListener(XLogListener logger) {
243: logListener = logger;
244: }
245: }
|