• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 /*
19  * $Id$
20  */
21 
22 package org.apache.qetest.xsl;
23 
24 import java.io.BufferedReader;
25 import java.io.File;
26 import java.io.FileReader;
27 import java.io.IOException;
28 import java.util.Properties;
29 import java.util.Vector;
30 
31 import org.apache.qetest.Logger;
32 
33 /**
34  * Simple services for getting lists of StylesheetDatalets.
35  *
36  *
37  * @author shane_curcuru@us.ibm.com
38  * @version $Id$
39  */
40 public abstract class StylesheetDataletManager // provide static services only
41 {
42 
43     /**
44      * Token in xsl file denoting the text of an expected exception.
45      * Used in getInfoItem.
46      */
47     public static final String INFOITEM_EXPECTED_EXCEPTION = "ExpectedException:";
48 
49     /**
50      * Get specified information about the datalet.
51      *
52      * <p>Note that different kinds of information may be read
53      * or discovered in different ways.</p>
54      *
55      * <p>Currently only implemented for
56      * INFOITEM_EXPECTED_EXCEPTION.</p>
57      *
58      * @param logger to report problems to
59      * @param datalet to get information about
60      * @param infoItem to get information about
61      * @return Vector of object(s) of appropriate type;
62      * or null if error
63      */
getInfoItem(Logger logger, StylesheetDatalet datalet, String infoItem)64     public static Vector getInfoItem(Logger logger, StylesheetDatalet datalet, String infoItem)
65     {
66         if ((null == datalet) || (null == infoItem))
67         {
68             logger.logMsg(Logger.ERRORMSG, "getTestInfo called with null datalet or infoItem!");
69             return null;
70         }
71         if (INFOITEM_EXPECTED_EXCEPTION.equals(infoItem))
72         {
73             return getExpectedException(logger, datalet);
74         }
75         else
76         {
77             logger.logMsg(Logger.WARNINGMSG, "getTestInfo unsupported infoItem: " + infoItem);
78             return null;
79         }
80     }
81 
82 
83     /**
84      * Worker method to get expected exception text about a stylesheet.
85      *
86      * Currently parses the inputDir stylesheet for a line that contains
87      * EXPECTED_EXCEPTION inside an xsl comment, on a single line, and
88      * trims off the closing comment -->.
89      * Future work: allow options on datalet to specify some other
90      * expected data in another format - a whole Throwable object to
91      * compare to, or a stacktrace, etc.
92      *
93      * @author Shane Curcuru
94      * @param d Datalet that contains info about the exception
95      * @return Vector of Strings denoting toString of exception(s)
96      * we might expect - any one of them will pass; null if error
97      */
getExpectedException(Logger logger, StylesheetDatalet d)98     protected static Vector getExpectedException(Logger logger, StylesheetDatalet d)
99     {
100         final String EXPECTED_EXCEPTION_END = "-->";
101         Vector v = null;
102         // Read in the testName file to see if it's expecting something
103         try
104         {
105             FileReader fr = new FileReader(d.inputName);
106             BufferedReader br = new BufferedReader(fr);
107             for (;;)
108             {
109                 String inbuf = br.readLine();
110 
111                 if (inbuf == null)
112                     break;  // end of file, break out and return
113 
114                 int idx = inbuf.indexOf(INFOITEM_EXPECTED_EXCEPTION);
115 
116                 if (idx < 0)
117                     continue;  // not on this line, keep going
118 
119                 // The expected exception.getMessage is the rest of the line...
120                 String expExc = inbuf.substring(idx + INFOITEM_EXPECTED_EXCEPTION.length(),
121                                          inbuf.length());
122 
123                 // ... less the trailing " -->" comment end; trimmed
124                 int endComment = expExc.indexOf(EXPECTED_EXCEPTION_END);
125                 if (endComment > -1)
126                     expExc = expExc.substring(0, endComment).trim();
127                 else
128                     expExc = expExc.trim();
129 
130                 if (null == v)
131                     v = new Vector(); // only create if needed
132                 v.addElement(expExc);
133 
134                 // Continue reading the file for more potential
135                 //  expected exception strings - read them all
136                 //@todo optimization: stop parsing after xx lines?
137 
138             }  // end for (;;)
139         }
140         catch (java.io.IOException ioe)
141         {
142             logger.logMsg(Logger.ERRORMSG, "getExpectedException() threw: "
143                                    + ioe.toString());
144             return null;
145         }
146         return v;
147     }
148 
149 
150     /** '[' character, first char in first line of xsltmark fileList.  */
151     public static final String XSLTMARK_CHAR = "[";
152 
153     /** '#' character, comment char in qetest fileList.  */
154     public static final String QETEST_COMMENT_CHAR = "#";
155 
156     /**
157      * Read in a file specifying a list of files to test.
158      * <p>File format is determined from first line in file,
159      * which is a little bit dangerous!</p>
160      * <p>If first line starts with '[', it's an xsltmark-style
161      * fileList, otherwise it's a qetest-style fileList.</p>
162      *
163      * @param logger to report problems to
164      * @param fileName String; name of the file
165      * @param desc description; caller's copy changed
166      * @param defaults default properties to potentially add to each datalet
167      * @return Vector of StylesheetDatalets, or null if error
168      */
readFileList(Logger logger, String fileName, String desc, Properties defaults)169     public static Vector readFileList(Logger logger, String fileName, String desc, Properties defaults)
170     {
171         // Verify the file is there
172         File f = new File(fileName);
173         if (!f.exists())
174         {
175             logger.logMsg(Logger.ERRORMSG, "readFileList: " + fileName
176                           + " does not exist!");
177             return null;
178         }
179 
180         BufferedReader br = null;
181         String line = null;
182         try
183         {
184             br = new BufferedReader(new FileReader(f));
185             line = br.readLine(); // read just first line
186         }
187         catch (IOException ioe)
188         {
189             logger.logMsg(Logger.ERRORMSG, "readFileList: " + fileName
190                           + " threw: " + ioe.toString());
191             return null;
192         }
193 
194         // Verify the first line
195         if (line == null)
196         {
197             logger.logMsg(Logger.ERRORMSG, "readFileList: " + fileName
198                           + " appears to be blank!");
199             return null;
200         }
201 
202         // Determine which kind of fileList this is
203         //  we support the 'native' org.apache.qetest format, and
204         //  alternately the .ini file format used in xsltmark
205         Vector vec = null;
206         if (line.startsWith(XSLTMARK_CHAR))
207         {
208             // This is an xsltmark .ini style file
209             vec = readXsltmarkFileList(logger, br, line, fileName, desc, defaults);
210         }
211         else if (line.startsWith(QETEST_COMMENT_CHAR))
212         {
213             // This is a native qetest style file
214             vec = readQetestFileList(logger, br, line, fileName, desc, defaults);
215         }
216         else
217         {
218             logger.logMsg(Logger.WARNINGMSG, "readFileList: " + fileName
219                           + " could not determine file type; assuming qetest!");
220             vec = readQetestFileList(logger, br, line, fileName, desc, defaults);
221         }
222 
223         if (vec.size() == 0)
224         {
225             logger.logMsg(Logger.ERRORMSG, "readFileList: " + fileName
226                           + " did not have any non-comment lines!");
227             return null;
228         }
229         return vec;
230     }
231 
232     /**
233      * Read in a qetest fileList specifying a list of files to test.
234      * <p>File format is pretty simple:</p>
235      * <ul>
236      * <li># first line of comments is copied into desc</li>
237      * <li># beginning a line is a comment</li>
238      * <li># rest of lines are whitespace delimited filenames and options</li>
239      * <li>inputName xmlName outName goldName flavor options...</li>
240      * <li><b>Note:</b> see {@link StylesheetDatalet} for
241      * details on how the file lines are parsed!</li>
242      * </ul>
243      * <p>Most items are optional, but not having them may result
244      * in validation oddities.  Future work would be to coordinate
245      * this with various Datalet's implementations of .load() so
246      * that Datalets can do better defaulting of non-provided
247      * items; or maybe so that a user can specific a default 'mask'
248      * of values to use for unspecified items.</p>
249      *
250      * @param logger to report problems to
251      * @param br BufferedReader to read from
252      * @param firstLine already read from br
253      * @param fileName String; name of the file
254      * @param desc to use of this file
255      * @param defaults default properties to potentially add to each datalet
256      * @return Vector of StylesheetDatalets, or null if error
257      */
readQetestFileList(Logger logger, BufferedReader br, String firstLine, String fileName, String desc, Properties defaults)258     protected static Vector readQetestFileList(Logger logger, BufferedReader br,
259                                                String firstLine, String fileName,
260                                                String desc, Properties defaults)
261     {
262         final String ABSOLUTE = "absolute";
263         final String RELATIVE = "relative";
264 
265         Vector vec = new Vector();
266         String line = firstLine;
267         // Check if the first line is a comment
268         if (line.startsWith(QETEST_COMMENT_CHAR))
269         {
270             // Save it as the description
271             desc = line;
272             // Parse the next line
273             try
274             {
275                 line = br.readLine();
276             }
277             catch (IOException ioe)
278             {
279                 logger.logMsg(Logger.ERRORMSG, "readQetestFileList: "
280                               + fileName + " threw: " + ioe.toString());
281                 return null;
282             }
283         }
284 
285         // Load each line into a StylesheetDatalet
286         for (;;)
287         {
288             // Skip any lines beginning with # comment char or that are blank
289             if ((!line.startsWith(QETEST_COMMENT_CHAR)) && (line.length() > 0))
290             {
291                 // Create a Datalet and initialize with the line's
292                 //  contents and default properties
293                 StylesheetDatalet d = new StylesheetDatalet(line, defaults);
294 
295                 // Also pass over the global runId, if set
296                 d.options.put("runId", defaults.getProperty("runId"));
297 
298                 //@todo Avoid spurious passes when output & gold not specified
299                 //  needs to detect when StylesheetDatalet doesn't
300                 //  properly have outputName and goldName set
301 
302                 // Add it to our vector
303                 vec.addElement(d);
304             }
305 
306             // Read next line and loop
307             try
308             {
309                 line = br.readLine();
310             }
311             catch (IOException ioe2)
312             {
313                 // Just force us out of the loop; if we've already
314                 //  read part of the file, fine
315                 logger.logMsg(Logger.WARNINGMSG, "readQetestFileList: "
316                               + fileName + " threw: " + ioe2.toString());
317                 break;
318             }
319 
320             if (line == null)
321                 break;
322         } // end of for (;;)
323         return vec;
324     }
325 
326     /**
327      * Read in an xsltmark fileList specifying a list of files to test.
328      * <p>File format is an .ini file like so:</p>
329      * <pre>
330      * [avts]
331      * input=db100.xml
332      * stylesheet=avts.xsl
333      * output=avts.out
334      * reference=avts.ref
335      * iterations=100
336      * </pre>
337      * <p>Note that additional attributes will be logged as warnings
338      * and will be ignored.</p>
339      *
340      * @param logger to report problems to
341      * @param br BufferedReader to read from
342      * @param firstLine already read from br
343      * @param fileName String; name of the file
344      * @param desc to use of this file
345      * @param defaults default properties to potentially add to each datalet
346      * @return Vector of StylesheetDatalets, or null if error
347      */
readXsltmarkFileList(Logger logger, BufferedReader br, String firstLine, String fileName, String desc, Properties defaults)348     protected static Vector readXsltmarkFileList(Logger logger, BufferedReader br,
349                                                  String firstLine, String fileName,
350                                                  String desc, Properties defaults)
351     {
352         Vector vec = new Vector();
353         String line = firstLine;
354         // Parse each line and build a datalet
355         for (;;)
356         {
357             // If we're starting a section, parse the section to a datalet
358             if (line.startsWith(XSLTMARK_CHAR))
359             {
360                 StylesheetDatalet d = readXsltmarkDatalet(logger, br, line, fileName, desc, defaults);
361 
362                 // Also pass over the global runId, if set
363                 d.options.put("runId", defaults.getProperty("runId"));
364 
365                 // Add datalet to our vector
366                 vec.addElement(d);
367             }
368             // Skip blank lines
369             else if (line.length() == 0)
370             {
371                 /* no-op */
372             }
373             // Ooops, readXsltmarkDatalet didn't work right
374             else
375             {
376                 logger.logMsg(Logger.WARNINGMSG, "readXsltmarkFileList parse error, unknown line: "
377                               + line);
378             }
379 
380             // Read next line and loop
381             try
382             {
383                 line = br.readLine();
384             }
385             catch (IOException ioe2)
386             {
387                 // Just force us out of the loop; if we've already
388                 //  read part of the file, fine
389                 logger.logMsg(Logger.WARNINGMSG, "readXsltmarkFileList: "
390                               + fileName + " threw: " + ioe2.toString());
391                 break;
392             }
393 
394             if (line == null)
395                 break;
396         } // end of for (;;)
397         return vec;
398     }
399 
400     /**
401      * Read in an xsltmark fileList specifying a list of files to test.
402      * <p>File format is an .ini file</p>
403      *
404      * @param logger to report problems to
405      * @param br BufferedReader to read from
406      * @param firstLine already read from br
407      * @param fileName String; name of the file
408      * @param desc to use of this file
409      * @param defaults default properties to potentially add to each datalet
410      * @return StylesheetDatalet with appropriate data, or null if error
411      */
readXsltmarkDatalet(Logger logger, BufferedReader br, String firstLine, String fileName, String desc, Properties defaults)412     private static StylesheetDatalet readXsltmarkDatalet(Logger logger, BufferedReader br,
413                                                 String firstLine, String fileName,
414                                                 String desc, Properties defaults)
415     {
416         final String STYLESHEET_MARKER = "stylesheet=";
417         final String INPUT_MARKER = "input=";
418         final String OUTPUT_MARKER = "output=";
419         final String REFERENCE_MARKER = "reference=";
420         final String ITERATIONS_MARKER = "iterations=";
421 
422         String line = firstLine;
423         StylesheetDatalet d = new StylesheetDatalet();
424 
425         // Also pass over the default properties as well
426         d.options = new Properties(defaults);
427 
428         // Parse lines throughout the section to build the datalet
429         for (;;)
430         {
431             // Each .ini file line starts with name of item to fill
432             if (line.startsWith(STYLESHEET_MARKER))
433             {
434                 d.inputName = line.substring(STYLESHEET_MARKER.length());
435             }
436             else if (line.startsWith(INPUT_MARKER))
437             {
438                 d.xmlName = line.substring(INPUT_MARKER.length());
439             }
440             else if (line.startsWith(OUTPUT_MARKER))
441             {
442                 d.outputName = line.substring(OUTPUT_MARKER.length());
443             }
444             else if (line.startsWith(REFERENCE_MARKER))
445             {
446                 d.goldName = line.substring(REFERENCE_MARKER.length());
447             }
448             else if (line.startsWith(XSLTMARK_CHAR))
449             {
450                 d.setDescription(line);
451             }
452             else if (line.startsWith(ITERATIONS_MARKER))
453             {
454                 d.options.put("iterations", line.substring(ITERATIONS_MARKER.length()));
455             }
456             else if (line.length() == 0)
457             {
458                 // Blank lines mean end-of-section; return datalet
459                 // This is the primary exit point for this method
460                 return d;
461             }
462             else
463             {
464                 logger.logMsg(Logger.WARNINGMSG, "readXsltmarkDatalet, unknown line: "
465                               + line);
466             }
467 
468             // Read next line and loop
469             try
470             {
471                 line = br.readLine();
472             }
473             catch (IOException ioe2)
474             {
475                 // Just force us out of the loop; if we've already
476                 //  read part of the file, fine
477                 logger.logMsg(Logger.WARNINGMSG, "readXsltmarkDatalet: "
478                               + fileName + " threw: " + ioe2.toString());
479                 break;
480             }
481 
482             if (line == null)
483                 break;
484         } // end of for (;;)
485         logger.logMsg(Logger.ERRORMSG, "readXsltmarkDatalet: " + fileName
486                       + " no data found!");
487         return null;
488     }
489 }
490