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

Quick Search    Search Deep

Source code: com/flexstor/common/util/Diagnostic.java


1   /*
2    * Diagnostic.java
3    *
4    * Copyright $Date: 2003/08/11 02:22:31 $ FLEXSTOR.net Inc.
5    *
6    * This work is licensed for use and distribution under license terms found at
7    * http://www.flexstor.org/license.html
8    *
9    */
10  
11  package com.flexstor.common.util;
12  
13  import java.io.FileOutputStream;
14  import java.io.FileWriter;
15  import java.io.IOException;
16  import java.io.PrintStream;
17  import java.io.PrintWriter;
18  import java.text.SimpleDateFormat;
19  import java.util.Date;
20  import java.util.Enumeration;
21  import java.util.Hashtable;
22  
23  import com.flexstor.common.settings.ObjectHolder;
24  import com.flexstor.common.settings.Settings;
25  
26  /**
27   * Revision 1.8 2000-09-28 : 22:51:00 Visesh
28   * Removed constructors particular to DiagnosticCategory when it was in the hiearchy
29   *
30   * Diagnostic is a utility class for tracing and debugging. It is not intended
31   * for error and exception handling. It provides methods to print, trace, and warn
32   * and also to check for conditions. One or more output streams can be registered
33   * so that output can be saved in a file and shown on the console simultaneously.<P>
34   * Diagnostic.initialize(section name) must be called to read properties from the 
35   * 'diagnostic.properties' file. Different section can be defined with different 
36   * properties, e.g. for different applications.<P>
37   * These are the available properties <BR><UL>
38   * <LI>traceDir               - Directory for output files. If omitted, an output file will not be created.
39   * <LI>traceFile              - File name. If omitted, a unique file name will be generated.
40   *                              This file will be added as an output device.
41   * <LI>traceLevel             - Global trace level, used for warnings and traces based on level or if a
42   *                              category trace level has not been specified.
43   * <LI>redirectOutput         - true or false. Indicates if System.out/err are to be redirected to above file.
44   *                              If traceDir is not specified, redirection is disabled.
45   * <LI>output                 - true or false. Indicates if output is turned on. If false and
46   *                              traceDir is not specified, however, System.out will still be output to the console.
47   * <LI>printTimeStamp         - true or false. Indicates if each line will be printed with date/time.
48   *                              The format can be specified with the timeFormat property, see below.
49   * <LI>printThreadId          - true or false. Indicates if each line will be printed with the thread id.
50   * <LI>outputToConsole        - true or false. Indicates if output to System.out is turned on. This
51   *                              will always print to the console, even if redirection is enabled.
52   * <LI>checking               - true or false. Enables/disables cheching for check and precondition.
53   * <LI>category.name.         - prefix for categories
54   * <LI>category.traceLevel.   - prefix for category trace levels
55   * <LI>category.generateFile. - true or false. Prefix for category file indicator. If set to true, 
56   *                              a separate output file will be created for the category.
57   * <LI>timeFormat             - format string (default: "yyyy-MM-dd kk:mm:ss:SSS"), 
58   *                              defined as follows:
59   * </UL><P>
60   * Time Format Syntax: <BR>
61   * To specify the time format use a time pattern string. In this pattern, all ASCII 
62   * letters are reserved as pattern letters, which are defined as the following: 
63   * <pre>
64   * 
65   * Symbol   Meaning                 Presentation        Example
66   *  ------   -------                 ------------        -------
67   *  G        era designator          (Text)              AD
68   *  y        year                    (Number)            1996
69   *  M        month in year           (Text & Number)     July & 07
70   *  d        day in month            (Number)            10
71   *  h        hour in am/pm (1~12)    (Number)            12
72   *  H        hour in day (0~23)      (Number)            0
73   *  m        minute in hour          (Number)            30
74   *  s        second in minute        (Number)            55
75   *  S        millisecond             (Number)            978
76   *  E        day in week             (Text)              Tuesday
77   *  D        day in year             (Number)            189
78   *  F        day of week in month    (Number)            2 (2nd Wed in July)
79   *  w        week in year            (Number)            27
80   *  W        week in month           (Number)            2
81   *  a        am/pm marker            (Text)              PM
82   *  k        hour in day (1~24)      (Number)            24
83   *  K        hour in am/pm (0~11)    (Number)            0
84   *  z        time zone               (Text)              Pacific Standard Time
85   *  '        escape for text         (Delimiter)
86   *  ''       single quote            (Literal)           '
87   * </pre> 
88   * 
89   * The count of pattern letters determine the format. 
90   * (Text): 4 or more pattern letters--use full form, < 4--use short or abbreviated form if one exists. 
91   * (Number): the minimum number of digits. Shorter numbers are zero-padded to this amount. Year is handled specially; that is, if the count of 'y' is 2, the Year will be truncated to 2 digits. 
92   * (Text & Number): 3 or over, use text, otherwise use number. 
93   * Any characters in the pattern that are not in the ranges of ['a'..'z'] and ['A'..'Z'] will be treated as quoted text. For instance, characters like ':', '.', ' ', '#' and '@' will appear in the resulting time text even they are not embraced within single quotes. 
94   * 
95   * A pattern containing any invalid pattern letter will result in a thrown exception during formatting or parsing. 
96   * Examples Using the US Locale: 
97   * 
98   * <pre> 
99   * Format Pattern                         Result
100  *  --------------                         -------
101  *  "yyyy.MM.dd G 'at' hh:mm:ss z"    ->>  1996.07.10 AD at 15:08:56 PDT
102  *  "EEE, MMM d, ''yy"                ->>  Wed, July 10, '96
103  *  "h:mm a"                          ->>  12:08 PM
104  *  "hh 'o''clock' a, zzzz"           ->>  12 o'clock PM, Pacific Daylight Time
105  *  "K:mm a, z"                       ->>  0:00 PM, PST
106  *  "yyyyy.MMMMM.dd GGG hh:mm aaa"    ->>  1996.July.10 AD 12:08 PM
107  * </pre> 
108  *   
109  * <P>
110  * Categories must be defined in DiagnosticCategoryI. <P>
111  * Categories must start with the prefix 'category.name.', the trace level for each
112  * category has a prefix of 'category.traceLevel.' with the category name following.<P>
113  * A sample diagnostic section in 'diagnostic.properties'. This file is to be expected 
114  * in the conf directory.
115  * <pre>
116  * 
117  *    [client]
118  *    output=true
119  *    printTimeStamp=true
120  *    printThreadId=true
121  *    timeFormat=dd-kk:mm:ss:SSS
122  *    outputToConsole=true
123  *    redirectOutput=true
124  *    traceDir=d:\fsdb\debug\
125  *    traceFile=diagnostic.txt
126  *    checking=true
127  *    traceLevel=10
128  *    category.name.Send=Send
129  *    category.traceLevel.Send=5
130  * 
131  *
132  *    Test Run Output: (*** indicates the code executing)
133  *    
134  * 21-12:36:49:482 | main | Current test settings:
135  * 21-12:36:49:492 | main | Number of output devices:2
136  * 21-12:36:49:502 | main | Default time stamp=1999-04-21 12:36:49:492
137  * 21-12:36:49:502 | main | Current time stamp=21-12:36:49:502
138  * 21-12:36:49:502 | main | TraceLevel=10
139  * 21-12:36:49:512 | main | Checking=true
140  * 21-12:36:49:522 | main | ThreadId=main
141  * 21-12:36:49:522 | main | Categories:
142  * 21-12:36:49:532 | main | Process
143  * 21-12:36:49:532 | main | Send
144  * 21-12:36:49:532 | main | 
145  * 21-12:36:49:532 | main | Test begin
146  * 21-12:36:49:662 | 1 | *** Diagnostic.trace(1, "Trace for level 1")
147  * 21-12:36:49:662 | 1 | [1]  Trace for level 1
148  * 21-12:36:49:662 | 1 | *** Diagnostic.trace(3, "Trace for level 3")
149  * 21-12:36:49:672 | 1 | [3]      Trace for level 3
150  * 21-12:36:49:672 | 1 | *** Diagnostic.trace(5, "Trace for level 5")
151  * 21-12:36:49:682 | 1 | [5]          Trace for level 5
152  * 21-12:36:49:682 | 1 | *** Diagnostic.trace(Diagnostic.CAT_ARCHIVE, "Trace for category Archive")
153  * 21-12:36:49:682 | 1 | *** Diagnostic.trace(Diagnostic.CAT_SEND, "Trace for category Send")
154  * 21-12:36:49:692 | 1 | [Send] Trace for category Send
155  * 21-12:36:49:692 | 1 | *** Diagnostic.precondition((5 < 9), "Precondition 5 < 9")
156  * 21-12:36:49:702 | 1 | *** Diagnostic.precondition((5 > 9), "Precondition 5 > 9")
157  * 21-12:36:49:702 | 1 | Precondition failed: Precondition 5 > 9
158  * 21-12:36:49:792 | 1 | com.flexstor.common.util.DiagnosticPreconditionException: Precondition 5 > 9
159  * 21-12:36:49:792 | 1 |   at com.flexstor.common.util.Diagnostic.precondition(Diagnostic.java:359)
160  * 21-12:36:49:792 | 1 |   at com.flexstor.common.util.Diagnostic$TestThread.run(Diagnostic.java:1019)
161  * 21-12:36:49:852 | 1 | *** Diagnostic.warn(2, true, "Warning level 2, condition true")
162  * 21-12:36:49:852 | 1 | wn[2]     Warning level 2, condition true
163  * 21-12:36:49:852 | 1 | *** Diagnostic.warn(2, false, "Warning level 2, condition false")
164  * 21-12:36:49:852 | 1 | *** Diagnostic.warn(5, true, "Warning level 5, condition true")
165  * 21-12:36:49:862 | 1 | wn[5]           Warning level 5, condition true
166  * 21-12:36:49:862 | 1 | *** Diagnostic.warn(Diagnostic.CAT_SEND, "Warning category 'Send'")
167  * 21-12:36:49:862 | 1 | wn[Send] Warning category 'Send'
168  * 21-12:36:49:872 | 1 | *** Diagnostic.warn(Diagnostic.CAT_ARCHIVE, "Warning for category 'Archive'")
169  * 21-12:36:49:872 | 1 | *** Diagnostic.needException()
170  * 21-12:36:49:872 | 1 | Check failed: Need Exception
171  * 21-12:36:49:882 | 1 | *** Diagnostic.fail(new Exception("Failing"))
172  * 21-12:36:49:882 | 1 | Failing
173  * 21-12:36:49:892 | 1 | java.lang.Exception: Failing
174  * 21-12:36:49:892 | 1 |   at com.flexstor.common.util.Diagnostic$TestThread.run(Diagnostic.java:1034)
175  * 21-12:36:49:892 | 1 | *** Diagnostic.printStackTrace()
176  * 21-12:36:49:932 | 1 | java.lang.Exception: Diagnostic Stack Trace
177  * 21-12:36:49:932 | 1 |   at com.flexstor.common.util.Diagnostic.printStackTrace(Diagnostic.java:539)
178  * 21-12:36:49:932 | 1 |   at com.flexstor.common.util.Diagnostic$TestThread.run(Diagnostic.java:1037)
179  * 21-12:36:49:942 | 1 | *** Diagnostic.printStackTrace(Diagnostic.CAT_SEND, 5, new Exception())
180  * 21-12:36:49:952 | 1 | java.lang.Exception
181  * 21-12:36:49:952 | 1 |   at com.flexstor.common.util.Diagnostic$TestThread.run(Diagnostic.java:1039)
182  * 21-12:36:49:952 | 1 | *** Test completed
183  * </pre>
184  *
185  * @see com.flexstor.common.util.DiagnosticCategoryI
186  */
187 public class Diagnostic
188    extends DiagnosticBase
189 {
190    private static final String DIAGNOSTIC_PROPERTIES_FILE   = "diagnostic.properties";
191    private static final String DIAGNOSTIC_TRACE_DIR         = "traceDir";
192    private static final String DIAGNOSTIC_TRACE_FILE        = "traceFile";
193    private static final String DIAGNOSTIC_TRACE_LEVEL       = "traceLevel";
194    private static final String DIAGNOSTIC_REDIR_OUTPUT      = "redirectOutput";
195    private static final String DIAGNOSTIC_OUTPUT_ENABLED    = "output";
196    private static final String DIAGNOSTIC_PRINT_TIME        = "printTimeStamp";
197    private static final String DIAGNOSTIC_TIME_FORMAT       = "timeFormat";
198    private static final String DIAGNOSTIC_PRINT_THREADID    = "printThreadId";
199    private static final String DIAGNOSTIC_OUTPUT_CONSOLE    = "outputToConsole";
200    private static final String DIAGNOSTIC_CHECKING_ENABLED  = "checking";
201    private static final String DIAGNOSTIC_CATEGORY_PREFIX   = "category.name.";
202    private static final String DIAGNOSTIC_CATEGORY_LEVEL    = "category.traceLevel.";
203    private static final String DIAGNOSTIC_CATEGORY_FILE     = "category.generateFile.";
204 
205    private static Diagnostic  instance;
206   
207   //No longer needed after removing circular dependencies 
208   /*   public Diagnostic() { super(); }
209    
210     public Diagnostic(String name)
211     {
212         super(name);
213     }*/
214 
215    /**
216     * Initializes Diagnostic by reading a section from the diagnostic.properties file
217     * and adding an instance to ObjectHolder to prevent garbage collection.
218     * @param sSectionName the section to load 
219     */
220    public static void initialize(String sSectionName)
221    {
222       if (instance == null)
223       {
224          ObjectHolder.add(instance = new Diagnostic());
225       }
226       getProperties(sSectionName);
227    }
228    
229   /**
230    * Gets the properties from the properties file. Uses an PropertyMapper to read
231    * the file.
232    * @param sDiagnosticSection the section name to use for configuration
233    * @see com.flexstor.common.util.PropertyMapper
234    */
235    private static void getProperties(String sDiagnosticSection)
236    {
237       if ( !bPropertiesLoaded )
238       {
239          PropertyMapper mapper = new PropertyMapper();
240          Hashtable properties = null;
241          String   dirName = Settings.getString(Settings.CONFIG_DIRECTORY);
242          String[] saKeys;
243          String   sTraceFile = "";     // name only, from properties or generated
244          String   sTraceDir = "";      // directory of trace file from properties
245          String   sFullTracePath= "";  // absolute path to trace file
246          String   traceLevelValue;
247          String   checkStatusValue;
248          DiagnosticCategory category;
249          String   traceKey;
250          String   categoryLevel;
251          PrintStream outStream = null;  // for System.out redirection
252          boolean  bRedirectOutput = false;
253          
254          try
255          {
256             mapper.readInputFile( dirName + DIAGNOSTIC_PROPERTIES_FILE );
257             properties = mapper.getSection(sDiagnosticSection);
258             saKeys     = mapper.getProperties( sDiagnosticSection );
259             
260             // try to get the output status flag
261             checkStatusValue = (String)properties.get(DIAGNOSTIC_OUTPUT_ENABLED);
262             if (checkStatusValue != null 
263             &&  checkStatusValue.toLowerCase().equals("true"))
264                bOutput = true;
265             else
266                bOutput = false;
267 
268             // check if redirection is enabled
269             checkStatusValue = (String)properties.get(DIAGNOSTIC_REDIR_OUTPUT);
270             if ( bOutput
271             && checkStatusValue != null 
272             &&  checkStatusValue.toLowerCase().equals("true"))
273             {
274                // try to register a trace file
275                sTraceDir = (String)properties.get(DIAGNOSTIC_TRACE_DIR);
276                   
277                if (sTraceDir != null && sTraceDir.length() > 0)
278                {
279                   bRedirectOutput = true;
280                   if (!sTraceDir.endsWith(System.getProperty("file.separator")))
281                      sTraceDir += System.getProperty("file.separator");
282                         
283                   sTraceFile = (String)properties.get(DIAGNOSTIC_TRACE_FILE);
284                      
285                   if (sTraceFile == null || sTraceFile.length() == 0)
286                      // generate unique file name
287                      sTraceFile = InetUtil.getIPAddress() + "_" + Math.abs ( (new Date()).getTime() );
288                         
289                   sFullTracePath = sTraceDir + sTraceFile + ".out";
290                   
291                   if (bOutput)
292                   {
293                      try
294                      {
295                         outStream = new PrintStream(new FileOutputStream(sFullTracePath)); //new FileWriter(sFullTracePath)
296                         Diagnostic.addOutputDevice(outStream);
297                         System.out.println("Diagnostic Output written to '" + sFullTracePath + "'");
298                      }
299                      catch(IOException ioe) 
300                      {
301                         // could not open file
302                      }
303                   }
304                }               
305             }            
306             // try to get the output console property and add System.out to output devices
307             checkStatusValue = (String)properties.get(DIAGNOSTIC_OUTPUT_CONSOLE);
308             if (bOutput
309             &&  checkStatusValue != null 
310             &&  checkStatusValue.toLowerCase().equals("true"))
311             {
312                bOutputConsole = true;
313                Diagnostic.addOutputDevice(System.out);
314             }
315 
316             System.setErr(System.out);
317 
318             try
319             {
320                traceLevelValue = (String)properties.get(DIAGNOSTIC_TRACE_LEVEL);
321                if (traceLevelValue != null)
322                   outLevel = Integer.parseInt(traceLevelValue);
323             }
324             catch (NumberFormatException nfe)
325             {
326                // just leave the outLevel the way it was
327             }
328          
329             // try to get the checking status flag
330             checkStatusValue = (String)properties.get(DIAGNOSTIC_CHECKING_ENABLED);
331             if (checkStatusValue != null 
332             &&  checkStatusValue.toLowerCase().equals("true"))
333                bChecking = true;
334             else
335                bChecking = false;
336 
337             // try to get the print time status flag
338             checkStatusValue = (String)properties.get(DIAGNOSTIC_PRINT_TIME);
339             if (checkStatusValue != null 
340             &&  checkStatusValue.toLowerCase().equals("true"))
341                bPrintTime = true;
342             else
343                bPrintTime = false;
344 
345             // try to get the print time status flag
346             checkStatusValue = (String)properties.get(DIAGNOSTIC_TIME_FORMAT);
347             if (checkStatusValue != null && checkStatusValue.length() > 0)
348             {
349                try
350                {
351                   timeFormat = new SimpleDateFormat(checkStatusValue);
352                }
353                catch(IllegalArgumentException iae) {}
354             }
355 
356             // try to get the print time status flag
357             checkStatusValue = (String)properties.get(DIAGNOSTIC_PRINT_THREADID);
358             if (checkStatusValue != null 
359             &&  checkStatusValue.toLowerCase().equals("true"))
360                bPrintThreadId = true;
361             else
362                bPrintThreadId = false;
363 
364             // clear the list of categories in the file list */
365             fileTraceCategories.removeAllElements();
366             
367             categoryTraceLevels.clear(); // clear the existing category trace levels
368             for (int i = 0; i < saKeys.length; i++)
369             {
370                // check to see if the key is a category key */
371                if (saKeys[i].startsWith(DIAGNOSTIC_CATEGORY_PREFIX))
372                {
373                   // get the category value */
374                   category = DiagnosticCategory.getCategory((String)properties.get(saKeys[i]));
375                   if (category == null)
376                   {
377                      Diagnostic.println("Trace category '" + saKeys[i] + "' invalid.");
378                   }
379                   else
380                   {
381                      // if the category isn't already registered explicitly by a class */
382                      if ( !traceCategories.contains(category) )
383                      {
384                         fileTraceCategories.addElement(category);
385                         //Diagnostic.println("added " + category);
386                      }
387                      // see if there is a key that corresponds to the category trace level
388                      traceKey = DIAGNOSTIC_CATEGORY_LEVEL + category.toString();
389                      categoryLevel = (String)properties.get(traceKey);
390                      if (categoryLevel != null && categoryLevel.length() > 0)
391                      {
392                         // we found a key/value pair, so store the level in our level properties
393                         categoryTraceLevels.put(category, categoryLevel);
394                      }
395                      if (bRedirectOutput)   // no file automatic file generation if output flag is false
396                      {
397                         // see if there is a key that corresponds to the category file generate
398                         traceKey = DIAGNOSTIC_CATEGORY_FILE + category.toString();
399                         checkStatusValue = (String)properties.get(traceKey);
400                         if (checkStatusValue != null 
401                         &&  checkStatusValue.equalsIgnoreCase("true"))
402                         {
403                            try
404                            {
405                               //sFullTracePath = sTraceDir + category + "_" + sTraceFile + ".out";
406                               addOutputDevice(category, new PrintWriter(new FileWriter(sTraceDir + category + "_" + sTraceFile + ".out")));
407                            }
408                            catch(IOException ioe)
409                            {
410                               // ignore it
411                            }
412                         }  // if
413                      }  // if bOutput
414                   }  // else
415                }  // if
416             }  // for
417             bPropertiesLoaded = true;
418          }  // try
419          catch (PropertyMapperException pme)
420          {
421             // section not found
422             return;
423          }
424          catch(IOException e) 
425          { 
426             // error reading input stream
427             return;
428          }
429       }  // if
430    }
431 
432    /**
433     * For demonstration purposes. Run this class to see how to use it.
434     */
435    public static void main(String[] args)
436    {
437       try
438       {
439          // these statements just set the config directory
440          Settings.registerDataSource(
441             Settings.RUNTIME, 
442             (new com.flexstor.common.settings.datasource.RuntimeDataSource())
443          );
444          if (args.length > 0)
445             Settings.addString(Settings.CONFIG_DIRECTORY, args[0]);
446          
447          /*
448          Diagnostic.enableOutput(true);
449          Diagnostic.enableChecking(true);
450          Diagnostic.setTraceLevel(3);
451          Diagnostic.addTraceCategory(Diagnostic.CAT_SEND);
452          */
453          
454          // try to get properties, overwrites defaults
455          Diagnostic.initialize("client");
456          
457          Diagnostic.println("Current test settings:");
458          Diagnostic.println("Number of output devices:" + outputDevices.length);
459          Diagnostic.println("Default time stamp="+(new SimpleDateFormat(DEFAULT_TIME_FORMAT)).format(new Date()));
460          Diagnostic.println("Current time stamp="+timeFormat.format(new Date()));
461 
462          Diagnostic.println("TraceLevel="+getTraceLevel());
463          Diagnostic.println("Checking="+bChecking);
464          Diagnostic.println("ThreadId=" + getThreadId());
465          Diagnostic.println("Categories:");
466          Enumeration e = fileTraceCategories.elements();
467          while(e.hasMoreElements())
468             Diagnostic.println(e.nextElement().toString());
469          e = traceCategories.elements();
470          while(e.hasMoreElements())
471             Diagnostic.println(e.nextElement().toString());
472          Diagnostic.println("");
473          Diagnostic.println("Test begin");
474          
475          // trace based on level
476          Diagnostic.println("*** Diagnostic.trace(1, \"Trace for level 1\")");
477          Diagnostic.trace(1, "Trace for level 1");
478          Diagnostic.println("*** Diagnostic.trace(3, \"Trace for level 3\")");
479          Diagnostic.trace(3, "Trace for level 3");
480          Diagnostic.println("*** Diagnostic.trace(5, \"Trace for level 5\")");
481          Diagnostic.trace(5, "Trace for level 5");
482          
483          // trace based on category
484          Diagnostic.println("*** Diagnostic.trace(Diagnostic.CAT_ARCHIVE, \"Trace for category Archive\")");
485          Diagnostic.trace(Diagnostic.CAT_ARCHIVE, "Trace for category Archive");
486          Diagnostic.println("*** Diagnostic.trace(Diagnostic.CAT_SEND, \"Trace for category Send\")");
487          Diagnostic.trace(Diagnostic.CAT_SEND, "Trace for category Send");
488          
489          Diagnostic.println("*** Diagnostic.precondition((5 < 9), \"Precondition 5 < 9\")");
490          try{Diagnostic.precondition((5 < 9), "Precondition 5 < 9");}catch(DiagnosticPreconditionException pce){}
491          Diagnostic.println("*** Diagnostic.precondition((5 > 9), \"Precondition 5 > 9\")");
492          try{Diagnostic.precondition((5 > 9), "Precondition 5 > 9");}catch(DiagnosticPreconditionException pce){printStackTrace(pce);}
493          
494          Diagnostic.println("*** Diagnostic.warn(2, true, \"Warning level 2, condition true\")");
495          Diagnostic.warn(2, true, "Warning level 2, condition true");
496          Diagnostic.println("*** Diagnostic.warn(2, false, \"Warning level 2, condition false\")");
497          Diagnostic.warn(2, false, "Warning level 2, condition false");
498          Diagnostic.println("*** Diagnostic.warn(5, true, \"Warning level 5, condition true\")");
499          Diagnostic.warn(5, true, "Warning level 5, condition true");
500          Diagnostic.println("*** Diagnostic.warn(Diagnostic.CAT_SEND, \"Warning category 'Send'\")");
501          Diagnostic.warn(Diagnostic.CAT_SEND, "Warning category 'Send'");
502          Diagnostic.println("*** Diagnostic.warn(Diagnostic.CAT_ARCHIVE, \"Warning for category 'Archive'\")");
503          Diagnostic.warn(Diagnostic.CAT_ARCHIVE, "Warning for category 'Archive'");
504          Diagnostic.println("*** Diagnostic.needException()");
505          try{Diagnostic.needException();}catch(DiagnosticCheckException ce){}
506          Diagnostic.println("*** Diagnostic.fail(new Exception(\"Failing\"))");
507          try{Diagnostic.fail(new Exception("Failing"));}catch(Exception pce){}
508          
509          Diagnostic.println("*** Diagnostic.printStackTrace()");
510          Diagnostic.printStackTrace();
511          Diagnostic.println("*** Diagnostic.printStackTrace(Diagnostic.CAT_SEND, 5, new Exception())");
512          Diagnostic.printStackTrace(Diagnostic.CAT_SEND, 5, new Exception());
513          Diagnostic.println("*** Test completed");
514       }
515       catch(Exception e)
516       {
517          System.out.println(e);
518       }
519       
520       System.out.println("*** Test completed. Press <enter>");
521       try{System.in.read();}catch(Exception ie){}
522 
523    }  // main
524 
525 }  // end of class
526