001/* 002 * $Source: v:/cvsroot/open/projects/WebARTS/ca/bc/webarts/tools/Log.java,v $ 003 * $Revision: 1295 $ $Date: 2019-04-18 18:05:01 -0700 (Thu, 18 Apr 2019) $ $Locker: $ 004 * Copyright (C) 2001 WebARTS Design, 005 * North Vancouver Canada. All Rights Reserved. 006 * 007 * Written by Tom Gutwin - WebARTS Design. 008 * http://www..webarts.bc.ca 009 * 010 * This program is free software; you can redistribute it and/or modify 011 * it under the terms of the GNU General Public License as published by 012 * the Free Software Foundation; either version 2 of the License, or 013 * (at your option) any later version. 014 * 015 * This program is distributed in the hope that it will be useful, 016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 018 * GNU General Public License for more details. 019 * 020 * You should have received a copy of the GNU General Public License 021 * along with this program; if not, write to the Free Software 022 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 023 */ 024/* 025Here is the revision log 026------------------------ 027$Log: Log.java,v $ 028Revision 1.10 2002/04/04 23:04:26 anonymous 029Added a few extra null checks to ensure a Log gets created. 030 031Revision 1.9 2002/04/03 00:01:42 anonymous 032Another fix to the logLevel check. 033 034Revision 1.8 2002/04/02 23:31:36 anonymous 035Fixed the logLevel_ compare on the debug methods. 036 037Revision 1.7 2002/03/14 23:09:52 tgutwin 038 039Added/Updated Many Comments. 040Added set and get logLeve and LogLevelString. 041logEntry is now private. 042Added the checking for logLevel on log methods. 043 044Revision 1.6 2001/12/04 06:43:49 tgutwin 045 046Added a null check into the log entry method. 047 048Revision 1.5 2001/11/21 03:59:11 tgutwin 049 050Added a get instance() method that ssimply returns the log_. 051It is to be used when you don't want to create a log. 052 053Revision 1.4 2001/10/08 20:28:26 tgutwin 054 055Made the Log Static ( only one instance Used. Plus added an initial std out message as to where the log is going. 056 057Revision 1.3 2001/10/07 23:36:33 tgutwin 058 059Created a single Log Output stream that different sources are now mapped into. 060ie ... FileStream StdOut, or pip Stream. 061 062*/ 063 064package ca.bc.webarts.tools; 065 066import java.io.File; 067import java.io.FileOutputStream; 068import java.io.FileWriter; 069import java.io.IOException; 070import java.io.OutputStream; 071import java.io.PrintStream; 072import java.lang.Exception; 073import java.util.Calendar; 074import java.util.Stack; 075 076/** 077 * A Simple Log class that can be set to output to a file, the Console or any 078 * specified OutputStream. It provides a few simple log entry methods with 079 * method entry/exit tracking.<br />It is a Singleton so that all classes using it log to the same instance/OutputStream. 080 * Use one of the Log.createLog(...) methods to gat a handel to the current instance. 081 * 082 * @author Tom Gutwin P.Eng 083 * @created September 17, 2001 084 */ 085public class Log 086{ 087 private static boolean instantiated_ = false; 088 private static Log log_ = null; 089 /** 090 * Constant Specifying NO logging will occur. 091 */ 092 public final static short NONE = 0; 093 /** 094 * Constant Specifying minimal logging 095 * will occur (only Method entry and exit). 096 */ 097 public final static short QUIET = 1; 098 /** 099 * Constant Specifying only Major Log events logging will occur. 100 */ 101 public final static short MAJOR = 2; 102 /** 103 * Constant Specifying Major and Minor Log events logging will occur. 104 */ 105 public final static short MINOR = 3; 106 /** 107 * Constant Specifying Major Minor and Debug Log events logging will occur. 108 */ 109 public final static short DEBUG = 4; 110 /** 111 * Constant Specifying ALL log event logging will occur. 112 */ 113 public final static short FULL = 5; 114 115 /** 116 * Constant Specifying that the logging output will go to System.out. 117 */ 118 public final static short CONSOLE = 50; 119 /** 120 * Constant Specifying that the logging output will go to a spec'd file. 121 */ 122 public final static short FILE = 51; 123 /** 124 * Constant Specifying that the logging output will go to a 125 * spec'd OutputStream. 126 */ 127 public final static short PIPE = 52; 128 129 /** 130 * The Standard OutputStream goes to System.out. 131 */ 132 private final static PrintStream STD_OUT = System.out; 133 134 /** 135 * The name of the current log file. Default is logfile.txt. 136 */ 137 static private String logFileName_ = "logfile.txt"; 138 /** 139 * Class field that is used to pad the log messages based on the level of the method being logged. 140 */ 141 static private String msgSpacing_ = ""; 142 /** 143 * Class field used for the PIPed output stream being used. 144 */ 145 static private OutputStream userOut_ = STD_OUT; 146 /** 147 * The stream that ALL logging ends up getting directed to. 148 */ 149 static private PrintStream logOut_ = null; 150 /** 151 * Description of the Field 152 */ 153 static private File logFile_ = null; 154 /** 155 * Description of the Field 156 */ 157 static private FileWriter logFileWriter_ = null; 158 /** 159 * Description of the Field 160 */ 161 static private short logLevel_ = MAJOR; 162 /** 163 * Description of the Field 164 */ 165 static private short outSpot_ = CONSOLE; 166 /** 167 * Description of the Field 168 */ 169 static private Calendar calendar_ = Calendar.getInstance(); 170 171 /** 172 * A stack of the method call history. 173 */ 174 static private Stack currentMethod_ = new Stack(); 175 176 177 /** 178 * Default Constructor for the Log object. The ouput location is Console and 179 * the log level is Major. 180 */ 181 private Log() 182 { 183 outSpot_ = CONSOLE; 184 logLevel_ = MAJOR; 185 instantiated_ = true; 186 log_ = this; 187 initLogOut(); 188 } 189 190 191 /** 192 * Constructor for the Log object that sends the output to the Console at the 193 * specified Log Level. 194 * 195 * @param logLevel The desired Logging level (must be one of the Constants 196 * spec'd in this class). 197 */ 198 private Log(short logLevel) 199 { 200 outSpot_ = CONSOLE; 201 logLevel_ = logLevel; 202 instantiated_ = true; 203 log_ = this; 204 initLogOut(); 205 } 206 207 208 /** 209 * Constructor for the Log object that sends the output to an OutputStream 210 * Pipe at the specified Log Level. 211 * 212 * @param logLevel The desired Logging level (must be one of the Constants 213 * spec'd in this class). 214 * @param o The OutputStream to Pipe the logging to. 215 */ 216 private Log(short logLevel, OutputStream o) 217 { 218 outSpot_ = PIPE; 219 logLevel_ = logLevel; 220 userOut_ = o; 221 instantiated_ = true; 222 log_ = this; 223 initLogOut(); 224 } 225 226 227 /** 228 * Constructor for the Log object that sends the output to a File 229 * at the specified Log Level. 230 * 231 * @param logLevel The desired Logging level (must be one of the Constants 232 * spec'd in this class). 233 * @param logFile The File to send the Logging to. 234 */ 235 private Log(short logLevel, File logFile) 236 { 237 outSpot_ = FILE; 238 logLevel_ = logLevel; 239 if (!setLogFile(logFile)) 240 { 241 outSpot_ = CONSOLE; 242 initLogOut(); 243 System.out.println("Error Creating Logfile."); 244 } 245 else 246 { 247 instantiated_ = true; 248 log_ = this; 249 initLogOut(); 250 //System.out.println("Creating Log: "+logFileName_+" at level "+ 251 //getLogLevelString()); 252 } 253 } 254 255 256 /** 257 * Constructor for the Log object that sends the output to a File with the 258 * spec'd filename at the specified Log Level. 259 * 260 * @param logLevel The desired Logging level (must be one of the Constants 261 * spec'd in this class). 262 * @param logName The filename for the File to send Logging output to. 263 */ 264 private Log(short logLevel, String logName) 265 { 266 outSpot_ = FILE; 267 logLevel_ = logLevel; 268 269 if (!setLogFile(logName)) 270 { 271 outSpot_ = CONSOLE; 272 initLogOut(); 273 System.out.println("Error Creating Logfile."); 274 } 275 else 276 { 277 instantiated_ = true; 278 log_ = this; 279 initLogOut(); 280 //System.out.println("In Log(): Creating Log: "+logFileName_+" at level "+ 281 //getLogLevelString()); 282 } 283 } 284 285 286 /** 287 * Singleton method to get the log instance going to a File. 288 **/ 289 public static Log createLog(short logLevel, File logFile) 290 { 291 Log retVal = null; 292 if (instantiated_ && log_ != null) 293 { 294 retVal = log_; 295 } 296 else 297 { 298 retVal = new Log(logLevel, logFile); 299 log_ = retVal; 300 logEntry("Log.createLog", "Creating Log: "+logFileName_+" at level "+ 301 getLogLevelString()); 302//System.out.println("Log.createLog(short logLevel, File): File="+logFile.toString()); 303 } 304 return retVal; 305 } 306 307 308 /** 309 * Singleton method to get the log instance going to an OutputStream. 310 **/ 311 public static Log createLog(short logLevel, OutputStream stream) 312 { 313 Log retVal = null; 314 if (instantiated_ && log_ != null) 315 { 316 retVal = log_; 317 } 318 else 319 { 320 retVal = new Log(logLevel, stream); 321 log_ = retVal; 322 logEntry("Log.createLog", "Creating Log: "+logFileName_+" at level "+ 323 getLogLevelString()); 324//System.out.println("Log.createLog(short logLevel, OutputStream): OutputStream="+stream); 325 } 326 return retVal; 327 } 328 329 330 /** 331 * Singleton method to get the log instance going to a File. 332 **/ 333 public static Log createLog(short logLevel, String fName) 334 { 335 //System.out.println("Into createLog"); 336 //System.out.println("instantiated_: "+instantiated_); 337 //System.out.println("log_ != null: "+(log_ != null)); 338 Log retVal = null; 339 if (instantiated_ && log_ != null) 340 retVal = log_; 341 else 342 { 343 retVal = new Log(logLevel, fName); 344 log_ = retVal; 345 logEntry("Log.createLog", "Creating Log: "+fName+" at level "+ 346 getLogLevelString()); 347 //System.out.println("Creating Log: "+fName+" at level "+ 348 //getLogLevelString()); 349 } 350 return retVal; 351 } 352 353 354 /** 355 * Singleton method to get the log instance going to stdout. 356 **/ 357 public static Log createLog(short logLevel) 358 { 359 Log retVal = null; 360 if (instantiated_ && log_ != null) 361 retVal = log_; 362 else 363 { 364 retVal = new Log(logLevel); 365 log_ = retVal; 366 logEntry("Log.createLog", "Creating Log: "+logFileName_+" at level "+ 367 getLogLevelString()); 368//System.out.println("Log.createLog(short logLevel)"); 369 } 370 return retVal; 371 } 372 373 /** 374 * Singleton method to get the log instance NULL if not init 375 * yet with a createLog call. 376 **/ 377 public static Log getInstance() 378 { 379 if (log_!=null) 380 return log_; 381 else 382 return createLog(MAJOR); 383 } 384 385 386 public static synchronized boolean alreadyInstantiated() 387 { 388 return instantiated_; 389 } 390 391 392 /** 393 * Sets the current Logging Level. 394 * 395 * @return true if it was set false if NOT set due to level out out bounds. 396 **/ 397 public static synchronized boolean setLogLevel(short level) 398 { 399 boolean retVal = false; 400 if (level >= NONE && level <= FULL) 401 { 402 retVal = true; 403 logLevel_ = level; 404 } 405 return retVal; 406 } 407 408 409 public static short getLogLevel() 410 { 411 return logLevel_; 412 } 413 414 415 public static String getLogLevelString() 416 { 417 String retVal = ""; 418 switch (logLevel_) 419 { 420 case NONE: 421 retVal="NONE"; 422 break; 423 case QUIET: 424 retVal="QUIET"; 425 break; 426 case MAJOR: 427 retVal="MAJOR"; 428 break; 429 case MINOR: 430 retVal="MINOR"; 431 break; 432 case DEBUG: 433 retVal="DEBUG"; 434 break; 435 case FULL: 436 retVal="FULL"; 437 break; 438 } 439 return retVal; 440 } 441 442 443 /** 444 * Creates a File object based on the spec'd filename and then inits the 445 * logFile_ attribute. 446 * 447 * @param fName The filename to use for the new logFile_. 448 * @return true if successfully created and init. 449 */ 450 static public boolean setLogFile(String fName) 451 { 452 boolean retVal = true; 453 String newFname = ""; 454 String tempStr = ""; 455 for (int i = 0; i < fName.length(); i++) 456 { 457 tempStr = String.valueOf(fName.charAt(i)); 458 if (!(" ".equals(tempStr)) && !(":".equals(tempStr))) 459 { 460 newFname += tempStr; 461 } 462 else 463 { 464 newFname += "_"; 465 } 466 } 467 try 468 { 469 logFile_ = new File(newFname); 470 logFileName_ = newFname; 471 } 472 catch (NullPointerException nullEx) 473 { 474 STD_OUT.println("Error Creating Logfile1: \n " + nullEx.getMessage()); 475 retVal = false; 476 } 477 478 return retVal; 479 } 480 481 482 /** 483 * Sets the logFile_ attribute to the spec'd File. 484 * 485 * @param logFile The File object to setr to the logFile_. 486 * @return true if successfully init. 487 */ 488 static public boolean setLogFile(File logFile) 489 { 490 boolean retVal = true; 491 492 if (logFile != null && logFile.exists() && logFile.canRead()) 493 { 494 logFile_ = logFile; 495 logFileName_ = logFile.getName(); 496 } 497 else 498 { 499 STD_OUT.println("Error Creating Logfile from Specified FILE. "); 500 retVal = false; 501 } 502 503 return retVal; 504 } 505 506 507 /** 508 * Creates a timestamp for the current time in the form of 509 * 'hour + "-" + min + "-" + sec + "-" + millis'. 510 * 511 * @return The CurrentTimeStamp value. 512 */ 513 static public String createCurrentTimeStamp() 514 { 515 String value = ""; 516 calendar_ = Calendar.getInstance(); 517 int currMillis = calendar_.get(calendar_.MILLISECOND); 518 String millis = String.valueOf(currMillis); 519 if (currMillis < 10) 520 { 521 millis = "00" + currMillis; 522 } 523 else if (currMillis < 100) 524 { 525 millis = "0" + currMillis; 526 } 527 int currSec = calendar_.get(calendar_.SECOND); 528 String sec = String.valueOf(currSec); 529 if (currSec < 10) 530 { 531 sec = "0" + currSec; 532 } 533 int currMin = calendar_.get(calendar_.MINUTE); 534 String min = String.valueOf(currMin); 535 if (currMin < 10) 536 { 537 min = "0" + currMin; 538 } 539 int currHr = calendar_.get(calendar_.HOUR); 540 String hour = String.valueOf(currHr); 541 if (currHr < 10) 542 { 543 hour = "0" + currHr; 544 } 545 546 return (String)hour + "-" + min + "-" + sec + "-" + millis; 547 } 548 549 550 /** 551 * Cleanup method that closes any open Files. 552 */ 553 static public void close() 554 { 555 try 556 { 557 if (logFileWriter_ != null) 558 { 559 STD_OUT.println("Closing Logfile: " + logFile_.getAbsolutePath()); 560 logFileWriter_.close(); 561 } 562 } 563 catch (IOException ioEx) 564 { 565 STD_OUT.println("Error Closing Logfile: \n " + ioEx.getMessage()); 566 } 567 } 568 569 570 /** 571 * Generic uncategorized log entry. 572 * 573 * @param value The String to dump into the Log. 574 */ 575 static private void logEntry(String value) 576 { 577 if (logOut_ != null && msgSpacing_!=null && !msgSpacing_.equals("") ) 578 { 579 value = createCurrentTimeStamp() + ":" + msgSpacing_ + value; 580 581 /* if (outSpot_ == FILE) 582 { 583 value += "\n"; 584 } 585 */ 586 logOut_.println(value); 587 } 588 } 589 590 591 /** 592 * Generic uncategorized log entry. 593 * 594 * @param value The String to dump into the Log. 595 */ 596 static private void logEntry(String value, Exception ex) 597 { 598 if (logOut_ != null && msgSpacing_!=null && !msgSpacing_.equals("") ) 599 { 600 value = createCurrentTimeStamp() + ":"+logLevel_ +" "+ msgSpacing_ + value; 601 602 /* if (outSpot_ == FILE) 603 { 604 value += "\n"; 605 } 606 */ 607 logOut_.println(value); 608 ex.printStackTrace(logOut_); 609 } 610 } 611 612 613 /** 614 * A log entry method 615 * 616 * @param methodName Description of Parameter 617 * @param value The String to dump into the Log. 618 */ 619 static private void logEntry(String methodName, String value) 620 { 621 logEntry(value); 622 } 623 624 625 /** 626 * Returns the calling classes name by going through the Stacktrace. 627 @return the calling methods name. 628 */ 629 public static String findCurrentClassName() 630 { 631 Throwable t = new Throwable(); 632 StackTraceElement[] es = t.getStackTrace(); 633 StackTraceElement e = es[2]; 634 return e.getClassName(); 635 //return e.getLineNumber(); 636 //return e.getMethodName(); 637 } 638 639 640 /** 641 * Returns the calling methods name by going through the Stacktrace. 642 @return the calling methods name. 643 */ 644 public static String findCurrentMethodName() 645 { 646 Throwable t = new Throwable(); 647 StackTraceElement[] es = t.getStackTrace(); 648 StackTraceElement e = es[2]; 649 //return e.getClassName(); 650 //return e.getLineNumber(); 651 return e.getMethodName(); 652 } 653 654 655 /** 656 * Generic uncategorized log entry. 657 * 658 * @param value The String to dump into the Log. 659 */ 660 static private String getCurrentMethodName() 661 { 662 String retVal = "!"; 663 if (!currentMethod_.empty()) 664 { 665 retVal = (String) currentMethod_.peek(); 666 } 667 return retVal; 668 } 669 670 671 /** 672 * Logs an entry into a method with a simple log message. It also keeps 673 * track of the entry so it can manage tabbing/spacing of log entries. 674 * 675 * @param methodName The method being entered. 676 */ 677 static public void startMethod() { startMethod(findCurrentClassName()+"."+findCurrentMethodName());} 678 /** 679 * Logs an entry into a method with a simple log message. It also keeps 680 * track of the entry so it can manage tabbing/spacing of log entries. 681 * 682 * @param methodName The method being entered. 683 */ 684 static public void startMethod(String methodName) 685 { 686 if (logLevel_>=DEBUG) 687 { 688 currentMethod_.push(methodName); 689 logEntry("Entering: " + methodName); 690 msgSpacing_ += " "; 691 } 692 } 693 694 695 /** 696 * Logs the exit from a method with a simple log message. It also keeps 697 * track of the exit so it can manage tabbing/spacing of log entries. 698 * 699 * @param methodName The method being exited. 700 */ 701 static public void endMethod(String methodName) 702 { 703 if (logLevel_>=DEBUG) 704 { 705 if (currentMethod_.size() > 0) 706 { 707 currentMethod_.pop(); 708 if (msgSpacing_.length() > 1) 709 { 710 msgSpacing_ = msgSpacing_.substring(0, msgSpacing_.length() - 2); 711 } 712 } 713 logEntry("Exiting : " + methodName); 714 } 715 } 716 717 718 /** 719 * Logs the exit from the last entered method with a simple log message. 720 * It also keeps track of the exit so it can manage tabbing/spacing 721 * of log entries. 722 */ 723 static public void endMethod() 724 { 725 if (logLevel_>=DEBUG) 726 { 727 if (msgSpacing_.length() > 1) 728 { 729 msgSpacing_ = msgSpacing_.substring(0, msgSpacing_.length() - 2); 730 } 731 if (currentMethod_.size() > 0) 732 logEntry("Exiting : " + currentMethod_.pop()); 733 else 734 logEntry("Exiting : " ); 735 } 736 } 737 738 739 /** 740 * Logs a Major Log event with the spec'd method name prefix. 741 * 742 * @param methodName The methodname to prefix the log message with. 743 * @param value The String to dump into the Log. 744 */ 745 static public void major(String methodName, String value) 746 { 747 if (logLevel_>=MAJOR) 748 logEntry("Major: " + methodName + ": " + value); 749 } 750 751 752 /** 753 * Logs a Minor level message prefixed with the spec'd methodname. 754 * 755 * @param methodName The methodname to prefix the log message with. 756 * @param value The String to dump into the Log. 757 */ 758 static public void minor(String methodName, String value) 759 { 760 if (logLevel_>=MINOR) 761 logEntry("Minor: " + methodName + ": " + value); 762 } 763 764 765 /** 766 * Logs a Debug level message prefixed with the spec'd methodname. 767 * 768 * @param methodName The methodname to prefix the log message with. 769 * @param value The String to dump into the Log. 770 */ 771 static public void debug(String methodName, String value) 772 { 773 if (logLevel_>=DEBUG) 774 logEntry("--> Debug: " + methodName + ": " + value); 775 } 776 777 778 /** 779 * Logs a Debug level message prefixed with the current methodname. 780 * 781 * @param value The String to dump into the Log. 782 */ 783 static public void debug(String value) 784 { 785 if (logLevel_>=DEBUG) 786 logEntry("--> Debug: " + getCurrentMethodName() + ": " + value); 787 } 788 789 790 /** 791 * Logs a Major level message prefixed with the current methodname. 792 * 793 * @param value The String to dump into the Log. 794 */ 795 static public void major(String value) 796 { 797 if (logLevel_>=MAJOR) 798 logEntry("Major: " + getCurrentMethodName() + ": " + value); 799 } 800 801 802 /** 803 * Logs a Major level message prefixed with the current methodname. 804 * 805 * @param value The String to dump into the Log. 806 * @param ex An exception that will dump its stacktrace into the log. 807 */ 808 static public void major(String value, Exception ex) 809 { 810 if (logLevel_>=MAJOR) 811 logEntry("Major: " + getCurrentMethodName() + ": " + value, ex); 812 } 813 814 815 /** 816 * Logs a minor level message prefixed with the current methodname. 817 * 818 * @param value The String to dump into the Log. 819 */ 820 static public void minor(String value) 821 { 822 if (logLevel_>=MINOR) 823 logEntry("Minor: " + getCurrentMethodName() + ": " + value); 824 } 825 826 827 /** 828 * Logs a minor level message prefixed with the current methodname. 829 * 830 * @param value The String to dump into the Log. 831 * @param ex An exception that will dump its stacktrace into the log. 832 */ 833 static public void minor(String value, Exception ex) 834 { 835 if (logLevel_>=MINOR) 836 logEntry("Minor: " + getCurrentMethodName() + ": " + value, ex); 837 } 838 839 840 /** 841 * Initializes the logOut_ Stream based on the outSpot specifired by the user. 842 */ 843 static private void initLogOut() 844 { 845 switch (outSpot_) 846 { 847 case FILE: 848 if (logFile_ != null) 849 { 850 try 851 { 852 logOut_ = new PrintStream(new FileOutputStream(logFile_), true); 853 } 854 catch (IOException ioEx) 855 { 856 STD_OUT.println("Error Creating Logfile:\n " + ioEx.getMessage()); 857 outSpot_ = CONSOLE; 858 initLogOut(); 859 } 860 } 861 else 862 { 863 outSpot_ = CONSOLE; 864 initLogOut(); 865 } 866 break; 867 case PIPE: 868 logOut_ = new PrintStream(userOut_, true); 869 break; 870 default: // default is CONSOLE 871 logOut_ = new PrintStream(STD_OUT, true); 872 } 873 } 874} 875