001: package com.salmonllc.util;
002:
003: /////////////////////////
004: //$Archive: /SOFIA/SourceCode/com/salmonllc/util/MessageLog.java $
005: //$Author: Dan $
006: //$Revision: 21 $
007: //$Modtime: 9/21/04 1:15p $
008: /////////////////////////
009:
010: import java.io.*;
011: import java.text.DecimalFormat;
012: import java.text.SimpleDateFormat;
013: import java.util.Date;
014: import java.util.HashMap;
015:
016: import com.salmonllc.properties.Props;
017:
018: /**
019: * This class is used to write messages to the system console or to a log file.
020: */
021: public class MessageLog implements Runnable {
022:
023: private static HashMap _appLoggers = new HashMap();
024: private static MessageLog _defaultLog;
025: private static boolean _runThread = true;
026: private int _logErrors = 10;
027: private int _logAssertions = 0;
028: private int _logInfo = 0;
029: private int _logSQL = 0;
030: private int _logDebug = 0;
031: private boolean _init = false;
032: private boolean _hideTimestamp = false;
033: private boolean _hideThread = false;
034: private String _logFile;
035: private int _logFileIndex;
036: private int _logFileSize = -1;
037: private PrintStream _errorOut = null;
038: private PrintStream _assertOut = null;
039: private PrintStream _infoOut = null;
040: private PrintStream _debugOut = null;
041: private PrintStream _SQLOut = null;
042: private Logger _logger = null;
043: private String _oldLoggerName = null;
044: private String _oldConfigName = null;
045: private long _oldConfigDate = -1;
046: private String _appName;
047:
048: private MessageLog(String appName) {
049: super ();
050: _appName = appName;
051: checkStatus();
052: }
053:
054: private synchronized void checkStatus() {
055: if (!_init) {
056: _init = true;
057: if (loadProperties()) {
058: Thread t = ApplicationContext
059: .createThreadWithContextClone(this );
060: t.start();
061: }
062: } else
063: loadProperties();
064:
065: }
066:
067: /**
068: * Use this method to get the level of logging desired.
069: * true converts to a level = 11
070: * false converts to a level = 0
071: * all others are returned as is
072: */
073:
074: private int getLoggingLevel(String prop) {
075: int retVal = 11;
076:
077: if (!Util.isNumeric(prop)) {
078: if (Util.isTrue(prop)) {
079: retVal = 11;
080: } else {
081: retVal = -1;
082: }
083:
084: } else {
085: retVal = Integer.parseInt(prop);
086: }
087: return retVal;
088: }
089:
090: private static PrintStream setUpPrintStream(Props pr, String key,
091: PrintStream def) {
092: String val = pr.getProperty(key);
093: if (val == null)
094: return def;
095: else if (val.equalsIgnoreCase("true"))
096: return def;
097: else if (val.equalsIgnoreCase("out"))
098: return System.out;
099: else if (val.equalsIgnoreCase("err"))
100: return System.err;
101: else
102: return null;
103: }
104:
105: private boolean loadProperties() {
106: Props p = Props.getSystemProps();
107: if (p == null)
108: return false;
109:
110: String logger = p
111: .getProperty(Props.SYS_MESSAGELOG_LOGGER_CLASS);
112: String configFile = p
113: .getProperty(Props.SYS_MESSAGELOG_LOGGER_CONFIG_FILE);
114: boolean reload = false;
115: if (logger != null) {
116: if (!valuesEqual(logger, _oldLoggerName))
117: reload = true;
118: else if (!valuesEqual(configFile, _oldConfigName))
119: reload = true;
120: else if (configFile != null) {
121: File cf = new File(configFile);
122: if (cf.exists()) {
123: if (cf.lastModified() != _oldConfigDate)
124: reload = true;
125: }
126:
127: }
128:
129: }
130:
131: if (reload) {
132: try {
133: Class c = Class.forName(logger);
134: _logger = (Logger) c.newInstance();
135: _oldConfigName = configFile;
136: _oldLoggerName = logger;
137: if (configFile != null) {
138: File cf = new File(configFile);
139: if (cf.exists())
140: _oldConfigDate = cf.lastModified();
141: } else
142: _oldConfigDate = -1;
143: return true;
144: } catch (Exception e) {
145: System.err.println("Error:Could not load logger class:"
146: + logger + " using default!");
147: e.printStackTrace();
148: }
149: }
150: String prop = null;
151: // ERRORS
152: prop = p.getProperty(Props.LOG_ERRORS);
153: _logErrors = getLoggingLevel(prop);
154: _errorOut = setUpPrintStream(p, Props.LOG_ERRORS_TO_CONSOLE,
155: System.err);
156:
157: // ASSERTIONS
158: prop = p.getProperty(Props.LOG_ASSERTIONS);
159: _logAssertions = getLoggingLevel(prop);
160: _assertOut = setUpPrintStream(p,
161: Props.LOG_ASSERTIONS_TO_CONSOLE, System.err);
162:
163: // INFO
164: prop = p.getProperty(Props.LOG_INFO);
165: _logInfo = getLoggingLevel(prop);
166: _infoOut = setUpPrintStream(p, Props.LOG_INFO_TO_CONSOLE,
167: System.out);
168:
169: // SQL
170: prop = p.getProperty(Props.LOG_SQL);
171: _logSQL = getLoggingLevel(prop);
172: _SQLOut = setUpPrintStream(p, Props.LOG_SQL_TO_CONSOLE,
173: System.out);
174:
175: // DEBUG
176: prop = p.getProperty(Props.LOG_DEBUG);
177: _logDebug = getLoggingLevel(prop);
178: _debugOut = setUpPrintStream(p, Props.LOG_DEBUG_TO_CONSOLE,
179: System.out);
180:
181: _logFile = p.getProperty(Props.LOG_FILE_NAME);
182:
183: _hideThread = p.getBooleanProperty(Props.LOG_HIDE_THREAD);
184: _hideTimestamp = p.getBooleanProperty(Props.LOG_HIDE_TIME);
185:
186: if (_logFile != null) {
187:
188: //file size is in bytes -1 is unlimited
189: _logFileSize = p.getIntProperty(Props.LOG_FILE_SIZE_LIMIT);
190:
191: String logFileExtension = p.getProperty(Props.LOG_FILE_EXT);
192: boolean appendDate = p
193: .getBooleanProperty(Props.LOG_FILE_APPEND_DATE);
194: if (appendDate) {
195: SimpleDateFormat d = new SimpleDateFormat("-yyyy-MM-dd");
196: _logFile += d.format(new Date(System
197: .currentTimeMillis()));
198:
199: }
200: if (logFileExtension != null)
201: _logFile += "." + logFileExtension;
202: }
203: return true;
204: }
205:
206: /**
207: * This method is part of the run thread used by this object. It should not be called directy.
208: */
209: public void run() {
210: while (_runThread) {
211: try {
212: Thread.sleep(15000);
213: checkStatus();
214: } catch (Exception e) {
215: }
216: }
217: }
218:
219: private void writeAssertionMessageInstance(String message,
220: int level, Object o) {
221: if (_logger != null)
222: _logger.log(message, Logger.TYPE_ASSERTION, level, null, o);
223: else if (_logAssertions >= level)
224: writeMessage("Assertion", o, message, null, _assertOut);
225: }
226:
227: /**
228: * Use this method to log Assertion Messages.
229: */
230: public static void writeAssertionMessage(String message, Object o) {
231: writeAssertionMessage(message, 0, o);
232: }
233:
234: /**
235: * Use this method to log Assertion Messages.
236: */
237: public static void writeAssertionMessage(String message, int level,
238: Object o) {
239: getLogger().writeAssertionMessageInstance(message, level, o);
240: }
241:
242: /**
243: * Use this method to log Debug Messages.
244: */
245: public static void writeDebugMessage(String message, int level,
246: Object o) {
247: getLogger().writeDebugMessageInstance(message, level, o);
248: }
249:
250: /**
251: * Use this method to log Debug Messages.
252: */
253: public static void writeDebugMessage(String message, Object o) {
254: writeDebugMessage(message, 0, o);
255: }
256:
257: private void writeDebugMessageInstance(String message, int level,
258: Object o) {
259: if (_logger != null)
260: _logger.log(message, Logger.TYPE_DEBUG, level, null, o);
261: else if (_logDebug >= level)
262: writeMessage("Debug", o, message, null, _debugOut);
263: }
264:
265: /**
266: * Use this method to log Error Messages.
267: */
268:
269: public static void writeErrorMessage(String message, int level,
270: Throwable e, Object o) {
271: getLogger().writeErrorMessageInstance(message, 0, e, o);
272: }
273:
274: /**
275: * Use this method to log Error Messages.
276: */
277: public static void writeErrorMessage(String message, Throwable e,
278: Object o) {
279: writeErrorMessage(message, 0, e, o);
280: }
281:
282: private void writeErrorMessageInstance(String message, int level,
283: Throwable e, Object o) {
284: if (_logger != null)
285: _logger.log(message, Logger.TYPE_ERROR, level, e, o);
286: else if (_logErrors >= level) {
287: if (message != null) {
288: if (e != null) {
289: writeMessage("Error", o, message + ":"
290: + e.toString(), e, _errorOut);
291: } else {
292: writeMessage("Error", o, message, e, _errorOut);
293: }
294: } else {
295: writeMessage("Error", o, e.toString(), e, _errorOut);
296: }
297: }
298: }
299:
300: /**
301: * Use this method to log Error Messages.
302: */
303:
304: public static void writeErrorMessage(Throwable e, Object o) {
305: writeErrorMessage(null, e, o);
306: }
307:
308: /**
309: * Use this method to Log Info Messages.
310: */
311: public static void writeInfoMessage(String message, int level,
312: Object o) {
313: getLogger().writeInfoMessageInstance(message, level, o);
314: }
315:
316: /**
317: * Use this method to Log Info Messages.
318: */
319:
320: public static void writeInfoMessage(String message, Object o) {
321: writeInfoMessage(message, 0, o);
322: }
323:
324: private void writeInfoMessageInstance(String message, int level,
325: Object o) {
326: if (_logger != null)
327: _logger.log(message, Logger.TYPE_INFO, level, null, o);
328: else if (_logInfo >= level)
329: writeMessage("Information Message", o, message, null,
330: _infoOut);
331: }
332:
333: private synchronized void writeMessage(String type, Object source,
334: String message, Throwable t, PrintStream p) {
335: StringBuffer outMessage = new StringBuffer("{ ");
336: outMessage.append(type);
337: outMessage.append(" | ");
338: if (!_hideTimestamp) {
339: outMessage.append((new java.sql.Timestamp(System
340: .currentTimeMillis())));
341: outMessage.append(" | ");
342: }
343:
344: if (!_hideThread) {
345: outMessage.append(Thread.currentThread());
346: outMessage.append(" | ");
347: }
348:
349: if (source != null) {
350: outMessage.append(source.getClass().getName());
351: }
352: outMessage.append("} ");
353: if (message != null) {
354: outMessage.append(message);
355: }
356: if (p != null)
357: p.println(outMessage);
358:
359: if (t != null) {
360: if (p != null) {
361: p.println("{Stack Trace");
362: t.printStackTrace(p);
363: p.println("}");
364: }
365: }
366: if (_logFile != null) {
367: try {
368: File f = new File(_logFile);
369: FileOutputStream out = null;
370: if (f.exists()) {
371:
372: if (!(_logFileSize <= 0)
373: && f.length() >= _logFileSize) {
374: String renameFile = null;
375: renameFile = _logFile
376: + "."
377: + new DecimalFormat("00000")
378: .format(_logFileIndex);
379: File renf = new File(renameFile);
380: while (renf.exists()) {
381: _logFileIndex++;
382: renameFile = _logFile
383: + "."
384: + new DecimalFormat("00000")
385: .format(_logFileIndex);
386: renf = new File(renameFile);
387: }
388: _logFileIndex++;
389: f.renameTo(renf);
390: out = new FileOutputStream(f);
391:
392: } else {
393: out = new FileOutputStream(_logFile, true);
394: }
395: } else {
396: out = new FileOutputStream(f);
397: }
398: PrintWriter pw = new PrintWriter(
399: new OutputStreamWriter(out));
400: pw.println(outMessage);
401: if (t != null) {
402: pw.println("[Stack Trace");
403: t.printStackTrace(pw);
404: pw.println("]");
405: }
406: pw.close();
407: out.close();
408: } catch (Exception e) {
409: System.err.println("Error Writing Message to:"
410: + _logFile + ":" + e);
411: }
412: }
413: }
414:
415: private void writeSQLMessageInstance(String message, int level,
416: String sql, Object o) {
417: if (_logger != null)
418: _logger.log(message + " " + sql, Logger.TYPE_SQL, level,
419: null, o);
420: else if (_logSQL >= level)
421: writeMessage("SQL Statement", o, message + " " + sql, null,
422: _SQLOut);
423: }
424:
425: /**
426: * Use this method to log SQL Messages.
427: */
428: public static void writeSQLMessage(String message, String sql,
429: Object o) {
430: writeSQLMessage(message, 0, sql, o);
431: }
432:
433: /**
434: * Use this method to log SQL Messages.
435: */
436: public static void writeSQLMessage(String message, int level,
437: String sql, Object o) {
438: getLogger().writeSQLMessageInstance(message, level, sql, o);
439: }
440:
441: private static boolean valuesEqual(Object newValue, Object oldValue) {
442: if (newValue == null && oldValue != null)
443: return false;
444: else if (newValue != null && oldValue == null)
445: return false;
446: else if (newValue != null && oldValue != null)
447: if (!newValue.toString().trim().equals(
448: oldValue.toString().trim()))
449: return false;
450:
451: return true;
452: }
453:
454: public static synchronized MessageLog getLoggerForApplication(
455: String appName) {
456: MessageLog ret = (MessageLog) _appLoggers.get(appName);
457: if (ret == null) {
458: ret = new MessageLog(appName);
459: _appLoggers.put(appName, ret);
460: }
461: return ret;
462: }
463:
464: public String toString() {
465: return _appName + " " + _logFile;
466: }
467:
468: private static MessageLog getLogger() {
469: ApplicationContext cont = ApplicationContext.getContext();
470: if (cont != null) {
471: return cont.getLogger();
472: } else {
473: if (_defaultLog == null)
474: _defaultLog = new MessageLog("");
475: return _defaultLog;
476:
477: }
478: }
479:
480: public static void stopThreads() {
481: _runThread = false;
482: }
483: }
|