1 /*****************************************************************************/
2 /* Software Testing Automation Framework (STAF)                              */
3 /* (C) Copyright IBM Corp. 2001, 2005                                        */
4 /*                                                                           */
5 /* This software is licensed under the Eclipse Public License (EPL) V1.0.    */
6 /*****************************************************************************/
7 
8 package com.ibm.staf;
9 import com.ibm.staf.service.*;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Set;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.io.FileWriter;
16 import java.io.BufferedWriter;
17 import java.io.IOException;
18 import java.io.FileNotFoundException;
19 
20 /**
21  * This class allows you to format a STAF log (which is a binary file that has
22  * been created by the STAF Log service) as html or text.
23  * <p>
24  * When run as an application, it submits the specified Log query request to
25  * query a STAF log on any machine currently running STAF and then formats the
26  * output as either html or text. Or, when run via a Java program that has
27  * already submitted a LOG QUERY request, you can use the STAFLogFormatter
28  * class to format the log query result as either html or text. You can specify various options including whether you want
29  * the formatted output written to a file.
30  * <p>
31  * Two format types are supported:
32  * <p>
33  * <ul>
34  * <li><code>text</code> - Formats the log as text. For each log record, the
35  * timestamp, level, and message fields are written in a single line with the
36  * fields separated by a space. If a title is specified, the title is written
37  * on the first line followed by a blank line before the log output. For
38  * example, if title "STAF local LOG QUERY GLOBAL LOGNAME test1 LAST 3" is
39  * specified, the log output formatted as text could look like:
40  * <p>
41  * STAF local LOG QUERY GLOBAL LOGNAME test1 LAST 3
42  * <p>
43  * 20081205-13:54:42 Info Step 1 of ScenarioB completed<br>
44  * 20081205-13:54:45 Info Step 2 of ScenarioB completed<br>
45  * 20081205-13:54:54 Pass Scenario completed
46  * <p>
47  * <li><code>html</code> - Formats the log as html. A html document is created
48  * with the body containing a table with three columns (timestamp, level, and
49  * message). Each row in the table contains the timestamp, level, and message
50  * for a log record. The courier font is used for the html document unless you
51  * set a different font. If a title is provided, a header with the title will
52  * be written at the beginning of the html document.
53  * </ul>
54  *
55  * @see <a href="http://staf.sourceforge.net/current/STAFJava.htm#Header_STAFLogFormatter">
56  *      Section "3.6.3 Class STAFLogFormatter" in the STAF Java User's Guide</a>
57  * @since STAF V3.3.2
58  */
59 public class STAFLogFormatter
60 {
61     public static final String sLOG_MAP_CLASS_DEF = "STAF/Service/Log/LogRecord";
62     public static final String sLOG_LONG_MAP_CLASS_DEF =
63         "STAF/Service/Log/LogRecordLong";
64 
65     private static String helpText = "\nSTAFLogFormatter Help\n\n" +
66         "Description:\n" +
67         "\n" +
68         "  The STAFLogFormatter queries a STAF log on any machine currently running\n" +
69         "  STAF and formats the output as either html or text.\n" +
70         "\n" +
71         "Options:\n" +
72         "\n" +
73         "  -queryRequest <LOG QUERY Request>\n" +
74         "  -fileName <File Name>\n" +
75         "  -type <html | text>\n" +
76         "  -fontName <Font Name>\n" +
77         "  -title <Title>\n" +
78         "  -machine <Log Service Machine Name>\n" +
79         "  -serviceName <Log Service Name>\n" +
80         "  -help\n" +
81         "  -version\n" +
82         "\n" +
83         "Notes:\n" +
84         "\n" +
85         "1) You must specify one of the following options:\n" +
86         "     -queryRequest or -help or -version.\n" +
87         "2) If specifying the -help or -version option, it must be the first and only\n" +
88         "   option specified.  All of the other options require the -queryRequest option\n" +
89         "   to be specified.\n" +
90         "3) The -queryRequest option specifies the QUERY request to submit to the Log\n" +
91         "   service.  It must not contain the TOTAL or STATS option.  It is required\n" +
92         "   unless you specified -help or -version.\n" +
93         "4) The -fileName option specifies the fully-qualified name of a file where the\n" +
94         "   formatted log output will be written.  If not specified, the formatted log\n" +
95         "   output is written to Stdout.\n" +
96         "5) The -type option specifies the format type.  Valid values are: html or\n" +
97         "   text.  If not specified, it defaults to html.\n" +
98         "6) The -fontName option specifies the font to use.  If not specified, it\n" +
99         "   defaults to courier (Monospaced).  It only has an effect if formatting as\n" +
100         "   type html.\n" +
101         "7) The -title option specifies a title for the log output.  If not\n" +
102         "   specified, it defaults to the log query request if using type html or to\n" +
103         "   no title if using type text.\n" +
104         "8) The -machine option specifies the machine where the LOQ QUERY request\n" +
105         "   will be submitted.  If not specified, it defaults to local.\n" +
106         "9) The -serviceName option specifies the name of the Log service to which\n" +
107         "   the query request will be submitted.  If not specified, it defaults to LOG.\n" +
108         "\n" +
109         "Examples: (Enter each as a single command)\n" +
110         "\n" +
111         "1) java com.ibm.staf.STAFLogFormatter -fileName /logs/test1.html -queryRequest\n" +
112         "   \"QUERY GLOBAL LOGNAME test1 ALL\"\n" +
113         "2) java com.ibm.staf.STAFLogFormatter -machine awesvc3 -queryRequest\n" +
114         "   \"QUERY GLOBAL LOGNAME CIS LAST 50\"\n" +
115         "3) java com.ibm.staf.STAFLogViewer  -fileName C:\\logs\\email.txt -type text\n" +
116         "   -queryRequest \"QUERY MACHINE client1.company.com LOGNAME email LAST 100\"\n" +
117         "4) java com.ibm.staf.STAFLogViewer -fileName /logs/job_1.html -queryRequest\n" +
118         "   \"QUERY MACHINE {STAF/Config/MachineNickname} LOGNAME STAX_Job_1 ALL\"";
119 
120     private static String kVersion = "3.0.0";
121 
122     private static int TYPE_TEXT = 1;
123     private static int TYPE_HTML = 2;
124     private static String FIELD_SEPARATOR = " ";
125 
126     private STAFMarshallingContext fContext = null;
127     private String fFileName = null;
128     private String fFontName = "courier";
129     private String fTitle = null;
130     private String fLineSep = "";
131 
132     private StringBuffer fOutputString = new StringBuffer();
133     private BufferedWriter fFileWriter = null;
134 
135     /**
136      * This constructs a formatter for a STAF Log.
137      *
138      * @param context The STAF marshalling context containing the output from
139      *                a STAF Log QUERY request.
140      */
STAFLogFormatter(STAFMarshallingContext context)141     public STAFLogFormatter(STAFMarshallingContext context) throws STAFException
142     {
143         // Verify the marshalling context is valid (contains the output
144         // from a LOG QUERY request (without the TOTAL or STATS option)
145 
146         if (context == null)
147         {
148             throw new STAFException(
149                 STAFResult.InvalidValue, "Marshalling context cannot be null");
150         }
151 
152         if (!context.hasMapClassDefinition(sLOG_MAP_CLASS_DEF) &&
153             !context.hasMapClassDefinition(sLOG_LONG_MAP_CLASS_DEF))
154         {
155             throw new STAFException(
156                 STAFResult.InvalidValue,
157                 "Marshalling context does not contain " +
158                 "the " + sLOG_MAP_CLASS_DEF + " or " +
159                 sLOG_LONG_MAP_CLASS_DEF + " map class definition. " +
160                 "Make sure the log query request does not contain the " +
161                 "TOTAL or STATS option.");
162         }
163 
164         if (context.getRootObject() == null)
165         {
166             throw new STAFException(
167                 STAFResult.InvalidValue,
168                 "Marshalling context's root object cannot be null");
169         }
170 
171         if (!(context.getRootObject() instanceof List))
172         {
173             throw new STAFException(
174                 STAFResult.InvalidValue,
175                 "Marshalling context's root object is not a list. " +
176                 "Make sure the log query request does not contain the " +
177                 "TOTAL or STATS option.");
178         }
179 
180         fContext = context;
181         fLineSep = System.getProperty("line.separator");
182     }
183 
setFileName(String fileName)184     public void setFileName(String fileName)
185     {
186         fFileName = fileName;
187     }
188 
189     // setFontName does not have any effect if formatting as text
190 
setFontName(String fontName)191     public void setFontName(String fontName)
192     {
193         fFontName = fontName;
194     }
195 
setTitle(String title)196     public void setTitle(String title)
197     {
198         fTitle = title;
199     }
200 
format(String typeString)201     public String format(String typeString) throws IOException, STAFException
202     {
203         // Verify the type specified is valid
204 
205         int type;
206 
207         if (typeString.equalsIgnoreCase("text"))
208         {
209             type = TYPE_TEXT;
210         }
211         else if (typeString.equalsIgnoreCase("html"))
212         {
213             type = TYPE_HTML;
214         }
215         else
216         {
217             throw new STAFException(
218                 STAFResult.InvalidValue,
219                 "Invalid value for the type option: " + typeString +
220                 "\nValid values are text or html, case-insensitive");
221         }
222 
223         // If a file name was set, create a file writer
224 
225         fFileWriter = null;
226 
227         if (fFileName != null)
228             fFileWriter = new BufferedWriter(new FileWriter(fFileName));
229 
230         try
231         {
232             writeHeader(type);
233             writeBody(type);
234             writeFooter(type);
235         }
236         finally
237         {
238             if (fFileWriter != null)
239             {
240                 try
241                 {
242                     fFileWriter.close();
243                 }
244                 catch (Exception ioe)
245                 { /* Do nothing */ }
246             }
247         }
248 
249         String result = new String("");
250 
251         if (fFileName == null)
252         {
253              // No file name was specified so return the formatted output in
254              // the result
255 
256              result = fOutputString.toString();
257         }
258 
259         return result;
260     }
261 
appendLine(String line)262     private void appendLine(String line) throws IOException
263     {
264         if (fFileName == null)
265         {
266             fOutputString.append(line).append(fLineSep);
267         }
268         else
269         {
270             fFileWriter.write(line);
271             fFileWriter.newLine();
272         }
273     }
274 
writeHeader(int type)275     private void writeHeader(int type) throws IOException
276     {
277         if (type == TYPE_TEXT)
278         {
279             // Do nothing
280         }
281         else if (type == TYPE_HTML)
282         {
283             // Monospaced is not recognized as a valid fixed font by style sheets
284             // so use courier instead for the font name
285 
286             if (fFontName.equalsIgnoreCase("Monospaced"))
287                 fFontName = "courier";
288 
289             // Write HTML header
290 
291             appendLine("<html>");
292             appendLine("");
293             appendLine("<head>");
294             appendLine("<style type=\"text/css\">");
295             appendLine("  h3");
296             appendLine("  {");
297             appendLine("    font-family: \"" + fFontName + "\"");
298             appendLine("  }");
299             appendLine("  th");
300             appendLine("  {");
301             appendLine("    background-color: #4477BB;");
302             appendLine("    font-family: \"" +  fFontName + "\"");
303             appendLine("  }");
304             appendLine("  tr");
305             appendLine("  {");
306             appendLine("    background-color: #DDEEFF;");
307             appendLine("    font-family: \"" + fFontName + "\"");
308             appendLine("  }");
309             appendLine("  tr.altcolor");
310             appendLine("  {");
311             appendLine("    background-color: #99CCFF;");
312             appendLine("    font-family: \"" + fFontName + "\"");
313             appendLine("  }");
314             appendLine("</style>");
315             appendLine("</head>");
316             appendLine("");
317         }
318     }
319 
writeBody(int type)320     private void writeBody(int type) throws IOException, STAFException
321     {
322         if (type == TYPE_TEXT)
323         {
324             if (fTitle != null)
325             {
326                 appendLine(fTitle);
327                 appendLine("");
328             }
329         }
330         else if (type == TYPE_HTML)
331         {
332             // Write HTML body
333 
334             appendLine("<body>");
335             appendLine("");
336 
337             if (fTitle != null)
338             {
339                 // Write html header containing the title
340 
341                 appendLine("<h3>" + fTitle + "</h3>");
342                 appendLine("");
343             }
344 
345             appendLine("<table border=\"3\" width=\"100%%\">");
346             appendLine("<tr>");
347             appendLine("  <th width=\"15%%\" align=\"left\">Date-Time</th>");
348             appendLine("  <th width=\"5%%\" align=\"left\">Level</th>");
349             appendLine("  <th width=\"80%%\" align=\"left\">Message</th>");
350             appendLine("</tr>");
351         }
352 
353         boolean altRowColor = false;
354 
355         List list = (List)fContext.getRootObject();
356         Iterator iter = list.iterator();
357 
358         while (iter.hasNext())
359         {
360             Object entry = iter.next();
361 
362             // Verify that the entry is an instance of the
363             // STAF/Service/Log/LogRecord or STAF/Service/Log/LogRecordLong
364             // map class
365 
366             if (!(entry instanceof Map))
367             {
368                 throw new STAFException(
369                     STAFResult.InvalidValue,
370                     "Input marshalling context's root object is not a list " +
371                     "of all " + sLOG_MAP_CLASS_DEF + " or " +
372                     sLOG_LONG_MAP_CLASS_DEF + " map class objects (1)");
373             }
374 
375             Map logMap = (Map)entry;
376 
377             if (!logMap.containsKey("staf-map-class-name"))
378             {
379                 throw new STAFException(
380                     STAFResult.InvalidValue,
381                     "Input marshalling context's root object is not a list " +
382                     "of all " + sLOG_MAP_CLASS_DEF + " or " +
383                     sLOG_LONG_MAP_CLASS_DEF + " map class objects (2)");
384             }
385 
386             String mapClassDef = (String)logMap.get("staf-map-class-name");
387 
388             if (!mapClassDef.equals(sLOG_MAP_CLASS_DEF) &&
389                 !mapClassDef.equals(sLOG_LONG_MAP_CLASS_DEF))
390             {
391                 throw new STAFException(
392                     STAFResult.InvalidValue,
393                     "Input marshalling context's root object is not a list " +
394                     "of all " + sLOG_MAP_CLASS_DEF + " or " +
395                     sLOG_LONG_MAP_CLASS_DEF + " map class objects (3)");
396             }
397 
398             if (type == TYPE_TEXT)
399             {
400                 // Write a line containing the timestamp, level, and message
401                 // separated by a space
402 
403                 String line =
404                     (String)logMap.get("timestamp") + FIELD_SEPARATOR +
405                     (String)logMap.get("level") + FIELD_SEPARATOR +
406                     (String)logMap.get("message");
407 
408                 appendLine(line);
409             }
410             else if (type == TYPE_HTML)
411             {
412                 // Alternate colors for each row in the table
413 
414                 if (altRowColor)
415                 {
416                     appendLine("<tr valign=\"top\" class=\"altcolor\">");
417                     altRowColor = false;
418                 }
419                 else
420                 {
421                     appendLine("<tr valign=\"top\">");
422                     altRowColor = true;
423                 }
424 
425                 // Write a row containing the timestamp, level, and message
426 
427                 appendLine("  <td>" + logMap.get("timestamp") + "</td>");
428 
429                 appendLine("  <td>" + logMap.get("level") + "</td>");
430 
431                 // Need to preserve whitespace in the message to retain correct
432                 // text formatting (preserves spaces and line breaks)
433 
434                 appendLine("  <td style=\"white-space: pre\">" +
435                            logMap.get("message") + "</td>");
436 
437                 appendLine("</tr>");
438             }
439         }
440 
441         if (type == TYPE_HTML)
442         {
443             appendLine("</table>");
444             appendLine("");
445             appendLine("</body>");
446         }
447     }
448 
writeFooter(int type)449     private void writeFooter(int type) throws IOException
450     {
451         if (type == TYPE_TEXT)
452         {
453             // Do nothing
454         }
455         else if (type == TYPE_HTML)
456         {
457             appendLine("</html>");
458         }
459     }
460 
checkIfArgHasValue(String argv[], int i, Set options)461     private static void checkIfArgHasValue(String argv[], int i, Set options)
462     {
463         if (((i+1) > argv.length - 1) ||
464             (options.contains(argv[i+1])))
465         {
466             System.err.println(
467                 "\nERROR: Option " + argv[i] + " requires a value");
468             System.err.println(helpText);
469             System.exit(1);
470         }
471     }
472 
verifyLogQueryResult(STAFResult queryResult, STAFHandle handle, String machine, String serviceName, String logRequest)473     private static void verifyLogQueryResult(STAFResult queryResult,
474                                              STAFHandle handle,
475                                              String machine,
476                                              String serviceName,
477                                              String logRequest)
478     {
479         if (queryResult.rc == 4010)
480         {
481             String errMsg = "\nThe LOG QUERY request failed with RC 4010 " +
482                 "because the query criteria selected more records than " +
483                 "allowed by the DefaultMaxQueryRecords setting. " +
484                 "Use the FIRST <Num> or LAST <Num> option to specify " +
485                 "the number of records or the ALL option if you " +
486                 "really want all of the records.";
487 
488             // Get the defaultMaxQueryRecords setting for the LOG service
489 
490             STAFResult logSettingsResult = handle.submit2(
491                 machine, serviceName, "LIST SETTINGS");
492 
493             if (logSettingsResult.rc == STAFResult.Ok)
494             {
495                 try
496                 {
497                     Map settingsMap = (Map)logSettingsResult.resultObj;
498 
499                     String defaultMaxQueryRecords =
500                         (String)settingsMap.get("defaultMaxQueryRecords");
501 
502                     errMsg += "  The last " + defaultMaxQueryRecords +
503                         " log entries will be formatted.";
504                 }
505                 catch (Exception e)
506                 {
507                     // Ignore
508                 }
509             }
510 
511             System.err.println(errMsg);
512         }
513         else if (queryResult.rc != 0)
514         {
515             String errMsg;
516 
517             if (queryResult.rc == STAFResult.DoesNotExist)
518             {
519                 errMsg = "\nThe log does not exist.  " +
520                     "The log query request failed with RC=" + queryResult.rc +
521                     ", Result=" + queryResult.result + "\n\n" + logRequest;
522 
523             }
524             else
525             {
526                 errMsg = "\nThe log query request failed with RC=" +
527                     queryResult.rc + ", Result=" + queryResult.result + "\n\n" +
528                     logRequest;
529             }
530 
531             System.err.println(errMsg);
532             System.exit(1);
533         }
534 
535         // Verify the marshalling context is valid (contains the output from a
536         // LOG QUERY request (without the TOTAL or STATS option)
537 
538         if ((queryResult.resultContext == null) ||
539             (queryResult.resultObj == null))
540         {
541             String errMsg = "\nThe log query request returned a null " +
542                 "marshalling context or root. \n\nInvalid query request: " +
543                 logRequest;
544 
545             System.err.println(errMsg);
546             System.exit(1);
547         }
548 
549         if ((!queryResult.resultContext.hasMapClassDefinition(
550                  sLOG_MAP_CLASS_DEF) &&
551              !queryResult.resultContext.hasMapClassDefinition(
552                  sLOG_LONG_MAP_CLASS_DEF)) ||
553             !(queryResult.resultObj instanceof java.util.List))
554         {
555             String errMsg = "\nThe log query request cannot contain the " +
556                 "TOTAL or STATS option.\n\nInvalid query request: " +
557                 logRequest;
558 
559             System.err.println(errMsg);
560             System.exit(1);
561         }
562     }
563 
564     /**
565      * This method is used to execute the STAFLogFormatter class from the
566      * command line.
567      * <p>
568      * To get help on the arguments to specify for the STAFLogFormatter class
569      * from the command line, specify the following:
570      * <p>
571      * <code>java com.ibm.staf.STAFLogViewer -help</code>
572      * <p>
573      * The arguments that can be specified from the command line when executing
574      * the STAFLogFormatter class are:
575      * <ul>
576      * <li>-queryRequest &lt;LOG QUERY Request>
577      * <li>-fileName <File Name>
578      * <li>-type <html | text>
579      * <li>-fontName <Font Name>
580      * <li>-title <Title>
581      * <li>-machine <Log Service Machine Name>
582      * <li>-serviceName <Log Service Name>
583      * <li>-help
584      * <li>-version
585      * </ul>
586      * <p>
587      * You must specify one of the following options: -queryRequest or -help
588      * or -version. If specifying the -help or -version option, it must be
589      * the first and only option specified. All of the other options require
590      * the -queryRequest option to be specified.
591      * <p>
592      * Here's a description of all of the options:
593      * <p>
594      * <ul>
595      * <li><code>-queryRequest</code> specifies the QUERY request to submit to
596      * the Log service. This option is required unless you specified -help or
597      * -version. It should begin with the QUERY option and include any
598      * additional query options, including the options to specify whether the
599      * log is a GLOBAL, MACHINE, or HANDLE log. You may not specify the TOTAL
600      * or STATS option within the queryRequest.
601      * <p>
602      * <li><code>-fileName</code> specifies the fully-qualified name of a file
603      * where the formatted log output will be written. This option is optional.
604      * If not specified, the formatted log output is written to Stdout.
605      * <p>
606      * <li><code>-type</code> specifies the format type. Valid values are:
607      * html or text. This option is optional. If not specified, it defaults
608      * to html.
609      * <p>
610      * <li><code>-fontName</code> specifies the name of the font to use when
611      * formatting the STAF log. It does not have an effect if formatting the
612      * log as text. This option is optional. If not specified, it defaults to
613      * courier (which is a Monospaced font). Examples of other valid font
614      * names are dialog and timesRoman.
615      * <p>
616      * <li><code>-title</code> specifies a title for the log output. This
617      * option is optional. If not specified, it defaults to the actual log
618      * query request submitted if using type html or to no title if using
619      * type text.
620      * <p>
621      * <li><code>-machine</code> specifies the name of the machine where the
622      * STAF log is located. This option is optional. If not specified, it
623      * defaults to local.
624      * <p>
625      * <li><code>-serviceName</code> specifies the name of the Log service
626      * to which the query request will be submitted. This option is optional.
627      * If not specified, it defaults to LOG.
628      * <p>
629      * <li><code>-help</code> displays help information for the STAFLogFormatter.
630      * This option is optional, but if specified, it must be the first and only
631      * option specified.
632      * <p>
633      * <li><code>-version</code> displays the version of the STAFLogFormatter.
634      * This option is optional, but if specified, it must be the first and
635      * only option specified.
636      * </ul>
637      *
638      * @param argv The command-line arguments to be specified by the user.
639      */
main(String argv[])640     public static void main(String argv[])
641     {
642         String queryRequest = "";
643         String fileName = null;
644         String type = "html";
645         String title = null;
646         String fontName = "courier";
647         String machine = "local";
648         String serviceName = "LOG";
649 
650         int minArgsAllowed = 1;  // -queryRequest or -help or -version
651 
652         // Maximum of 14 arguments: A maximum of 7 options can be specifed at
653         // once, but need to multiple 7 by 2 (to get 14) since each of these
654         // options requires a value (and each option value also counts as an
655         // argument).
656         // e.g. -queryRequest <request> -fileName <name> -type <type>
657         //      -title <title> -fontName <fontName> -machine <machine>
658         //      -serviceName <name>
659         int maxArgsAllowed = 14;
660 
661         boolean queryRequestArg = false;
662 
663         Set options = new HashSet();
664         options.add("-queryRequest");
665         options.add("-fileName");
666         options.add("-type");
667         options.add("-title");
668         options.add("-fontName");
669         options.add("-machine");
670         options.add("-serviceName");
671         options.add("-help");
672         options.add("-version");
673 
674         if (argv.length < minArgsAllowed)
675         {
676             System.err.println(
677                 "\nERROR: Must specify " + minArgsAllowed + " of the " +
678                 "following options:  -queryRequest, -help, or -version");
679             System.err.println(helpText);
680             System.exit(1);
681         }
682         else if (argv.length > maxArgsAllowed)
683         {
684             System.err.println(
685                 "\nERROR: Too many arguments.  You specified " + argv.length +
686                 " arguments, but only up to " + maxArgsAllowed +
687                 " arguments are allowed.");
688 
689             System.err.println(helpText);
690             System.exit(1);
691         }
692         else if (argv[0].equalsIgnoreCase("-help"))
693         {
694             System.out.println(helpText);
695             System.exit(0);
696         }
697         else if (argv[0].equalsIgnoreCase("-version"))
698         {
699             System.out.println(kVersion);
700             System.exit(0);
701         }
702         else
703         {
704             for (int i = 0; i < argv.length; i++)
705             {
706                 if (argv[i].equalsIgnoreCase("-queryRequest"))
707                 {
708                     checkIfArgHasValue(argv, i, options);
709                     queryRequestArg = true;
710                     queryRequest = argv[i+1];
711                     i++;
712                 }
713                 else if (argv[i].equalsIgnoreCase("-fileName"))
714                 {
715                     checkIfArgHasValue(argv, i, options);
716                     fileName = argv[i+1];
717                     i++;
718                 }
719                 else if (argv[i].equalsIgnoreCase("-type"))
720                 {
721                     checkIfArgHasValue(argv, i, options);
722                     type = argv[i+1];
723                     i++;
724 
725                     if (!type.equalsIgnoreCase("html") &&
726                         !type.equalsIgnoreCase("text"))
727                     {
728                         System.err.println(
729                             "\nERROR: Invalid value for -type option: " + type +
730                             "\nValid values are html or text.");
731                         System.exit(1);
732                     }
733                 }
734                 else if (argv[i].equalsIgnoreCase("-fontName"))
735                 {
736                     checkIfArgHasValue(argv, i, options);
737                     fontName = argv[i+1];
738                     i++;
739                 }
740                 else if (argv[i].equalsIgnoreCase("-title"))
741                 {
742                     checkIfArgHasValue(argv, i, options);
743                     title = argv[i+1];
744                     i++;
745                 }
746                 else if (argv[i].equalsIgnoreCase("-machine"))
747                 {
748                     checkIfArgHasValue(argv, i, options);
749                     machine = argv[i+1];
750                     i++;
751                 }
752                 else if (argv[i].equalsIgnoreCase("-serviceName"))
753                 {
754                     checkIfArgHasValue(argv, i, options);
755                     serviceName = argv[i+1];
756                     i++;
757                 }
758                 else if (argv[i].equalsIgnoreCase("-version"))
759                 {
760                     System.err.println(
761                         "\nERROR: Option -version must be specified " +
762                         "as the first and only option");
763                     System.err.println(helpText);
764                     System.exit(1);
765                 }
766                 else if (argv[i].equalsIgnoreCase("-help"))
767                 {
768                     System.err.println(
769                         "\nERROR: Option -help must be specified as " +
770                         "the first and only option");
771                     System.err.println(helpText);
772                     System.exit(1);
773                 }
774                 else
775                 {
776                     System.err.println("\nInvalid option name: " + argv[i]);
777                     System.err.println(helpText);
778                     System.exit(1);
779                 }
780             }
781 
782             if (!queryRequestArg)
783             {
784                 System.err.println(
785                     "\nERROR: Must specify " + minArgsAllowed + " of the " +
786                     "following options:  -queryRequest, -help, or -version");
787                 System.err.println(helpText);
788                 System.exit(1);
789             }
790         }
791 
792         // Create a STAF Handle
793 
794         STAFHandle handle = null;
795 
796         try
797         {
798             handle = new STAFHandle("STAFLogFormatter");
799         }
800         catch(STAFException e)
801         {
802             String errMsg = "Error registering with STAF, RC: " + e.rc;
803 
804             System.err.println(errMsg);
805             System.exit(1);
806         }
807 
808         // Submit the Log query request
809 
810         String logRequest = "STAF " + machine + " " + serviceName + " " +
811             queryRequest;
812 
813         STAFResult queryResult = handle.submit2(
814             machine, serviceName, queryRequest);
815 
816         verifyLogQueryResult(
817             queryResult, handle, machine, serviceName, logRequest);
818 
819         // Format the log query output
820 
821         String output = new String("");
822 
823         try
824         {
825             STAFLogFormatter logFormatter = new STAFLogFormatter(
826                 queryResult.resultContext);
827 
828             if (fileName != null)
829                 logFormatter.setFileName(fileName);
830 
831             if (fontName != null)
832                 logFormatter.setFontName(fontName);
833 
834             // If the -title option is not specified, default to the log query
835             // request unless using type text
836 
837             if (title != null)
838                 logFormatter.setTitle(title);
839             else if (!type.equalsIgnoreCase("text"))
840                 logFormatter.setTitle(logRequest);
841 
842             output = logFormatter.format(type);
843         }
844         catch (Exception e)
845         {
846             String errMsg = "\nFormatting the log as " + type;
847 
848             if (fileName != null)
849             {
850                 errMsg += " and/or saving the formatted output to file " +
851                     fileName;
852             }
853 
854             errMsg += " failed.\n" + e.toString();
855 
856             System.err.println(errMsg);
857             System.exit(1);
858         }
859 
860         // If no fileName was specified, write the formatted output to stdout
861 
862         if (fileName == null)
863             System.out.println(output);
864 
865         System.exit(0);
866     }
867 }
868