Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: konspire/common/log/Log.java


1   package konspire.common.log;
2   
3   import java.util.*;
4   import java.text.*;
5   
6   
7   /**
8    * <code>Log</code> is the base class which defines 
9    * all of the logging constants and implements any 
10   * general logging responsibilities.  It dispatches the actual
11   * logging information over to a concrete subclass of 
12   * <code>AbstractLoggingMechanism</code> to do the work of writing
13   * out the log information. <p>
14   *
15   * This class could be extended to do application-specific behavior,
16   * or better yet you could create a class "wrapper" like <code>AppLog</code>
17   * to make instances well-known Singletons with handy static/class methods.
18   *
19   * @author Todd Lauinger
20   * @version $Revision: 1.3 $
21   *
22   * @see AbstractLoggingMechanism
23   * @see AppLog
24   */
25  public class Log {
26  
27      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28      // Constants section
29      
30    // The following constants are levels for logging an error,
31    // with the lowest number the most detailed
32    // (and least critical) and the highest number the least detailed
33    // (and most critical).
34  
35    /**
36     * Turns the log off, no messages are logged
37     */
38    public static final int DEACTIVATE_LEVEL = 0;
39  
40    /**
41     * The system encountered a critical error at this logging level, 
42     * which affects the accuracy, integrity, reliability, or 
43     * capability of the system.  Someone should be paged to address
44     * the error as soon as possible.
45     */
46    public static final int CRITICAL_ERROR_LEVEL = 1;
47  
48    /**
49     * The system encountered an unexpected error at this logging level, 
50     * which probably means the code intercepted an error it cannot handle.
51     * This error is not of a critical nature and can be recovered from
52     * automatically.
53     * Someone should probably be emailed to resolve the error in the near
54     * future to increase the reliability of the product.
55     */
56    public static final int ERROR_LEVEL = 2;
57  
58    /**
59     * The system encountered an expected error situation.  The system
60     * recovered from it but the fact that it happened should be recorded
61     * to see how frequent it happens.
62     */
63    public static final int WARNING_LEVEL = 3;
64  
65    /**
66     * Normal logging level.  All interesting periodic events should 
67     * be logged at this level so someone looking through the log can
68     * see the amount and kind of processing happening in the system.
69     */
70    public static final int INFO_LEVEL = 4;
71  
72    /**
73     * Moderately detailed logging level to be used to help debug
74     * typical problems in the system.  Not so detailed that the
75     * big picture gets lost.
76     */
77    public static final int DETAIL_LEVEL = 5;
78  
79    /**
80     * Most detailed logging level. Everything
81     * sent to the log will be logged.  Use this level to 
82     * trace system execution for really nasty problems.
83     */
84    public static final int TRACE_LEVEL = 6;
85  
86  
87    // The following constants define different output log mechanisms a log
88    // can accommodate.
89    
90    /**
91     * Logging mechanism to log all messages to System.err
92     */
93    public static final String STANDARD_ERR_MECHANISM = StandardErrLoggingMechanism.class.getName();
94  
95    /**
96     * Logging mechanism to log all messages to a unique file 
97     * specific to that <code>Log</code> instance.  Reuse the same
98     * log file name (append to it) if it already exists.
99     */
100   public static final String UNIQUE_FILE_MECHANISM = UniqueFileLoggingMechanism.class.getName();
101 
102   /**
103    * Logging mechanism to log all messages to a unique 
104    * file specific to that <code>Log</code> instance. Don't append
105    * to an existing log, instead create a new one with a date stamp.
106    */
107   public static final String UNIQUE_DATED_FILE_MECHANISM = UniqueDatedFileLoggingMechanism.class.getName();
108 
109   /**
110    * Logging mechanism to log all messages to a shared 
111    * file for any <code>Log</code> instances using this mechanism.
112    * Append to an existing log, if it already exists.
113    */
114   public static final String SHARED_FILE_MECHANISM = SharedFileLoggingMechanism.class.getName();
115 
116   /**
117    * Logging mechanism to log all messages to a shared file 
118    * for any <code>Log</code> instances using this mechanism.
119    * Don't append to an existing log, instead create a new one with a
120    * date stamp.
121    */
122   public static final String SHARED_DATED_FILE_MECHANISM = SharedDatedFileLoggingMechanism.class.getName();
123 
124     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
125     // Constructor section
126 
127   /**
128    * Class constructor to properly create and register a new log.  All other
129    * constructors and subclasses should eventually call this method!
130    */
131   protected Log() {
132 
133     // Add the new Log instance to LogManager
134     LogManager.getInstance().addElement(this);
135   }
136   
137   /**
138    * Public constructor to register a new log with a particular name.
139    * The name of the log is very important.  It is used as a key into
140    * the log properties file to find settings for how the log is to
141    * be opened.
142    */
143   public Log(String name) {
144       this();
145       this.name = name;
146       
147       // Get logging level and field separator from properties file
148       currentLoggingLevel = 
149           LogProperties.getInstance().getLoggingLevel(this);
150       logFieldSeparator = 
151           LogProperties.getInstance().getLogFieldSeparator(this);
152 
153         System.out.println("Initializing log named " + name + 
154             " at logging level " + currentLoggingLevel + 
155             " with separator " + logFieldSeparator);
156 
157       // Get a list of all of the mechanism names and open them
158       String mechanismName = null;
159       Enumeration e = LogProperties.getInstance().
160       getLoggingMechanismNames(this).elements();
161       while (e.hasMoreElements()) {
162           mechanismName = (String) e.nextElement();
163           addLoggingMechanism(mechanismName);
164       }
165           
166   }
167 
168 
169     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
170     // Instance Variable section
171   
172   /**
173    * Keeps the name of the Log instance.
174    */
175   protected String name = "Log";
176   
177   /**
178    * Keep the logging level the log is currently operating at.
179    */
180   protected int currentLoggingLevel;
181 
182   /**
183    * Keeps a collection of logging mechanisms to use when 
184    * writing out the log.
185    */
186   protected Vector loggingMechanisms = new Vector(10);
187 
188   /**
189    * Keeps the date the log opened
190    */
191   protected Date dateOpened = new Date();
192 
193 
194     /**
195      * Keeps a string demarking fields within the log file.
196      */
197     protected String logFieldSeparator = 
198         LogProperties.DEFAULT_LOG_FIELD_SEPARATOR;
199 
200     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
201     // Instance method section
202   
203   /**
204    * Gets the logging level of the current log.
205    */
206   public int getLoggingLevel() {
207 
208     return currentLoggingLevel;
209   }
210 
211   /**
212    * Changes the logging level of the current log.
213    *
214    * Use this method to activate, deactivate, or change the logging
215    * detail level of an active log.
216    */
217   synchronized public void setLoggingLevel(int newLoggingLevel) {
218 
219         AbstractLoggingMechanism currentLoggingMechanism = null;
220         
221     // See if we have to open or close the log
222     if (newLoggingLevel == Log.DEACTIVATE_LEVEL) {
223 
224       if (currentLoggingLevel != Log.DEACTIVATE_LEVEL) {
225 
226         // Must close the log.  
227         // Close/deregister with all logging mechanisms
228         for (Enumeration e = loggingMechanisms.elements();
229                 e.hasMoreElements(); ) {
230         
231             currentLoggingMechanism = (AbstractLoggingMechanism) 
232                                         e.nextElement();
233             currentLoggingMechanism.closeForLog(this);
234             }
235       }
236 
237     }  // Activating the log, see if we need to open it first
238     else if (currentLoggingLevel == Log.DEACTIVATE_LEVEL) {
239 
240       // Open/register with each logging mechanism
241       for (Enumeration e = loggingMechanisms.elements();
242               e.hasMoreElements(); ) {
243         
244           currentLoggingMechanism = (AbstractLoggingMechanism) 
245                                         e.nextElement();
246           currentLoggingMechanism.openForLog(this, newLoggingLevel);
247       }
248 
249       // Update dateOpened
250       dateOpened = new Date();
251         
252     }
253 
254     // Notify the log of the change if not deactivated
255     if ( (newLoggingLevel != Log.DEACTIVATE_LEVEL) &&
256             (currentLoggingLevel != Log.DEACTIVATE_LEVEL) )
257 
258       for (Enumeration e = loggingMechanisms.elements();
259               e.hasMoreElements(); ) {
260           currentLoggingMechanism = (AbstractLoggingMechanism) 
261                                         e.nextElement();
262           currentLoggingMechanism.notifyLoggingLevelChange(this, newLoggingLevel);
263           }
264 
265     // Set the new logging level
266     currentLoggingLevel = newLoggingLevel;
267     
268   }
269 
270   /**
271    * Returns a <code>Vector</code> of logging mechanisms 
272    * currently active for the log.
273    *
274    * @return a <code>Vector</code> of logging mechanisms 
275    *    currently active for the log.
276    */
277   public synchronized Vector getLoggingMechanisms() {
278       return this.loggingMechanisms;
279   }
280 
281   /**
282    * If a logging mechanism of the type input is in effect for this log, 
283    * return the logging mechanism instance matching the name given as
284    * input.
285    *
286    * @param loggingMechanismName  Name of the logging mechanism to search for,
287    *         one of the constants in the <code>Log</code> class.
288    *
289    * @return The concrete instance of an <code>AbstractLoggingMechanism</code>
290    *         that is currently in effect for the Log if one found, null if not.
291    */
292   public synchronized AbstractLoggingMechanism getLoggingMechanism(String loggingMechanismName) {
293 
294         AbstractLoggingMechanism currentLoggingMechanism = null;
295         
296     // Run through the loggingMechanisms vector to try and find
297     // the mechanism for the name provided.
298     for (Enumeration e = loggingMechanisms.elements();
299                 e.hasMoreElements(); ) {
300         
301         currentLoggingMechanism = (AbstractLoggingMechanism) 
302                                       e.nextElement();
303       if (currentLoggingMechanism.getName().equals(loggingMechanismName)) {
304           return currentLoggingMechanism;
305       }
306         }
307         
308         // Not found in the enumeration, return null
309         return null;
310   }
311 
312   /**
313    * Adds a Logging Mechanism to the list of mechanisms that this
314    * log writes to.  Opens the mechanism and registers it also.
315    *
316    * @param loggingMechanismName The name of the Logging Mechanism.
317    *
318    * @return The concrete instance of <code>AbstractLoggingMechanism</code>
319    *         that implements the mechanism just added, null if an error
320    *         occurred like the log could not be opened or that log was
321    *         previously opened!
322    */
323   public synchronized AbstractLoggingMechanism addLoggingMechanism(String loggingMechanismName) {
324 
325     AbstractLoggingMechanism newLoggingMechanism = null;
326 
327         System.out.println("  Adding log mechanism " + loggingMechanismName +
328             " to log " + this.getName());
329 
330 
331         // Try to find a duplicate.  If found, log an error.
332         if (getLoggingMechanism(loggingMechanismName) != null) {
333             System.err.println("Error: Tried to open an already open logging mechanism: " +
334                 loggingMechanismName);
335             System.err.println("Ignoring the call to re-open the logging mechanism");
336             return null;
337         }
338 
339     try {
340       newLoggingMechanism =
341         AbstractLoggingMechanism.getLoggingMechanismForString(loggingMechanismName);
342     } catch (Throwable e) {
343       System.err.println("Exception caught: " + e.getMessage());
344       System.err.println("Unable to open logging mechanism " +
345         loggingMechanismName + " for log " + this.getName());
346       return null;
347     }
348 
349         // Open the new mechanism and add it to the list of mechanisms currently logging to
350     newLoggingMechanism.openForLog(this, currentLoggingLevel);
351     loggingMechanisms.addElement(newLoggingMechanism);
352     return newLoggingMechanism;
353 
354   }
355 
356   /**
357    * Removes an active Logging Mechanism from the list of mechanisms that this
358    * log writes to.  Closes the mechanism and deregisters it also.
359    *
360    * @param loggingMechanismName The name of the Logging Mechanism to remove.
361    *
362    */
363   public synchronized void removeLoggingMechanism(String loggingMechanismName) {
364 
365     AbstractLoggingMechanism loggingMechanismToRemove = null;
366 
367         // Try to find the open mechanism.  If not found, log an error.
368         loggingMechanismToRemove = getLoggingMechanism(loggingMechanismName);
369         if (loggingMechanismToRemove == null) {
370             System.err.println("Error: Tried to close logging mechanism: " +
371                 loggingMechanismName + " which is not open");
372             System.err.println("Ignoring the call to close the logging mechanism");
373             return;
374         }
375 
376     loggingMechanismToRemove.closeForLog(this);
377     loggingMechanisms.removeElement(loggingMechanismToRemove);
378 
379   }
380 
381   /**
382    * Removes all Logging Mechanisms from the list of mechanisms that this
383    * log writes to.  Closes the mechanisms and deregisters them also.
384    *
385    */
386   public synchronized void removeAllLoggingMechanisms() {
387       
388         AbstractLoggingMechanism currentLoggingMechanism = null;
389         
390     // Run through the loggingMechanisms vector and close the mechanisms
391       for (Enumeration e = loggingMechanisms.elements();
392               e.hasMoreElements(); ) {
393           currentLoggingMechanism = (AbstractLoggingMechanism) 
394                                     e.nextElement();
395          currentLoggingMechanism.closeForLog(this);
396       }
397           
398       loggingMechanisms.removeAllElements();
399   }
400 
401   
402   /**
403    * Adds a message string to the log if the log's level is
404    * currently set at or above the loggingLevel passed in.
405    *
406    * @param logString The string to write to all logging mechanisms
407    *
408    * @param loggingLevel The level at which to log the string.
409    */
410   synchronized public void logString(String logString, int loggingLevel) {
411 
412     // Log the message if higher or equal to current logging level,
413     if (loggingLevel <= currentLoggingLevel) {
414         
415             AbstractLoggingMechanism currentLoggingMechanism = null;
416         
417         // Run through the loggingMechanisms vector and close the mechanisms
418           for (Enumeration e = loggingMechanisms.elements();
419               e.hasMoreElements(); ) {
420               currentLoggingMechanism = (AbstractLoggingMechanism) 
421                                         e.nextElement();
422           currentLoggingMechanism.logString(this, loggingLevel, logString);
423       }
424     }
425   }
426 
427   /**
428    * Must close the log for the application if the application did not or
429    * could not.
430    *
431    * @exception Throwable Default finalizer exception
432    */
433   protected void finalize() throws Throwable {
434 
435         // If the log file is open must address open mechanisms
436     if (isOpen()) {
437             removeAllLoggingMechanisms();
438       }
439       
440     super.finalize();
441   }
442   
443 
444   /**
445    * Gets the string that delimits the various fields of a log entry
446    */
447   public String getLogFieldSeparator() {
448 
449     return logFieldSeparator;
450   }
451 
452   /**
453    * Sets the string that delimits the various fields of a log entry
454    */
455   public void setLogFieldSeparator(String logFieldSeparator) {
456 
457     this.logFieldSeparator = logFieldSeparator;
458   }
459 
460   /**
461    * Return the name of the log, usually passed in by the constructor.
462    */
463   public String getName() {
464       return name;
465   }
466 
467   /**
468    * Return whether the log is open (is not deactivated).
469    */
470   public boolean isOpen() {
471 
472     return (currentLoggingLevel != Log.DEACTIVATE_LEVEL);
473   }
474 
475   /**
476    * Return the date the log was opened, only valid if the log is
477    * currently open.
478    */
479   public Date getDateOpened() {
480 
481     return dateOpened;
482   }
483   
484 }