001: package com.quadcap.util;
002:
003: /* Copyright 1997 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.File;
042: import java.io.FileOutputStream;
043: import java.io.IOException;
044: import java.io.PrintStream;
045:
046: import java.util.Date;
047: import java.util.Hashtable;
048:
049: import java.sql.SQLException;
050:
051: import java.text.SimpleDateFormat;
052:
053: import com.quadcap.sql.file.DatafileException;
054:
055: /**
056: * Common functions for debug and log output.
057: *
058: * @author Stan Bailes
059: */
060: public class Debug {
061: static public PrintStream debugStream = System.out;
062: static public int printLevel = 0;
063:
064: private static String debugFileName = null;
065: private static FileOutputStream debugFileStream = null;
066:
067: static Hashtable debugMap = new Hashtable();
068: static NullSecurityManager sm = null;
069:
070: static public final int debugOff = 0;
071: static public final int debugSome = 1;
072: static public final int debugAll = 3;
073: static public final int debugPackage = 4;
074:
075: static public int debugMode = debugAll;
076:
077: static public final int debugNoTime = 0;
078: static public final int debugElap = 1;
079: static public final int debugInterval = 2;
080: static public final int debugShowTime = 3;
081:
082: static public int debugTime = debugShowTime;
083:
084: static public long start = new Date().getTime();
085: static public long last = start;
086:
087: static SimpleDateFormat sdf = new SimpleDateFormat(
088: "yyyy-MM-dd HH:mm:ss.SSS");
089:
090: /*{com.quadcap.util.Config-vars.xml-0}
091: *
092: * <config>
093: */
094:
095: /*{com.quadcap.util.Config-vars.xml-999999}
096: *
097: * </config>
098: */
099:
100: /*{com.quadcap.util.Config-vars.xml-10}
101: *
102: * <config-var>
103: * <config-name>debug.file</config-name>
104: * <config-dflt>stderr</config-dflt>
105: * <config-desc>Specify the name of the debug log file. The default
106: * value, <code>stderr</code>, causes debug information to
107: * be written to <code>System.err</code>.</config-desc>
108: * </config-var>
109: *
110: * <config-var>
111: * <config-name>debug.level</config-name>
112: * <config-dflt>0</config-dflt>
113: * <config-desc>Specify the level of debugging output. Level zero,
114: * the lowest level, essentially turns debug output off (though
115: * errors/exceptions will still be reported.) Increasing levels
116: * will result in more debug output. The maximum debug level is
117: * five (5).</config-desc>
118: * </config-var>
119: */
120: static {
121: //System.setSecurityManager(sm = new NullSecurityManager());
122: try {
123: ConfigString file = ConfigString.find("debug.file",
124: "stderr");
125: if (file != null) {
126: setLogFile(file.toString());
127: }
128: ConfigNumber level = ConfigNumber.find("debug.level", "0");
129: if (level != null) {
130: printLevel = level.intValue();
131: }
132: } catch (IOException e) {
133: Debug.print(e);
134: }
135: }
136:
137: static public Class[] getClassContext() {
138: return sm.pubGetClassContext();
139: }
140:
141: static public void setDebugLevel(String name, String level) {
142: debugMap.put(name, level);
143: }
144:
145: static public void print(Throwable e) {
146: if (e == null)
147: return;
148: if (!(e instanceof SQLException)) {
149: Debug.println(0, 2, e.getClass().getName());
150: }
151: debugStream.print(hdr());
152: e.printStackTrace(debugStream);
153: if (e instanceof SQLException) {
154: printSQLException((SQLException) e);
155: } else if (e.getCause() != null) {
156: Debug.println("Cause of this exception:");
157: print(e.getCause());
158: }
159: }
160:
161: static void printSQLException(SQLException e) {
162: StringBuffer sb = new StringBuffer(e.toString());
163: int idx;
164: while ((idx = sb.toString().indexOf("Exception:")) >= 0) {
165: sb.setCharAt(idx + 9, ',');
166: }
167: Debug
168: .println(0, 3, sb.toString() + ", SQLState = "
169: + e.getSQLState() + ", errorCode = "
170: + e.getErrorCode());
171: SQLException next = e.getNextException();
172: if (next != null) {
173: Debug.println("Next SQL Exception:");
174: printSQLException(next);
175: } else if (e.getCause() != null) {
176: Debug.println("Cause of this exception:");
177: print(e);
178: }
179: }
180:
181: static public void println(String s) {
182: println(0, 1, s);
183: }
184:
185: static public String getInterval() {
186: String ret = null;
187: Date d = new Date();
188: long now = d.getTime();
189:
190: switch (debugTime) {
191: case debugInterval:
192: ret = "" + (now - last);
193: last = now;
194: break;
195: case debugElap:
196: ret = "" + (now - start);
197: break;
198: case debugShowTime:
199: ret = "" + sdf.format(d);
200: break;
201: }
202: return ret;
203: }
204:
205: /**
206: * Specify the file to be used for debug/log output. If there is
207: * already a debug file open with a different name, it is closed first,
208: * and if the name specified is <code>"stdout"</code>, then debug
209: * output is directed to <code>System.out</code>.
210: *
211: * @param name the name of the debug log file.
212: * @exception IOException may be thrown.
213: */
214: static public void setLogFile(String name) throws IOException {
215: if (name.equals("stdout")) {
216: if (debugFileStream != null) {
217: debugFileStream.close();
218: debugFileStream = null;
219: }
220: debugStream = System.out;
221: } else if (name.equals("stderr")) {
222: if (debugFileStream != null) {
223: debugFileStream.close();
224: debugFileStream = null;
225: }
226: debugStream = System.err;
227: } else {
228: boolean append = name.startsWith("append:");
229: if (append)
230: name = name.substring(7).trim();
231: name = new File(name).getAbsolutePath();
232: if (debugFileName == null || !name.equals(debugFileName)) {
233: debugFileName = name;
234: if (debugFileStream != null) {
235: debugFileStream.close();
236: debugFileStream = null;
237: }
238: debugFileStream = new FileOutputStream(name, append);
239: debugStream = new PrintStream(debugFileStream);
240: println("---- [Debug started]");
241: }
242: }
243: }
244:
245: /**
246: * Specify the 'level' for debugging output. Only debug statements
247: * satisfying <code>level <= printLevel</code> result in output.
248: *
249: * @param printLevel the new debug output level.
250: */
251: static public void setLogLevel(int printLevel) {
252: if (printLevel != Debug.printLevel) {
253: Debug.println(0, "Changing log level from "
254: + Debug.printLevel + " to " + printLevel);
255: Debug.printLevel = printLevel;
256: }
257: }
258:
259: /**
260: * Specify the debug mode using the convenient string representation
261: *
262: * @param mode the debug mode.
263: */
264: static public void setDebugMode(String mode) {
265: if (mode.equals("off")) {
266: Debug.debugMode = Debug.debugOff;
267: } else if (mode.equals("some")) {
268: Debug.debugMode = Debug.debugSome;
269: } else if (mode.equals("all")) {
270: Debug.debugMode = Debug.debugAll;
271: } else if (mode.equals("package")) {
272: Debug.debugMode = Debug.debugPackage;
273: }
274: }
275:
276: /**
277: * Debug output at level <code>level</code>.
278: */
279: static synchronized public void println(int level, String s) {
280: println(level, 1, s);
281: }
282:
283: static String hdr() {
284: StringBuffer sb = new StringBuffer();
285: if (debugTime != debugNoTime) {
286: sb.append(getInterval());
287: sb.append(": ");
288: }
289: sb.append("[");
290: sb.append(Thread.currentThread().getName());
291: sb.append("] ");
292: return sb.toString();
293: }
294:
295: /**
296: * Debug output at level <code>level</code>.
297: */
298: static synchronized public void println(int level, int depth,
299: String s) {
300: if (level > printLevel)
301: return;
302: debugStream.print(hdr());
303: if (sm != null) {
304: String className = debugSite(level, depth + 1);
305: debugStream.print(className + ": ");
306: }
307: debugStream.println(s);
308: }
309:
310: static String debugSite(int level, int depth) {
311: if (debugMode == debugOff || level > printLevel)
312: return null;
313: boolean print = true;
314: Class[] classes = sm.pubGetClassContext();
315:
316: String className = "";
317: String packageName = "";
318: if (classes.length > 2 + depth) {
319: Class caller = classes[2 + depth];
320: className = caller.getName();
321: int pos = className.lastIndexOf('.');
322: if (pos >= 0) {
323: packageName = className.substring(0, pos);
324: className = className.substring(pos + 1);
325: }
326: }
327:
328: String debugVal;
329:
330: switch (debugMode) {
331: case debugSome:
332: debugVal = (String) debugMap.get(className);
333: if (debugVal != null && level <= Integer.parseInt(debugVal)) {
334: print = debugMode == debugSome;
335: }
336: break;
337: case debugPackage:
338: debugVal = (String) debugMap.get(packageName);
339: if (debugVal != null && level <= Integer.parseInt(debugVal)) {
340: print = debugMode == debugPackage;
341: }
342: break;
343: }
344:
345: if (print)
346: return className;
347: return null;
348: }
349:
350: }
|