001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: /*
066: * LogHandler.java
067: *
068: * Copyright 1999, 2000, 2001 Jcorporate Ltd.
069: */
070: package com.jcorporate.expresso.core.logging;
071:
072: import com.jcorporate.expresso.core.db.DBException;
073: import com.jcorporate.expresso.core.registry.ExpressoThread;
074: import com.jcorporate.expresso.services.dbobj.LogEntry;
075: import org.apache.log4j.Logger;
076:
077: import java.io.ByteArrayOutputStream;
078: import java.io.PrintStream;
079: import java.util.Vector;
080:
081: /**
082: * The LogHandler is an asynchronous version of logging - it accepts
083: * requests to log, then logs them "eventually" in a separate thread
084: *
085: * @author Michael Nash
086: * @deprecated As of Expresso 5.6 This has not been used since
087: * Log4j was integrated with Expresso.
088: */
089: public class LogHandler extends ExpressoThread {
090: private static Vector queue = new Vector(3);
091: private static boolean trace = false;
092: private static LogHandler myInstance = null;
093: private static int maxLevel = 9;
094: private static boolean daemonMode = false;
095: private static Logger log = Logger.getLogger(LogHandler.class);
096:
097: /**
098: * Log Handler shuts down it's background thread when it's been
099: * idle for a while
100: */
101: private static int idleTimes = 0;
102: private static int maxIdleTimes = 10;
103:
104: /**
105: * Don't write more than a certain number of log entries, it slows
106: * the system down too much
107: */
108: private static int maxWrites = 5;
109:
110: /**
111: * How long to sleep between checking the queue
112: */
113: private int sleepTime = 30;
114: private static String this Class = LogHandler.class.getName();
115:
116: /**
117: * Constructor
118: */
119: public LogHandler() {
120:
121: /* String sleepTimeString = StringUtil.notNull(ConfigManager.getProperty(
122:
123: "loghandler.sleeptime"));
124:
125: if (!sleepTimeString.equals("")) {
126:
127: sleepTime = new Integer(sleepTimeString).intValue();
128:
129: } */
130: } /* LogHandler() */
131:
132: /**
133: * @param le
134: */
135: public synchronized void addToQueue(LogEntry le) {
136: queue.addElement(le);
137: } /* addToQueue(LogEntry) */
138:
139: /**
140: * Takes a premade LogEntry and sends it to the logging queue. Used by
141: * the DBAppender.class
142: *
143: * @param le
144: */
145: public static synchronized void staticAddToQueue(LogEntry le) {
146: startUp();
147:
148: if (myInstance != null) {
149: queue.addElement(le);
150: }
151: } /* staticAddToQueue(LogEntry) */
152:
153: /**
154: * Actually check the log queue and save the entries
155: */
156: private synchronized void checkQueue() throws LogException {
157: String myName = (this Class + "checkQueue()");
158:
159: if (queue.size() == 0) {
160: idleTimes++;
161:
162: if (trace) {
163: System.err.println(myName + ":Queue empty. Idle "
164: + idleTimes + " times");
165: }
166:
167: return;
168: }
169: if (trace) {
170: System.err.println(myName + ":Checking queue. "
171: + queue.size() + " entries");
172: }
173: try {
174: LogEntry oneLogEntry = null;
175: int writeCount = 0;
176:
177: while (queue.size() > 0) {
178: oneLogEntry = (LogEntry) queue.firstElement();
179: queue.removeElementAt(0);
180: oneLogEntry.add();
181: writeCount++;
182:
183: if (writeCount > maxWrites) {
184: break;
185: }
186: } /* for each queue entry */
187:
188: } catch (Exception de) {
189: de.printStackTrace(System.err);
190: throw new LogException(myName
191: + ":Database error storing log queue", de);
192: }
193: } /* checkQueue() */
194:
195: /**
196: * Translate a color spelt out in english in to a one-char encoding
197: *
198: * @param color
199: * @return
200: */
201: private static String encode(String color) {
202: if (color.equalsIgnoreCase("RED")) {
203: return ("R");
204: } else if (color.equalsIgnoreCase("GREEN")) {
205: return ("G");
206: } else if (color.equalsIgnoreCase("BLUE")) {
207: return ("B");
208: } else if (color.equalsIgnoreCase("YELLOW")) {
209: return ("Y");
210: } else {
211: return ("");
212: }
213: } /* encode(String) */
214:
215: /**
216: * If for any reason the app exits, and gc is getting called
217: * we need to flush what we've got and then bail.
218: */
219: public void finalize() {
220: try {
221: flush();
222: } catch (LogException e) {
223: }
224: } /* finalize() */
225:
226: /**
227: * @throws LogException
228: */
229: public static void flush() throws LogException {
230: startUp();
231: myInstance.checkQueue();
232: } /* flush() */
233:
234: /**
235: * Log a new message at the given level, if we log at or above this level
236: *
237: * @param newLevel Log level
238: * @param msg Message to log
239: */
240: public static void log(int newLevel, String msg) {
241: String myName = (this Class + "log(int, String)");
242:
243: if (newLevel <= maxLevel) {
244: if (trace) {
245: System.err.println(msg);
246: }
247:
248: startUp();
249:
250: try {
251: LogEntry myLog = new LogEntry();
252: myLog.setField("MessageText", msg);
253: myLog.setField("MessageLevel", "" + newLevel);
254: myLog.setTimeStamp();
255: myInstance.addToQueue(myLog);
256: } catch (DBException de) {
257: System.err.println(myName + ":Unable to log '" + msg
258: + "'");
259: de.printStackTrace(System.err);
260: }
261: } /* if level is logged */
262:
263: } /* log(int, String) */
264:
265: /**
266: * Log the given message at the given level, recording the originating
267: * object
268: *
269: * @param newLevel Logging level of this message
270: * @param objectName Calling object
271: * @param msg Message to log
272: */
273: public static void log(int newLevel, String objectName, String msg)
274: throws LogException {
275: String myName = (this Class + "log(int, String, String)");
276:
277: if (newLevel <= maxLevel) {
278: if (trace) {
279: System.err.println(objectName + ":" + msg);
280: }
281:
282: startUp();
283:
284: try {
285: LogEntry myLog = new LogEntry();
286: myLog.setField("ObjectName", objectName);
287: myLog.setField("MessageText", msg);
288: myLog.setField("MessageLevel", "" + newLevel);
289: myLog.setTimeStamp();
290: myInstance.addToQueue(myLog);
291: } catch (DBException de) {
292: throw new LogException(myName + ":" + de.getMessage());
293: }
294: } /* if this level is logged */
295:
296: } /* log(int, String, String) */
297:
298: /**
299: * Log a message from a particular object with a color at the given
300: * level
301: *
302: * @param newLevel Message level to log
303: * @param objectName Calling object
304: * @param msg Message to log
305: * @param color Color to log the message with
306: */
307: public static void log(int newLevel, String objectName, String msg,
308: String color) {
309: String myName = (this Class + "log(int, String, String, " + "String)");
310:
311: if (newLevel <= maxLevel) {
312: if (trace) {
313: System.err.println(objectName + ":" + msg);
314: }
315:
316: startUp();
317:
318: try {
319: LogEntry myLog = new LogEntry();
320: myLog.setField("ObjectName", objectName);
321: myLog.setField("MessageText", msg);
322: myLog.setField("MessageColor", encode(color));
323: myLog.setField("MessageLevel", "" + newLevel);
324: myLog.setTimeStamp();
325: myInstance.addToQueue(myLog);
326: } catch (DBException de) {
327: System.err.println(myName + ":Unable to log '" + msg
328: + "'");
329: de.printStackTrace(System.err);
330: }
331: } /* if we log this level */
332:
333: } /* log(int, String, String, String) */
334:
335: /**
336: * Log a message with the uid and job number recorded as well
337: *
338: * @param newLevel Level of this message
339: * @param objectName Calling object
340: * @param msg Message to log
341: * @param color Color to log the message
342: * @param uid User Name
343: * @param jobNumber Job Number
344: */
345: public static void log(int newLevel, String objectName, String msg,
346: String color, String uid, String jobNumber) {
347: log("default", "", newLevel, objectName, msg, color, uid,
348: jobNumber);
349: } /* log(int, String, String, String, String, String) */
350:
351: /**
352: * Log an exception
353: *
354: * @param e Exception to log
355: * @throws LogException If the log entry cannot be written
356: */
357: public static void log(Throwable e) throws LogException {
358: log("default", "", e);
359: } /* log(Throwable) */
360:
361: /**
362: * Log the given message at the level 0 (e.g. always log)
363: *
364: * @param msg Message to log
365: */
366: public static void log(String msg) {
367: log(0, msg);
368: } /* log(String) */
369:
370: /**
371: * Log an exception from a particular object
372: *
373: * @param objectName Calling object
374: * @param e Exception to log
375: */
376: public static void log(String objectName, Throwable e)
377: throws LogException {
378: log("default", objectName, e);
379: } /* log(String, Throwable) */
380:
381: /**
382: * Log the given message at level 0 from the named object
383: *
384: * @param objectName Calling object
385: * @param msg Message to log
386: * @throws LogException if the message cannot be logged
387: */
388: public static void log(String objectName, String msg)
389: throws LogException {
390: log(0, objectName, msg);
391: } /* log(String, String) */
392:
393: /**
394: * Log an exception from a particular object
395: *
396: * @param dbName
397: * @param channelName
398: * @param level
399: * @param objectName
400: * @param e
401: * @param color
402: * @param uid
403: * @param jobNumber
404: */
405: public static void log(String dbName, String channelName,
406: int level, String objectName, Throwable e, String color,
407: String uid, String jobNumber) throws LogException {
408: String myName = (this Class
409: + "log(String, String, int, String, Exception," + "String, String, String)");
410: String message = e.getMessage();
411:
412: if (e instanceof DBException) {
413: DBException de = (DBException) e;
414: message = de.getMessage() + ":" + de.getDBMessage();
415: }
416: if (trace) {
417: System.err.println(objectName + ":" + message);
418: e.printStackTrace(System.err);
419: }
420:
421: startUp();
422:
423: try {
424: LogEntry myLog = new LogEntry();
425: myLog.setDataContext(dbName);
426:
427: ByteArrayOutputStream bos = new ByteArrayOutputStream();
428: e.printStackTrace(new PrintStream(bos));
429: myLog.setField("MessageText", bos.toString());
430: myLog.setField("MessageColor", color);
431: myLog.setField("ObjectName", objectName);
432: myLog.setField("LogChannel", channelName);
433: myLog.setField("ExpUid", uid);
434: myLog.setField("JobNumber", jobNumber);
435: myLog.setTimeStamp();
436: myInstance.addToQueue(myLog);
437: } catch (DBException de) {
438: throw new LogException(myName + ":" + de.getMessage());
439: }
440: } /* log(String, String, int, String, Throwable, String, String, String) */
441:
442: /**
443: * Log a message with the uid and job number recorded as well
444: *
445: * @param dbName Database/config key name to use
446: * @param channelName of this logging "channel"
447: * @param newLevel Level of this message
448: * @param objectName Calling object
449: * @param msg Message to log
450: * @param color Color to log the message
451: * @param uid User Name
452: * @param jobNumber Job Number
453: */
454: public static void log(String dbName, String channelName,
455: int newLevel, String objectName, String msg, String color,
456: String uid, String jobNumber) {
457: String myName = (this Class + "log(String, String, int, " + "String, String, String, String, String)");
458:
459: if (newLevel <= maxLevel) {
460: if (trace) {
461: System.err.println(objectName + ":" + msg + ":" + uid
462: + ":" + jobNumber);
463: }
464:
465: startUp();
466:
467: try {
468: LogEntry myLog = new LogEntry();
469: myLog.setDataContext(dbName);
470: myLog.setField("ObjectName", objectName);
471: myLog.setField("MessageText", msg);
472: myLog.setField("MessageColor", encode(color));
473: myLog.setField("ExpUid", uid);
474: myLog.setField("JobNumber", jobNumber);
475: myLog.setField("MessageLevel", "" + newLevel);
476: myLog.setField("LogChannel", channelName);
477: myLog.setTimeStamp();
478: myInstance.addToQueue(myLog);
479: } catch (DBException de) {
480: System.err.println(myName + ":Unable to log '" + msg
481: + "'");
482: de.printStackTrace(System.err);
483: }
484: } /* if we log this level */
485:
486: } /* log(String, String, int, String, String, String, String, String) */
487:
488: /**
489: * Log an exception from a particular object
490: *
491: * @param dbName
492: * @param objectName Calling object
493: * @param e Exception to log
494: */
495: public static void log(String dbName, String objectName, Throwable e)
496: throws LogException {
497: String myName = (this Class + "log(String, Exception)");
498: String message = e.getMessage();
499:
500: if (e instanceof DBException) {
501: DBException de = (DBException) e;
502: message = de.getMessage() + ":" + de.getDBMessage();
503: }
504: if (trace) {
505: System.err.println(objectName + ":" + message);
506: e.printStackTrace(System.err);
507: }
508:
509: startUp();
510:
511: try {
512: LogEntry myLog = new LogEntry();
513: myLog.setDataContext(dbName);
514:
515: ByteArrayOutputStream bos = new ByteArrayOutputStream();
516: e.printStackTrace(new PrintStream(bos));
517: myLog.setField("MessageText", bos.toString());
518: myLog.setField("MessageColor", encode("RED"));
519: myLog.setField("ObjectName", objectName);
520: myLog.setTimeStamp();
521: myInstance.addToQueue(myLog);
522: } catch (DBException de) {
523: throw new LogException(myName + ":" + de.getMessage());
524: }
525: } /* log(String, String, Throwable) */
526:
527: /**
528: * Log the given message from an object at level 0
529: *
530: * @param objectName Calling object
531: * @param msg Message to log
532: * @param color Color to log the message with
533: */
534: public static void log(String objectName, String msg, String color) {
535: log(0, objectName, msg, color);
536: } /* log(String, String, String) */
537:
538: /**
539: * Log a message at level 0
540: *
541: * @param objectName Calling object
542: * @param msg Message to log
543: * @param color Color to log the message
544: * @param uid User Id
545: * @param jobNumber Job Number
546: */
547: public static void log(String objectName, String msg, String color,
548: String uid, String jobNumber) {
549: log(0, objectName, msg, color, uid, jobNumber);
550: } /* log(String, String, String, String, String) */
551:
552: /**
553: * Main thread process of the LogHandler process
554: */
555: public void run() {
556: super .run();
557: String myName = (this Class + "run()");
558:
559: try {
560: log.info(myName + " Log Handler starts");
561:
562: if (trace) {
563: System.err.println(myName + ":Log Handler starts");
564: }
565: while (true) {
566: if (idleTimes >= maxIdleTimes) {
567: if (trace) {
568: System.err.println(myName
569: + ":Log handler idle more than "
570: + maxIdleTimes
571: + " times - shutting down");
572: }
573:
574: return;
575: }
576: try {
577: checkQueue();
578: } catch (LogException ae) {
579: log.error(myName + "Unable to check log queue: "
580: + ae.getMessage());
581: }
582:
583: yield();
584: sleep(sleepTime * 1000);
585: } /* forever */
586:
587: } catch (InterruptedException ie) {
588: log.info(myName + ": LogHandler was interrupted:"
589: + ie.getMessage());
590: } catch (Throwable t) {
591: System.err.println("Test");
592: }
593: } /* run() */
594:
595: /**
596: * Set the max size that a log is allowed to reach before it is
597: * auto-archived to the old directory
598: *
599: * @param newMax Max size of the new log in records
600: */
601: public static void setMax(int newMax) {
602: if (newMax < 0) {
603: maxLevel = 0;
604: } else if (newMax > 9) {
605: maxLevel = 9;
606: } else {
607: maxLevel = newMax;
608: }
609: } /* setMax(int) */
610:
611: /**
612: * Sets whether the thread, when started will behave in daemon mode or not.
613: * If you're running test cases, you want it true so everything will exit
614: * properly. But in secure environments, some things might not get logged
615: * if you have daemonMode==true. So leave it at it's default of false.
616: */
617: public static void setDaemonMode(boolean newValue) {
618: daemonMode = newValue;
619: }
620:
621: /**
622: * This has been semi-deprecated since log4j has been added. Log4j now
623: * controls whether or not something is logged, not the db logging.
624: */
625: private static void setupLevels() {
626: maxLevel = 9;
627:
628: //MR String myName = (THIS_CLASS + "setupLevels()");
629: //MR try {
630: //MR String logLev = Setup.getValueRequired("default", "LogLevel");
631: //MR if (logLev.equals("")) {
632: //MR logLev = ("9");
633: //MR }
634: //MR try {
635: //MR setMax(new Integer(logLev).intValue());
636: //MR } catch(NumberFormatException ne) {
637: //MR System.err.println(myName + ":Log level '" + logLev
638: //MR + "' cannot be converted to a number");
639: //MR }
640: //MR } catch(DBException de) {
641: //MR throw new LogException(myName + ":Unable to read setup values", de);
642: //MR }
643: } /* setupLevel() */
644:
645: /**
646: *
647: *
648: */
649: public synchronized static void startUp() {
650: idleTimes = 0;
651:
652: boolean restart = false;
653:
654: if (myInstance == null) {
655: restart = true;
656: } else {
657: if (!myInstance.isAlive()) {
658: restart = true;
659: }
660: }
661: if (restart) {
662: setupLevels();
663: myInstance = new LogHandler();
664: myInstance.setDaemon(daemonMode);
665: myInstance.start();
666: }
667: } /* startUp() */
668:
669: /**
670: * Log a message at a given level with an objectname, message,
671: * and color. Does not throw exception if message cannot be logged
672: *
673: * @param newLevel
674: * @param objectName
675: * @param msg
676: * @param color
677: */
678: public static void tryLog(int newLevel, String objectName,
679: String msg, String color) {
680: log(newLevel, objectName, msg, color);
681: } /* tryLog(int, String, String, String) */
682:
683: /**
684: * Call to log that does not throw any exception, but writes to standard
685: * error if the message cannot be logged correctly
686: *
687: * @param objectName Name of the object logging the message
688: * @param e Exception being logged
689: */
690: public static void tryLog(String objectName, Exception e) {
691: String myName = (this Class + "tryLog(String, Exception)");
692: String message = e.getMessage();
693:
694: if (e instanceof DBException) {
695: DBException de = (DBException) e;
696: message = de.getMessage() + ":" + de.getDBMessage();
697: }
698: try {
699: startUp();
700: log(objectName, e);
701: } catch (LogException he) {
702: System.err.println(myName + ":Unable to log exception '"
703: + message + "' from object '" + objectName + "':"
704: + he.getMessage());
705: he.printStackTrace(System.err);
706: e.printStackTrace(System.err);
707: }
708: } /* tryLog(String, Exception) */
709:
710: /**
711: * Try to log the given message from the given object at level 0
712: * but don't throw an exception if it doesn't work
713: *
714: * @param objectName
715: * @param msg
716: */
717: public static void tryLog(String objectName, String msg) {
718: String myName = (this Class + "tryLog(String, String)");
719:
720: try {
721: log(objectName, msg);
722: } catch (LogException he) {
723: System.err.println(myName + ":Unable to log message '"
724: + msg + "' from object '" + objectName + "':"
725: + he.getMessage());
726: he.printStackTrace(System.err);
727: }
728: } /* tryLog(String, String) */
729:
730: /**
731: * Log a message at a given level with an objectname, message,
732: * and color. Does not throw exception if message cannot be logged
733: *
734: * @param dbName
735: * @param channelName
736: * @param newLevel
737: * @param objectName
738: * @param msg
739: * @param color
740: */
741: public static void tryLog(String dbName, String channelName,
742: int newLevel, String objectName, String msg, String color) {
743: log(dbName, channelName, newLevel, objectName, msg, color, "",
744: "");
745: } /* tryLog(String, String, int, String, String, String) */
746:
747: /**
748: * Log a message at a given level with an objectname, message,
749: * and color. Does not throw exception if message cannot be logged
750: *
751: * @param dbName
752: * @param channelName
753: * @param newLevel
754: * @param objectName
755: * @param msg
756: * @param color
757: * @param newUid
758: * @param newJobNumber
759: */
760: public static void tryLog(String dbName, String channelName,
761: int newLevel, String objectName, String msg, String color,
762: String newUid, String newJobNumber) {
763: log(dbName, channelName, newLevel, objectName, msg, color,
764: newUid, newJobNumber);
765: } /* tryLog(String, String, int, String, String, String, String, String) */
766:
767: /**
768: * Try to log a message at level 0 given the objectname, message, and
769: * color. No exception if unable to be logged.
770: *
771: * @param objectName
772: * @param msg
773: * @param color
774: */
775: public static void tryLog(String objectName, String msg,
776: String color) {
777: log(objectName, msg, color);
778: } /* tryLog(String, String, String) */
779:
780: /**
781: * Try to log a message given the object, message, color
782: * uid and job number. No exception if message cannot be logged
783: *
784: * @param objectName
785: * @param msg
786: * @param color
787: * @param uid
788: * @param jobNumber
789: */
790: public static void tryLog(String objectName, String msg,
791: String color, String uid, String jobNumber) {
792: log(objectName, msg, color, uid, jobNumber);
793: } /* tryLog(String, String, String, String, String) */
794:
795: } /* LogHandler */
|