001: /**
002: * InstantJ
003: *
004: * Copyright (C) 2002 Nils Meier
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: */package instantj.tst;
017:
018: import instantj.reflect.PropertyException;
019: import instantj.reflect.ReflectAccess;
020: import instantj.compile.CompilationFailedException;
021: import instantj.expression.Expression;
022: import instantj.expression.EvaluationFailedException;
023:
024: import javax.xml.parsers.SAXParser;
025: import javax.xml.parsers.SAXParserFactory;
026:
027: import org.xml.sax.Attributes;
028: import org.xml.sax.SAXException;
029: import org.xml.sax.helpers.DefaultHandler;
030:
031: import java.io.File;
032: import java.io.FileFilter;
033: import java.io.FileInputStream;
034: import java.io.IOException;
035: import java.io.InputStream;
036: import java.util.HashMap;
037: import java.util.Map;
038:
039: /**
040: * Runs tests read from configuration descriptors
041: */
042: public class DescriptorTest implements FileFilter {
043:
044: /**
045: * MAIN
046: */
047: public static void main(String[] args) {
048:
049: // Disclaimer
050: System.out.println("InstantJ - "
051: + ReflectAccess.getInstance().calcClassNameOf(
052: DescriptorTest.class));
053:
054: // Check the args - we need the directory folder where
055: // the test-cases reside in
056: if (args.length != 1) {
057: System.out
058: .println("Usage: java instantj.tst.RunTests [folder]");
059: return;
060: }
061:
062: // Check if folder exists
063: File folder = new File(args[0]);
064: if (!folder.exists()) {
065: System.out.println("Folder " + folder + " doesn't exist!");
066: return;
067: }
068:
069: // Run the test
070: new DescriptorTest(folder);
071:
072: // Done
073: System.out.println("Done");
074:
075: // .. we want to make sure that we actually quit
076: // (could have an awt thread sticking around)
077: System.exit(0);
078: }
079:
080: /**
081: * Constructor
082: */
083: private DescriptorTest(File folder) {
084:
085: // Try to get a parser
086: SAXParser parser;
087: try {
088: parser = SAXParserFactory.newInstance().newSAXParser();
089: } catch (Throwable t) {
090: System.out
091: .println("Couldn't instantiate SAXParser because of "
092: + t.getClass().getName()
093: + "#"
094: + t.getMessage());
095: return;
096: }
097:
098: // Try to open the tests
099: File[] files = getTests(folder);
100: for (int i = 0; i < files.length; i++) {
101: test(files[i], parser);
102: }
103:
104: // Done
105: }
106:
107: /**
108: * Callback whether we accept a given file or not
109: */
110: public boolean accept(File file) {
111: return file.getAbsolutePath().endsWith(".xml");
112: }
113:
114: /**
115: * Helper that resolves tests from given folder
116: */
117: private File[] getTests(File folder) {
118:
119: // Info
120: System.out.println("Looking for *.xml in " + folder);
121:
122: // Here's the list
123: return folder.listFiles(this );
124:
125: }
126:
127: /**
128: * Run a single test
129: */
130: private void test(File test, SAXParser parser) {
131:
132: // we have to handle the case of some IO problem
133: try {
134:
135: // open the file
136: InputStream in = new FileInputStream(test);
137:
138: // and parse it
139: Configuration conf = parse(in, parser);
140:
141: // and execute it
142: evaluate(test, conf);
143:
144: // done
145: in.close();
146:
147: } catch (SAXException e) {
148: System.out.println("Parsing test " + test.getName()
149: + " failed because of " + e.getClass().getName()
150: + "#" + e.getMessage());
151: } catch (IOException e) {
152: System.out.println("Reading test " + test.getName()
153: + " failed because of " + e.getClass().getName()
154: + "#" + e.getMessage());
155: }
156:
157: }
158:
159: /**
160: * Evaluates an expression
161: */
162: private void evaluate(File test, Configuration conf) {
163:
164: System.out.print("Evaluating \"" + conf.getTitle() + "\" ("
165: + test + ")");
166:
167: // Try to compile the expression
168: Expression ex;
169: try {
170: ex = new Expression(conf.getExpression(), conf
171: .getProperties());
172: } catch (CompilationFailedException cfe) {
173: System.out
174: .println(" failed because of compilation problem: "
175: + cfe.getMessage());
176: cfe.printErrors(System.out);
177: return;
178: }
179:
180: // Try to evaluate the expression in its context
181: Object result;
182: try {
183: // now we create an instance for the expression and let it grab
184: // necessary properties from the map we've collected but
185: // alternatively we could set properties ourselves with :
186: // ex.getInstance().set("something", somevalue).set("else", anothervalue).evaluate().
187: result = ex.getInstance(conf.getValues()).evaluate();
188: } catch (PropertyException mpe) {
189: System.out.println(" failed : " + mpe.getMessage());
190: return;
191: } catch (EvaluationFailedException efe) {
192: System.out.println(" failed : " + efe.getMessage());
193: return;
194: }
195:
196: // Done
197: System.out.println(" resulted in ("
198: + result.getClass().getName() + ") " + result);
199:
200: }
201:
202: /**
203: * Parses a test
204: */
205: private Configuration parse(InputStream in, SAXParser parser)
206: throws IOException, SAXException {
207:
208: ExpressionDescriptorHandler handler = new ExpressionDescriptorHandler();
209: parser.parse(in, handler);
210: return handler.getConfiguration();
211:
212: }
213:
214: /**
215: * An expression that's configured in the descriptor
216: */
217: static class Configuration {
218:
219: /** the title */
220: private String title = null;
221:
222: /** the expression */
223: private String expression = null;
224:
225: /** the property types */
226: private Map properties = new HashMap();
227:
228: /** the property values */
229: private Map values = new HashMap();
230:
231: /**
232: * Helper that adds an property
233: */
234: void addProperty(String pName, String pType, String pValue)
235: throws IllegalArgumentException {
236:
237: // We simply remember the tpye and value as java.lang.String and
238: // rely on ReflectAccess underlying Expression to later transform
239: // that into something typed
240: properties.put(pName, pType);
241: values.put(pName, pValue);
242:
243: // We could have used ReflectAccess here to provide something
244: // that is already typed correctly, too
245: // Class type = ReflectAccess.getInstance().calcClass(pType);
246: // Object value = ReflectAccess.getInstance().calcTypedInstance(pValue, type);
247: // propertyTypes.put (pName, type);
248: // propertyValues.put(pName, value);
249: }
250:
251: /**
252: * Accessor - the expression
253: */
254: String getExpression() {
255: return expression.toString();
256: }
257:
258: /**
259: * Accessor - the expression
260: */
261: void setExpression(String pExpression) {
262: expression = pExpression;
263: }
264:
265: /**
266: * Accessor - the title
267: */
268: String getTitle() {
269: return title;
270: }
271:
272: /**
273: * Accessor - the title
274: */
275: void setTitle(String pTitle) {
276: title = pTitle;
277: }
278:
279: /**
280: * Gets the properties.
281: * @return returns the mapping between property-names and -types
282: */
283: Map getProperties() {
284: return properties;
285: }
286:
287: /**
288: * Gets the values.
289: * @return returns the mapping between property-names and -values
290: */
291: Map getValues() {
292: return values;
293: }
294:
295: }
296:
297: /**
298: * A SAX 'Default' Handler that knows how to read a test-case
299: */
300: /*package*/static class ExpressionDescriptorHandler extends
301: DefaultHandler {
302:
303: /** the result */
304: private Configuration configuration = new Configuration();
305:
306: /** the expression we gather */
307: private StringBuffer expression = new StringBuffer();
308:
309: /** the elements we know */
310: private final static String ELEM_TEST = "test",
311: ELEM_PROPERTY = "property",
312: ELEM_EXPRESSION = "expression";
313:
314: /** the attributes we know */
315: private final static String ATTR_TYPE = "type",
316: ATTR_NAME = "name", ATTR_VALUE = "value";
317:
318: /**
319: * @see DocumentHandler#startElement(String, AttributeList)
320: */
321: public void startElement(String uri, String localName,
322: String elemName, Attributes attributes)
323: throws SAXException {
324:
325: // we keep the element
326: expression.append('<');
327: expression.append(elemName);
328: expression.append('>');
329:
330: // A property ?
331: if (ELEM_PROPERTY.equals(elemName)) {
332:
333: // .. get its attributes
334: String name = attributes.getValue(ATTR_NAME);
335: String type = attributes.getValue(ATTR_TYPE);
336: String value = attributes.getValue(ATTR_VALUE);
337:
338: // .. check validity
339: if ((name == null) || (type == null) || (value == null)) {
340: throw new SAXException("Element " + ELEM_PROPERTY
341: + " requires attributes " + ATTR_NAME + "&"
342: + ATTR_TYPE + "&" + ATTR_VALUE);
343: }
344:
345: // .. and remember
346: try {
347: configuration.addProperty(name, type, value);
348: } catch (IllegalArgumentException e) {
349: throw new SAXException(e.getMessage()
350: + " for attributes " + ATTR_NAME + "&"
351: + ATTR_TYPE + "&" + ATTR_VALUE);
352: }
353:
354: }
355:
356: // The expression?
357: if (ELEM_EXPRESSION.equals(elemName)) {
358: // .. the initial comment ends because that's the code we need
359: expression.append("*/");
360: }
361:
362: // The test?
363: if (ELEM_TEST.equals(elemName)) {
364: // .. get the title
365: configuration.setTitle(attributes.getValue("title"));
366: }
367:
368: // Done
369: }
370:
371: /**
372: * Receive notification of the end of an element.
373: */
374: public void endElement(String uri, String localName,
375: String elemName) throws SAXException {
376: // After the expression is considered to be comment again
377: if (ELEM_EXPRESSION.equals(elemName)) {
378: expression.append("/*");
379: }
380: // we keep the element
381: expression.append("</");
382: expression.append(elemName);
383: expression.append('>');
384: }
385:
386: /**
387: * Receive notification of character data inside an element.
388: */
389: public void characters(char ch[], int start, int length)
390: throws SAXException {
391: expression.append(ch, start, length);
392: }
393:
394: /**
395: * Returns the configuration
396: */
397: /*package*/Configuration getConfiguration() {
398: return configuration;
399: }
400:
401: /**
402: * Callback for startDocument
403: */
404: public void startDocument() throws SAXException {
405: // we start out with a comment until we hit ELEM_EXPRESSION
406: expression.append("/*");
407: }
408:
409: /**
410: * Callback for endDocument
411: */
412: public void endDocument() throws SAXException {
413: // we end the comment we started in the beginning
414: expression.append("*/");
415: // and keep the result
416: configuration.setExpression(expression.toString());
417: }
418:
419: }
420:
421: }
|