0001: /*
0002: * This file or a portion of this file is licensed under the terms of
0003: * the Globus Toolkit Public License, found in file GTPL, or at
0004: * http://www.globus.org/toolkit/download/license.html. This notice must
0005: * appear in redistributions of this file, with or without modification.
0006: *
0007: * Redistributions of this Software, with or without modification, must
0008: * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
0009: * some other similar material which is provided with the Software (if
0010: * any).
0011: *
0012: * Copyright 1999-2004 University of Chicago and The University of
0013: * Southern California. All rights reserved.
0014: */
0015: package org.griphyn.vdl.parser;
0016:
0017: import org.griphyn.vdl.invocation.*;
0018: import org.griphyn.vdl.util.Logging;
0019:
0020: // Xerces
0021: import org.xml.sax.*;
0022: import org.xml.sax.helpers.DefaultHandler;
0023: import javax.xml.parsers.*;
0024: import java.io.*;
0025: import java.util.*;
0026: import java.text.*;
0027: import java.net.InetAddress;
0028: import java.net.UnknownHostException;
0029:
0030: /**
0031: * This class uses the Xerces SAX2 parser to validate and parse an XML
0032: * document which contains information from kickstart generated
0033: * invocation record.
0034: *
0035: * @author Jens-S. Vöckler
0036: * @author Yong Zhao
0037: * @version $Revision: 50 $
0038: *
0039: */
0040: public class InvocationParser extends DefaultHandler {
0041: /**
0042: * Default parser is the Xerces parser.
0043: */
0044: protected static final String vendorParserClass = "org.apache.xerces.parsers.SAXParser";
0045:
0046: /**
0047: * Holds the instance of a {@link org.xml.sax.XMLReader} class.
0048: */
0049: private XMLReader m_parser;
0050:
0051: /**
0052: * Holds the result, will be overwritten by each invocation of parse().
0053: */
0054: private InvocationRecord m_result;
0055:
0056: /**
0057: * Keep the location within the document
0058: */
0059: private Locator m_location;
0060:
0061: /**
0062: * A Hashmap to forward resolve namespaces that were encountered
0063: * during parsing.
0064: */
0065: private Map m_forward;
0066:
0067: /**
0068: * A Hashmap to reverse resolve namespaces that were encountered
0069: * during parsing.
0070: */
0071: private Map m_reverse;
0072:
0073: /**
0074: * Parsing for ISO dates without milliseconds
0075: */
0076: private SimpleDateFormat m_coarse;
0077:
0078: /**
0079: * Parsing for ISO dates with millisecond extension.
0080: */
0081: private SimpleDateFormat m_fine;
0082:
0083: /**
0084: * Obtain our logger once for multiple uses.
0085: */
0086: private Logging m_log;
0087:
0088: /**
0089: * Count the depths of elements in the document
0090: */
0091: private int m_depth = 0;
0092:
0093: /**
0094: * A stack of namespaces?
0095: */
0096: private Stack m_stack;
0097:
0098: /**
0099: * Sets a feature while capturing failed features right here.
0100: *
0101: * @param uri is the feature's URI to modify
0102: * @param flag is the new value to set.
0103: * @return true, if the feature could be set, false for an exception
0104: */
0105: private boolean set(String uri, boolean flag) {
0106: boolean result = false;
0107: try {
0108: this .m_parser.setFeature(uri, flag);
0109: result = true;
0110: } catch (SAXException se) {
0111: Logging.instance().log("default", 0,
0112: "Could not set parser feature " + se.getMessage());
0113: }
0114: return result;
0115: }
0116:
0117: /**
0118: * The class constructor. This function initializes the Xerces parser
0119: * and the features that enable schema validation.
0120: *
0121: * @param schemaLocation is the default location of the XML Schema
0122: * which this parser is capable of parsing. It may be null to use
0123: * the defaults provided in the document.
0124: */
0125: public InvocationParser(String schemaLocation) {
0126: this .m_forward = new HashMap();
0127: this .m_reverse = new HashMap();
0128: this .m_coarse = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
0129: this .m_fine = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
0130: this .m_log = Logging.instance();
0131:
0132: try {
0133: m_parser = (XMLReader) Class.forName(vendorParserClass)
0134: .newInstance();
0135: m_parser.setContentHandler(this );
0136: // m_parser.setErrorHandler(this);
0137: m_parser.setErrorHandler(new VDLErrorHandler());
0138:
0139: set("http://xml.org/sax/features/validation", true);
0140: set("http://apache.org/xml/features/validation/dynamic",
0141: true);
0142: set("http://apache.org/xml/features/validation/schema",
0143: true);
0144: // time+memory consuming, see http://xml.apache.org/xerces2-j/features.html
0145: // set( "http://apache.org/xml/features/validation/schema-full-checking", true );
0146:
0147: // Send XML Schema element default values via characters().
0148: set(
0149: "http://apache.org/xml/features/validation/schema/element-default",
0150: true);
0151: set(
0152: "http://apache.org/xml/features/validation/warn-on-duplicate-attdef",
0153: true);
0154: // mysteriously, this one fails with recent Xerces
0155: // set( "http://apache.org/xml/features/validation/warn-on-undeclared-elemdef", true );
0156: set(
0157: "http://apache.org/xml/features/warn-on-duplicate-entitydef",
0158: true);
0159:
0160: // set the schema default location.
0161: if (schemaLocation != null) {
0162: setSchemaLocations(InvocationRecord.SCHEMA_NAMESPACE
0163: + ' ' + schemaLocation);
0164: m_log.log("app", 2, "will use " + schemaLocation);
0165: } else {
0166: m_log.log("app", 2, "will use document schema hint");
0167: }
0168: } catch (ClassNotFoundException e) {
0169: m_log.log("defaut", 0,
0170: "The SAXParser class was not found: " + e);
0171: } catch (InstantiationException e) {
0172: m_log.log("default", 0,
0173: "The SAXParser class could not be instantiated: "
0174: + e);
0175: } catch (IllegalAccessException e) {
0176: m_log.log("default", 0,
0177: "The SAXParser class could not be accessed: " + e);
0178: }
0179: }
0180:
0181: /**
0182: * Sets the list of external real locations where the XML schema may
0183: * be found. Since this list can be determined at run-time through
0184: * properties etc., we expect this function to be called between
0185: * instantiating the parser, and using the parser
0186: *
0187: * @param list is a list of strings representing schema locations. The
0188: * content exists in pairs, one of the namespace URI, one of the
0189: * location URL.
0190: */
0191: public void setSchemaLocations(String list) {
0192: // schema location handling
0193: try {
0194: m_parser
0195: .setProperty(
0196: "http://apache.org/xml/properties/schema/external-schemaLocation",
0197: list);
0198: } catch (SAXException se) {
0199: m_log.log("default", 0, "The SAXParser reported an error: "
0200: + se);
0201: }
0202: }
0203:
0204: /**
0205: * This function parses a XML source from an InputStream source, and
0206: * creates java class instances that correspond to different elements
0207: * in the XML source.
0208: *
0209: * @param reader is a bytestream opened for reading.
0210: * @return the records with the invocation information, or null on failure.
0211: */
0212: public InvocationRecord parse(java.io.InputStream reader) {
0213: try {
0214: // will change m_result
0215: m_parser.parse(new InputSource(reader));
0216: return m_result;
0217: } catch (SAXException e) {
0218: // e.printStackTrace( System.err );
0219: m_log.log("default", 0, "SAX Error: " + e.getMessage());
0220: } catch (IOException e) {
0221: m_log.log("default", 0, "IO Error: " + e.getMessage());
0222: }
0223:
0224: return null;
0225: }
0226:
0227: /**
0228: * This function parses a XML source from the new Reader source, and
0229: * creates java class instances that correspond to different elements
0230: * in the XML source.
0231: *
0232: * @param reader is a character stream opened for reading.
0233: * @return the records with the invocation information, or null on failure.
0234: */
0235: public InvocationRecord parse(java.io.Reader reader) {
0236: try {
0237: // will change m_result
0238: m_parser.parse(new InputSource(reader));
0239: return m_result;
0240: } catch (SAXException e) {
0241: // e.printStackTrace( System.err );
0242: m_log.log("default", 0, "SAX Error: " + e.getMessage());
0243: } catch (IOException e) {
0244: m_log.log("default", 0, "IO Error: " + e.getMessage());
0245: }
0246:
0247: return null;
0248: }
0249:
0250: //
0251: // here starts the implementation to the Interface
0252: //
0253:
0254: /**
0255: * Obtains the document locator from the parser. The document location
0256: * can be used to print debug information, i.e the current location
0257: * (line, column) in the document.
0258: *
0259: * @param locator is the externally set current position
0260: */
0261: public void setDocumentLocator(Locator locator) {
0262: this .m_location = locator;
0263: }
0264:
0265: /**
0266: * This method specifies what to do when the parser is at the beginning
0267: * of the document. In this case, we simply print a message for debugging.
0268: */
0269: public void startDocument() {
0270: this .m_depth = 0;
0271: this .m_stack = new Stack();
0272: this .m_log.log("parser", 1, "*** start of document ***");
0273: }
0274:
0275: /**
0276: * The parser comes to the end of the document.
0277: */
0278: public void endDocument() {
0279: this .m_log.log("parser", 1, "*** end of document ***");
0280: }
0281:
0282: /**
0283: * There is a prefix or namespace defined, put the prefix and its URI
0284: * in the HashMap. We can get the URI when the prefix is used here after.
0285: *
0286: * @param prefix the Namespace prefix being declared.
0287: * @param uri the Namespace URI the prefix is mapped to.
0288: */
0289: public void startPrefixMapping(java.lang.String prefix,
0290: java.lang.String uri) throws SAXException {
0291: String p = prefix == null ? null : new String(prefix);
0292: String u = uri == null ? null : new String(uri);
0293: m_log.log("parser", 2, "adding \"" + p + "\" <=> " + u);
0294:
0295: if (!this .m_forward.containsKey(p))
0296: this .m_forward.put(p, new Stack());
0297: ((Stack) this .m_forward.get(p)).push(u);
0298:
0299: if (!this .m_reverse.containsKey(u))
0300: this .m_reverse.put(u, new Stack());
0301: ((Stack) this .m_reverse.get(u)).push(p);
0302: }
0303:
0304: /**
0305: * Out of the reach of the prefix, remove it from the HashMap.
0306: *
0307: * @param prefix is the prefix that was being mapped previously.
0308: */
0309: public void endPrefixMapping(java.lang.String prefix)
0310: throws SAXException {
0311: String u = (String) ((Stack) this .m_forward.get(prefix)).pop();
0312: String p = (String) ((Stack) this .m_reverse.get(u)).pop();
0313: m_log.log("parser", 2, "removed \"" + p + "\" <=> " + u);
0314: }
0315:
0316: /**
0317: * Helper function to map prefixes correctly onto the elements.
0318: *
0319: * @param uri is the parser-returned URI that needs translation.
0320: * @return the correct prefix for the URI
0321: */
0322: private String map(String uri) {
0323: if (uri == null || uri.length() == 0)
0324: return "";
0325: Stack stack = (Stack) this .m_reverse.get(uri);
0326: String result = stack == null ? null : (String) stack.peek();
0327: if (result == null || result.length() == 0)
0328: return "";
0329: else
0330: return result + ':';
0331: }
0332:
0333: /**
0334: * This method defines the action to take when the parser begins to parse
0335: * an element.
0336: *
0337: * @param namespaceURI is the URI of the namespace for the element
0338: * @param localName is the element name without namespace
0339: * @param qName is the element name as it appears in the docment
0340: * @param atts has the names and values of all the attributes
0341: */
0342: public void startElement(java.lang.String namespaceURI,
0343: java.lang.String localName, java.lang.String qName,
0344: Attributes atts) throws SAXException {
0345: m_log.log("parser", 3, "<" + map(namespaceURI) + localName
0346: + "> at " + m_location.getLineNumber() + ":"
0347: + m_location.getColumnNumber());
0348:
0349: // yup, one more element level
0350: m_depth++;
0351:
0352: java.util.List names = new java.util.ArrayList();
0353: java.util.List values = new java.util.ArrayList();
0354: for (int i = 0; i < atts.getLength(); ++i) {
0355: String name = new String(atts.getLocalName(i));
0356: String value = new String(atts.getValue(i));
0357:
0358: m_log.log("parser", 2, "attribute " + map(atts.getURI(i))
0359: + name + "=\"" + value + "\"");
0360: names.add(name);
0361: values.add(value);
0362: }
0363:
0364: //System.out.println( "QNAME " + qName + " NAME " + names + "\t Values" + values );
0365:
0366: Invocation object = createObject(qName, names, values);
0367: if (object != null)
0368: m_stack.push(new IVSElement(qName, object));
0369: else
0370: throw new SAXException("empty element while parsing");
0371: }
0372:
0373: /**
0374: * The parser is at the end of an element. Each successfully and
0375: * completely parsed Definition will trigger a callback to the
0376: * registered DefinitionHandler.
0377: *
0378: * @param namespaceURI is the URI of the namespace for the element
0379: * @param localName is the element name without namespace
0380: * @param qName is the element name as it appears in the docment
0381: */
0382: public void endElement(java.lang.String namespaceURI,
0383: java.lang.String localName, java.lang.String qName)
0384: throws SAXException {
0385: // that's it for this level
0386: m_depth--;
0387: m_log.log("parser", 3, "</" + map(namespaceURI) + localName
0388: + "> at " + m_location.getLineNumber() + ":"
0389: + m_location.getColumnNumber());
0390:
0391: IVSElement tos = (IVSElement) m_stack.pop();
0392: if (!qName.equals(tos.m_name)) {
0393: m_log.log("default", 0, "assertion failure");
0394: System.exit(1);
0395: }
0396:
0397: if (!m_stack.empty()) {
0398: // add pieces to lower levels
0399: IVSElement peek = (IVSElement) m_stack.peek();
0400: if (!setElementRelation(peek.m_name.charAt(0), peek.m_obj,
0401: tos.m_obj))
0402: m_log.log("parser", 0, "Element " + tos.m_name
0403: + " does not fit into element " + peek.m_name);
0404: } else {
0405: // run finalizer, if available
0406: // m_log.log( "default", 0, "How did I get here?" );
0407: }
0408: }
0409:
0410: /**
0411: * This method is the callback function for characters in an element.
0412: * The element is expected to be of mixed content.
0413: *
0414: * @param ch are the characters from the XML document
0415: * @param start is the start position into the array
0416: * @param length is the amount of valid data in the array
0417: */
0418: public void characters(char[] ch, int start, int length)
0419: throws SAXException {
0420: String message = new String(ch, start, length);
0421: if (message.length() > 0) {
0422: if (message.trim().length() == 0)
0423: m_log.log("parser", 3, "Characters: \' \' x "
0424: + message.length());
0425: else
0426: m_log.log("parser", 3, "Characters: \"" + message
0427: + "\"");
0428:
0429: // Insert text into the text carrying elements. These elements
0430: // must be capable to have text added repeatedly.
0431: if (!m_stack.empty()) {
0432: IVSElement tos = (IVSElement) m_stack.peek();
0433: if (tos.m_obj instanceof HasText) {
0434: HasText obj = (HasText) tos.m_obj;
0435: obj.appendValue(message);
0436: }
0437: } else {
0438: // run finalizer, if available
0439: m_log.log("default", 0, "How did I get here II?");
0440: }
0441: }
0442: }
0443:
0444: /**
0445: * Currently, ignorable whitespace will be ignored.
0446: *
0447: * @param ch are the characters from the XML document
0448: * @param start is the start position into the array
0449: * @param length is the amount of valid data in the array
0450: */
0451: public void ignorableWhitespace(char[] ch, int start, int length)
0452: throws SAXException {
0453: // not implemented
0454: }
0455:
0456: /**
0457: * Receive a processing instruction. Currently, we are just printing
0458: * a debug message that we received a PI.
0459: *
0460: * @param target the processing instruction target
0461: * @param data the processing instruction data, or null if none was supplied.
0462: * The data does not include any whitespace separating it from the target.
0463: */
0464: public void processingInstruction(java.lang.String target,
0465: java.lang.String data) throws SAXException {
0466: m_log.log("parser", 2, "processing instruction " + target
0467: + "=\"" + data + "\" was skipped!");
0468: }
0469:
0470: /**
0471: * Receive a notification that an entity was skipped. Currently, we
0472: * are just printing a debug message to this fact.
0473: *
0474: * @param name The name of the skipped entity. If it is a parameter
0475: * entity, the name will begin with '%', and if it is the external DTD
0476: * subset, it will be the string "[dtd]".
0477: */
0478: public void skippedEntity(java.lang.String name)
0479: throws SAXException {
0480: m_log.log("parser", 2, "entity " + name + " was skipped!");
0481: }
0482:
0483: //
0484: // =================================================== our own stuff ===
0485: //
0486:
0487: /**
0488: * Small helper method to bundle repetitive parameters in a template
0489: * for reporting progress.
0490: *
0491: * @param subject is the name of the XML element that is being scrutinized.
0492: * @param name is then name of the element we are working with.
0493: * @param value is the attribute value.
0494: */
0495: private void log(String subject, String name, String value) {
0496: if (value == null)
0497: value = new String();
0498: m_log.log("filler", 3, subject + "." + name + "=\"" + value
0499: + "\"");
0500: }
0501:
0502: /**
0503: * Small helper method to bundle repetitive complaints in a template
0504: * for reporting progress.
0505: *
0506: * @param subject is the name of the XML element that is being scrutinized.
0507: * @param name is then name of the element we are working with.
0508: * @param value is the attribute value.
0509: */
0510: private void complain(String subject, String name, String value) {
0511: if (value == null)
0512: value = new String();
0513: m_log.log("default", 0, "ignoring " + subject + '@' + name
0514: + "=\"" + value + '"', true);
0515: }
0516:
0517: /**
0518: * Small helper to parse the different date varieties and deal with
0519: * Java obnoxeity.
0520: *
0521: * @param date is an ISO 8601 timestamp
0522: * @return a date field
0523: * @exception ParseException thrown if the date cannot be parsed
0524: */
0525: private Date parseDate(String date) throws ParseException {
0526: // SimpleDataFormat stumbles over colon in time zone
0527: int size = date.length();
0528: if (date.charAt(size - 3) == ':') {
0529: StringBuffer temp = new StringBuffer(date);
0530: temp.deleteCharAt(size - 3);
0531: date = temp.toString();
0532: }
0533:
0534: Date result;
0535: if (date.indexOf('.') == -1) {
0536: // coarse grained timestamp
0537: result = m_coarse.parse(date);
0538: } else {
0539: // fine grained timestamp
0540: result = m_fine.parse(date);
0541: }
0542:
0543: SimpleDateFormat sdf = new SimpleDateFormat(
0544: "yyyyMMdd'T'HHmmssZ");
0545: m_log.log("filler", 3, "found date " + sdf.format(result));
0546: return result;
0547: }
0548:
0549: /**
0550: * Small helper method to set up the attributes for the job elements.
0551: *
0552: * @param job is the job to set up.
0553: * @param names is the list of attribute names
0554: * @param values is the list of attribute values
0555: */
0556: private void setupJob(Job job, java.util.List names,
0557: java.util.List values) throws NumberFormatException,
0558: ParseException {
0559: for (int i = 0; i < names.size(); ++i) {
0560: String name = (String) names.get(i);
0561: String value = (String) values.get(i);
0562:
0563: if (name.equals("start")) {
0564: this .log(job.getTag(), name, value);
0565: job.setStart(parseDate(value));
0566: } else if (name.equals("duration")) {
0567: this .log(job.getTag(), name, value);
0568: job.setDuration(Double.parseDouble(value));
0569: } else if (name.equals("pid")) {
0570: this .log(job.getTag(), name, value);
0571: job.setPID(Integer.parseInt(value));
0572: } else {
0573: this .complain(job.getTag(), name, value);
0574: }
0575: }
0576: }
0577:
0578: /**
0579: * This method determines the actively parsed element, creates the
0580: * Java object that corresponds to the element, and sets the member
0581: * variables with the values of the attributes of the element.
0582: *
0583: * @param e is the name of the element
0584: * @param names is a list of attribute names, as strings.
0585: * @param values is a list of attribute values, to match the key list.
0586: * @return A new VDL Java object, which may only be partly constructed.
0587: * @exception IllegalArgumentException if the element name is too short.
0588: */
0589: protected Invocation createObject(String e, java.util.List names,
0590: java.util.List values) throws IllegalArgumentException {
0591: if (e == null || e.length() < 1)
0592: throw new IllegalArgumentException("illegal element length");
0593:
0594: try {
0595: // postcondition: string has content w/ length > 0
0596: switch (e.charAt(0)) {
0597: //
0598: // A
0599: //
0600: case 'a':
0601: if (e.equals("arg")) {
0602: ArgEntry entry = new ArgEntry();
0603: for (int i = 0; i < names.size(); ++i) {
0604: String name = (String) names.get(i);
0605: String value = (String) values.get(i);
0606:
0607: if (name.equals("nr")) {
0608: this .log(e, name, value);
0609: entry.setPosition(Integer.parseInt(value));
0610: } else {
0611: this .complain(e, name, value);
0612: }
0613: }
0614: return entry;
0615:
0616: } else if (e.equals("arguments")) {
0617: Arguments cli = new ArgString();
0618: for (int i = 0; i < names.size(); ++i) {
0619: String name = (String) names.get(i);
0620: String value = (String) values.get(i);
0621:
0622: if (name.equals("executable")) {
0623: this .log(e, name, value);
0624: cli.setExecutable(value);
0625: } else {
0626: this .complain(e, name, value);
0627: }
0628: }
0629: return cli;
0630:
0631: } else if (e.equals("argument-vector")) {
0632: Arguments cli = new ArgVector();
0633: for (int i = 0; i < names.size(); ++i) {
0634: String name = (String) names.get(i);
0635: String value = (String) values.get(i);
0636:
0637: if (name.equals("executable")) {
0638: this .log(e, name, value);
0639: cli.setExecutable(value);
0640: } else {
0641: this .complain(e, name, value);
0642: }
0643: }
0644: return cli;
0645: }
0646:
0647: // unknown
0648: return null;
0649:
0650: //
0651: // C
0652: //
0653: case 'c':
0654: if (e.equals("cwd")) {
0655: WorkingDir cwd = new WorkingDir();
0656: for (int i = 0; i < names.size(); ++i) {
0657: String name = (String) names.get(i);
0658: String value = (String) values.get(i);
0659:
0660: this .complain(e, name, value);
0661: }
0662: return cwd;
0663: } else if (e.equals("cleanup")) {
0664: Job job = new Job(e);
0665: setupJob(job, names, values);
0666: return job;
0667: }
0668:
0669: // unknown
0670: return null;
0671:
0672: //
0673: // D
0674: //
0675: case 'd':
0676: if (e.equals("data")) {
0677: Data data = new Data();
0678: for (int i = 0; i < names.size(); ++i) {
0679: String name = (String) names.get(i);
0680: String value = (String) values.get(i);
0681:
0682: if (name.equals("truncated")) {
0683: this .log(e, name, value);
0684: data.setTruncated(Boolean.valueOf(value)
0685: .booleanValue());
0686: } else {
0687: this .complain(e, name, value);
0688: }
0689: }
0690: return data;
0691: } else if (e.equals("descriptor")) {
0692: Descriptor file = new Descriptor();
0693: for (int i = 0; i < names.size(); ++i) {
0694: String name = (String) names.get(i);
0695: String value = (String) values.get(i);
0696:
0697: if (name.equals("number")) {
0698: this .log(e, name, value);
0699: file.setDescriptor(Integer.parseInt(value));
0700: } else {
0701: this .complain(e, name, value);
0702: }
0703: }
0704: return file;
0705: }
0706:
0707: // unknown
0708: return null;
0709:
0710: //
0711: // E
0712: //
0713: case 'e':
0714: if (e.equals("env")) {
0715: EnvEntry ee = new EnvEntry();
0716: for (int i = 0; i < names.size(); ++i) {
0717: String name = (String) names.get(i);
0718: String value = (String) values.get(i);
0719:
0720: if (name.equals("key")) {
0721: this .log(e, name, value);
0722: ee.setKey(value);
0723: } else {
0724: this .complain(e, name, value);
0725: }
0726: }
0727: return ee;
0728:
0729: } else if (e.equals("environment")) {
0730: Environment env = new Environment();
0731: for (int i = 0; i < names.size(); ++i) {
0732: String name = (String) names.get(i);
0733: String value = (String) values.get(i);
0734: this .complain(e, name, value);
0735: }
0736: return env;
0737: }
0738:
0739: // unknown
0740: return null;
0741:
0742: //
0743: // F
0744: //
0745: case 'f':
0746: if (e.equals("file")) {
0747: Regular file = new Regular();
0748: for (int i = 0; i < names.size(); ++i) {
0749: String name = (String) names.get(i);
0750: String value = (String) values.get(i);
0751:
0752: if (name.equals("name")) {
0753: this .log(e, name, value);
0754: file.setFilename(value);
0755: } else {
0756: this .complain(e, name, value);
0757: }
0758: }
0759: return file;
0760: } else if (e.equals("fifo")) {
0761: Fifo fifo = new Fifo();
0762: for (int i = 0; i < names.size(); ++i) {
0763: String name = (String) names.get(i);
0764: String value = (String) values.get(i);
0765:
0766: if (name.equals("name")) {
0767: this .log(e, name, value);
0768: fifo.setFilename(value);
0769: } else if (name.equals("descriptor")) {
0770: this .log(e, name, value);
0771: fifo.setDescriptor(Integer.parseInt(value));
0772: } else if (name.equals("count")) {
0773: this .log(e, name, value);
0774: fifo.setCount(Integer.parseInt(value));
0775: } else if (name.equals("rsize")) {
0776: this .log(e, name, value);
0777: fifo.setInputSize(Long.parseLong(value));
0778: } else if (name.equals("wsize")) {
0779: this .log(e, name, value);
0780: fifo.setOutputSize(Long.parseLong(value));
0781: } else {
0782: this .complain(e, name, value);
0783: }
0784: }
0785: return fifo;
0786: } else if (e.equals("failure")) {
0787: JobStatusFailure failed = new JobStatusFailure();
0788: for (int i = 0; i < names.size(); ++i) {
0789: String name = (String) names.get(i);
0790: String value = (String) values.get(i);
0791:
0792: if (name.equals("error")) {
0793: this .log(e, name, value);
0794: failed.setError(Integer.parseInt(value));
0795: } else {
0796: this .complain(e, name, value);
0797: }
0798: }
0799: return failed;
0800: }
0801:
0802: // unknown
0803: return null;
0804:
0805: //
0806: // H
0807: //
0808: case 'h':
0809: if (e.equals("hard")) {
0810: return new Ignore();
0811: }
0812:
0813: // unknown
0814: return null;
0815:
0816: //
0817: // I
0818: //
0819: case 'i':
0820: if (e.equals("invocation")) {
0821: this .m_result = new InvocationRecord();
0822: for (int i = 0; i < names.size(); ++i) {
0823: String name = (String) names.get(i);
0824: String value = (String) values.get(i);
0825:
0826: if (name.equals("version")) {
0827: this .log(e, name, value);
0828: m_result.setVersion(value);
0829: } else if (name.equals("start")) {
0830: this .log(e, name, value);
0831: m_result.setStart(parseDate(value));
0832: } else if (name.equals("duration")) {
0833: this .log(e, name, value);
0834: m_result.setDuration(Double
0835: .parseDouble(value));
0836: } else if (name.equals("transformation")) {
0837: this .log(e, name, value);
0838: m_result.setTransformation(value);
0839: } else if (name.equals("derivation")) {
0840: this .log(e, name, value);
0841: m_result.setDerivation(value);
0842: } else if (name.equals("host")
0843: || name.equals("hostaddr")) {
0844: this .log(e, name, value);
0845: m_result.setHostAddress(InetAddress
0846: .getByName(value));
0847: } else if (name.equals("hostname")) {
0848: this .log(e, name, value);
0849: m_result.setHostname(value);
0850: } else if (name.equals("resource")) {
0851: this .log(e, name, value);
0852: m_result.setResource(value);
0853: } else if (name.equals("pid")) {
0854: this .log(e, name, value);
0855: m_result.setPID(Integer.parseInt(value));
0856: } else if (name.equals("uid")) {
0857: this .log(e, name, value);
0858: m_result.setUID(Integer.parseInt(value));
0859: } else if (name.equals("gid")) {
0860: this .log(e, name, value);
0861: m_result.setGID(Integer.parseInt(value));
0862: } else if (name.equals("user")) {
0863: this .log(e, name, value);
0864: m_result.setUser(value);
0865: } else if (name.equals("group")) {
0866: this .log(e, name, value);
0867: m_result.setGroup(value);
0868: } else if (name.equals("schemaLocation")) {
0869: // ignore root element schema location hint
0870: } else if (name.equals("umask")) {
0871: this .log(e, name, value);
0872: m_result.setUMask(Integer
0873: .parseInt(value, 8));
0874: } else if (name.equals("wf-label")) {
0875: this .log(e, name, value);
0876: m_result.setWorkflowLabel(value);
0877: } else if (name.equals("wf-stamp")) {
0878: this .log(e, name, value);
0879: m_result
0880: .setWorkflowTimestamp(parseDate(value));
0881: } else {
0882: this .complain(e, name, value);
0883: }
0884: }
0885: return this .m_result;
0886: }
0887:
0888: // unknown
0889: return null;
0890:
0891: //
0892: // M
0893: //
0894: case 'm':
0895: if (e.equals("mainjob")) {
0896: Job job = new Job(e);
0897: setupJob(job, names, values);
0898: return job;
0899: }
0900:
0901: // unknown
0902: return null;
0903:
0904: //
0905: // P
0906: //
0907: case 'p':
0908: if (e.equals("prejob")) {
0909: Job job = new Job(e);
0910: setupJob(job, names, values);
0911: return job;
0912: } else if (e.equals("postjob")) {
0913: Job job = new Job(e);
0914: setupJob(job, names, values);
0915: return job;
0916: }
0917:
0918: // unknown
0919: return null;
0920:
0921: //
0922: // R
0923: //
0924: case 'r':
0925: if (e.equals("regular")) {
0926: JobStatusRegular regular = new JobStatusRegular();
0927: for (int i = 0; i < names.size(); ++i) {
0928: String name = (String) names.get(i);
0929: String value = (String) values.get(i);
0930:
0931: if (name.equals("exitcode")) {
0932: this .log(e, name, value);
0933: regular
0934: .setExitCode(Short
0935: .parseShort(value));
0936: } else {
0937: this .complain(e, name, value);
0938: }
0939: }
0940: return regular;
0941: } else if (e.equals("resource")) {
0942: // ignore
0943: return new Ignore();
0944: }
0945:
0946: // unknown
0947: return null;
0948:
0949: //
0950: // S
0951: //
0952: case 's':
0953: if (e.equals("statcall")) {
0954: StatCall statcall = new StatCall();
0955: for (int i = 0; i < names.size(); ++i) {
0956: String name = (String) names.get(i);
0957: String value = (String) values.get(i);
0958:
0959: if (name.equals("error")) {
0960: this .log(e, name, value);
0961: statcall.setError(Integer.parseInt(value));
0962: } else if (name.equals("id")) {
0963: this .log(e, name, value);
0964: statcall.setHandle(value);
0965: } else if (name.equals("lfn")) {
0966: this .log(e, name, value);
0967: statcall.setLFN(value);
0968: } else {
0969: this .complain(e, name, value);
0970: }
0971: }
0972: return statcall;
0973:
0974: } else if (e.equals("statinfo")) {
0975: StatInfo statinfo = new StatInfo();
0976: for (int i = 0; i < names.size(); ++i) {
0977: String name = (String) names.get(i);
0978: String value = (String) values.get(i);
0979:
0980: if (name.equals("mode")) {
0981: this .log(e, name, value);
0982: statinfo
0983: .setMode(Integer.parseInt(value, 8));
0984: } else if (name.equals("size")) {
0985: this .log(e, name, value);
0986: statinfo.setSize(Long.parseLong(value));
0987: } else if (name.equals("inode")) {
0988: this .log(e, name, value);
0989: statinfo.setINode(Long.parseLong(value));
0990: } else if (name.equals("nlink")) {
0991: this .log(e, name, value);
0992: statinfo
0993: .setLinkCount(Long.parseLong(value));
0994: } else if (name.equals("blksize")) {
0995: this .log(e, name, value);
0996: statinfo
0997: .setBlockSize(Long.parseLong(value));
0998: } else if (name.equals("blocks")) {
0999: this .log(e, name, value);
1000: statinfo.setBlocks(Long.parseLong(value));
1001: } else if (name.equals("atime")) {
1002: this .log(e, name, value);
1003: statinfo.setAccessTime(parseDate(value));
1004: } else if (name.equals("ctime")) {
1005: this .log(e, name, value);
1006: statinfo.setCreationTime(parseDate(value));
1007: } else if (name.equals("mtime")) {
1008: this .log(e, name, value);
1009: statinfo
1010: .setModificationTime(parseDate(value));
1011: } else if (name.equals("uid")) {
1012: this .log(e, name, value);
1013: statinfo.setUID(Integer.parseInt(value));
1014: } else if (name.equals("user")) {
1015: this .log(e, name, value);
1016: statinfo.setUser(value);
1017: } else if (name.equals("gid")) {
1018: this .log(e, name, value);
1019: statinfo.setGID(Integer.parseInt(value));
1020: } else if (name.equals("group")) {
1021: this .log(e, name, value);
1022: statinfo.setGroup(value);
1023: } else {
1024: this .complain(e, name, value);
1025: }
1026: }
1027: return statinfo;
1028:
1029: } else if (e.equals("status")) {
1030: Status status = new Status();
1031: for (int i = 0; i < names.size(); ++i) {
1032: String name = (String) names.get(i);
1033: String value = (String) values.get(i);
1034:
1035: if (name.equals("raw")) {
1036: this .log(e, name, value);
1037: status.setStatus(Integer.parseInt(value));
1038: } else {
1039: this .complain(e, name, value);
1040: }
1041: }
1042: return status;
1043:
1044: } else if (e.equals("soft")) {
1045: return new Ignore();
1046:
1047: } else if (e.equals("signalled")) {
1048: JobStatusSignal signalled = new JobStatusSignal();
1049: for (int i = 0; i < names.size(); ++i) {
1050: String name = (String) names.get(i);
1051: String value = (String) values.get(i);
1052:
1053: if (name.equals("signal")) {
1054: this .log(e, name, value);
1055: signalled.setSignalNumber(Short
1056: .parseShort(value));
1057: } else if (name.equals("corefile")) {
1058: this .log(e, name, value);
1059: signalled.setCoreFlag(Boolean
1060: .valueOf(value).booleanValue());
1061: } else {
1062: this .complain(e, name, value);
1063: }
1064: }
1065: return signalled;
1066:
1067: } else if (e.equals("suspended")) {
1068: JobStatusSuspend suspended = new JobStatusSuspend();
1069: for (int i = 0; i < names.size(); ++i) {
1070: String name = (String) names.get(i);
1071: String value = (String) values.get(i);
1072:
1073: if (name.equals("signal")) {
1074: this .log(e, name, value);
1075: suspended.setSignalNumber(Short
1076: .parseShort(value));
1077: } else {
1078: this .complain(e, name, value);
1079: }
1080: }
1081: return suspended;
1082:
1083: } else if (e.equals("setup")) {
1084: Job job = new Job(e);
1085: setupJob(job, names, values);
1086: return job;
1087: }
1088:
1089: // unknown
1090: return null;
1091:
1092: //
1093: // T
1094: //
1095: case 't':
1096: if (e.equals("temporary")) {
1097: Temporary file = new Temporary();
1098: for (int i = 0; i < names.size(); ++i) {
1099: String name = (String) names.get(i);
1100: String value = (String) values.get(i);
1101:
1102: if (name.equals("name")) {
1103: this .log(e, name, value);
1104: file.setFilename(value);
1105: } else if (name.equals("descriptor")) {
1106: this .log(e, name, value);
1107: file.setDescriptor(Integer.parseInt(value));
1108: } else {
1109: this .complain(e, name, value);
1110: }
1111: }
1112: return file;
1113: }
1114:
1115: // unknown
1116: return null;
1117:
1118: //
1119: // U
1120: //
1121: case 'u':
1122: if (e.equals("usage")) {
1123: Usage usage = new Usage();
1124: for (int i = 0; i < names.size(); ++i) {
1125: String name = (String) names.get(i);
1126: String value = (String) values.get(i);
1127:
1128: if (name.equals("utime")) {
1129: this .log(e, name, value);
1130: usage
1131: .setUserTime(Double
1132: .parseDouble(value));
1133: } else if (name.equals("stime")) {
1134: this .log(e, name, value);
1135: usage.setSystemTime(Double
1136: .parseDouble(value));
1137: } else if (name.equals("minflt")) {
1138: this .log(e, name, value);
1139: usage.setMinorFaults(Integer
1140: .parseInt(value));
1141: } else if (name.equals("majflt")) {
1142: this .log(e, name, value);
1143: usage.setMajorFaults(Integer
1144: .parseInt(value));
1145: } else if (name.equals("nswap")) {
1146: this .log(e, name, value);
1147: usage.setSwaps(Integer.parseInt(value));
1148: } else if (name.equals("nsignals")) {
1149: this .log(e, name, value);
1150: usage.setSignals(Integer.parseInt(value));
1151: } else if (name.equals("nvcsw")) {
1152: this .log(e, name, value);
1153: usage.setVoluntarySwitches(Integer
1154: .parseInt(value));
1155: } else if (name.equals("nivcsw")) {
1156: this .log(e, name, value);
1157: usage.setInvoluntarySwitches(Integer
1158: .parseInt(value));
1159: } else if (name.equals("maxrss")) {
1160: this .log(e, name, value);
1161: usage
1162: .setMaximumRSS(Integer
1163: .parseInt(value));
1164: } else if (name.equals("ixrss")) {
1165: this .log(e, name, value);
1166: usage.setSharedRSS(Integer.parseInt(value));
1167: } else if (name.equals("idrss")) {
1168: this .log(e, name, value);
1169: usage.setUnsharedRSS(Integer
1170: .parseInt(value));
1171: } else if (name.equals("isrss")) {
1172: this .log(e, name, value);
1173: usage.setStackRSS(Integer.parseInt(value));
1174: } else if (name.equals("inblock")) {
1175: this .log(e, name, value);
1176: usage.setInputBlocks(Integer
1177: .parseInt(value));
1178: } else if (name.equals("outblock")) {
1179: this .log(e, name, value);
1180: usage.setOutputBlocks(Integer
1181: .parseInt(value));
1182: } else if (name.equals("msgsnd")) {
1183: this .log(e, name, value);
1184: usage.setSent(Integer.parseInt(value));
1185: } else if (name.equals("msgrcv")) {
1186: this .log(e, name, value);
1187: usage.setReceived(Integer.parseInt(value));
1188: } else {
1189: this .complain(e, name, value);
1190: }
1191: }
1192: return usage;
1193: } else if (e.equals("uname")) {
1194: Architecture uname = new Architecture();
1195: for (int i = 0; i < names.size(); ++i) {
1196: String name = (String) names.get(i);
1197: String value = (String) values.get(i);
1198:
1199: if (name.equals("system")) {
1200: this .log(e, name, value);
1201: uname.setSystemName(value);
1202: } else if (name.equals("archmode")) {
1203: this .log(e, name, value);
1204: uname.setArchMode(value);
1205: } else if (name.equals("nodename")) {
1206: this .log(e, name, value);
1207: uname.setNodeName(value);
1208: } else if (name.equals("release")) {
1209: this .log(e, name, value);
1210: uname.setRelease(value);
1211: } else if (name.equals("machine")) {
1212: this .log(e, name, value);
1213: uname.setMachine(value);
1214: } else if (name.equals("domainname")) {
1215: this .log(e, name, value);
1216: uname.setDomainName(value);
1217: } else {
1218: this .complain(e, name, value);
1219: }
1220: }
1221: return uname;
1222: }
1223:
1224: // unknown
1225: return null;
1226:
1227: default:
1228: // FIXME: shouldn't this be an exception?
1229: m_log.log("filler", 0,
1230: "Error: No rules defined for element " + e);
1231: return null;
1232: }
1233: } catch (NumberFormatException nfe) {
1234: m_log.log("filler", 0, "Error: Unable to parse a number: "
1235: + nfe.getMessage() + " at "
1236: + m_location.getLineNumber() + ":"
1237: + m_location.getColumnNumber());
1238: return null;
1239: } catch (UnknownHostException uh) {
1240: m_log.log("filler", 0,
1241: "Error: Unable to parse a hostname: "
1242: + uh.getMessage() + " at "
1243: + m_location.getLineNumber() + ":"
1244: + m_location.getColumnNumber());
1245: return null;
1246: } catch (ParseException pe) {
1247: m_log.log("filler", 0, "Error: Unable to parse a date: "
1248: + pe.getMessage() + " at "
1249: + m_location.getLineNumber() + ":"
1250: + m_location.getColumnNumber());
1251: return null;
1252: }
1253: }
1254:
1255: /**
1256: * This method sets the relations between the currently finished XML
1257: * element and its containing element in terms of Java objects.
1258: * Usually it involves adding the object to the parent's child object
1259: * list.
1260: *
1261: * @param initial is the first charactor of the parent element name
1262: * @param parent is a reference to the parent's Java object
1263: * @param child is the completed child object to connect to the parent
1264: * @return true if the element was added successfully, false, if the
1265: * child does not match into the parent.
1266: */
1267: protected boolean setElementRelation(char initial,
1268: Invocation parent, Invocation child) {
1269: switch (initial) {
1270: //
1271: // A
1272: //
1273: case 'a':
1274: if (parent instanceof ArgVector
1275: && child instanceof ArgEntry) {
1276: ArgVector args = (ArgVector) parent;
1277: ArgEntry entry = (ArgEntry) child;
1278: args.setValue(entry.getPosition(), entry.getValue());
1279: return true;
1280: }
1281: // unknown
1282: return false;
1283:
1284: //
1285: // C
1286: //
1287: case 'c':
1288: if (parent instanceof Job) {
1289: Job job = (Job) parent;
1290: if (child instanceof Usage) {
1291: job.setUsage((Usage) child);
1292: return true;
1293: } else if (child instanceof Status) {
1294: job.setStatus((Status) child);
1295: return true;
1296: } else if (child instanceof StatCall) {
1297: job.setExecutable((StatCall) child);
1298: return true;
1299: } else if (child instanceof Arguments) {
1300: job.setArguments((Arguments) child);
1301: return true;
1302: }
1303: }
1304: // unknown
1305: return false;
1306:
1307: //
1308: // E
1309: //
1310: case 'e':
1311: if (parent instanceof Environment
1312: && child instanceof EnvEntry) {
1313: ((Environment) parent).addEntry((EnvEntry) child);
1314: return true;
1315: }
1316:
1317: // unknown
1318: return false;
1319:
1320: //
1321: // I
1322: //
1323: case 'i':
1324: if (parent instanceof InvocationRecord) {
1325: InvocationRecord invocation = (InvocationRecord) parent;
1326: if (child instanceof Job) {
1327: invocation.addJob((Job) child);
1328: return true;
1329: } else if (child instanceof Usage) {
1330: invocation.setUsage((Usage) child);
1331: return true;
1332: } else if (child instanceof StatCall) {
1333: invocation.addStatCall((StatCall) child);
1334: return true;
1335: } else if (child instanceof WorkingDir) {
1336: invocation.setWorkingDirectory((WorkingDir) child);
1337: return true;
1338: } else if (child instanceof Architecture) {
1339: invocation.setArchitecture((Architecture) child);
1340: return true;
1341: } else if (child instanceof Environment) {
1342: invocation.setEnvironment((Environment) child);
1343: return true;
1344: }
1345: }
1346: // unknown
1347: return false;
1348:
1349: //
1350: // mainjob
1351: //
1352: case 'm':
1353: if (parent instanceof Job) {
1354: Job job = (Job) parent;
1355: if (child instanceof Usage) {
1356: job.setUsage((Usage) child);
1357: return true;
1358: } else if (child instanceof Status) {
1359: job.setStatus((Status) child);
1360: return true;
1361: } else if (child instanceof StatCall) {
1362: job.setExecutable((StatCall) child);
1363: return true;
1364: } else if (child instanceof Arguments) {
1365: job.setArguments((Arguments) child);
1366: return true;
1367: }
1368: }
1369: // unknown
1370: return false;
1371:
1372: //
1373: // P
1374: //
1375: case 'p':
1376: if (parent instanceof Job) {
1377: // both, prejob and postjob
1378: Job job = (Job) parent;
1379: if (child instanceof Usage) {
1380: job.setUsage((Usage) child);
1381: return true;
1382: } else if (child instanceof Status) {
1383: job.setStatus((Status) child);
1384: return true;
1385: } else if (child instanceof StatCall) {
1386: job.setExecutable((StatCall) child);
1387: return true;
1388: } else if (child instanceof Arguments) {
1389: job.setArguments((Arguments) child);
1390: return true;
1391: }
1392: }
1393:
1394: // unknown
1395: return false;
1396:
1397: //
1398: // R
1399: //
1400: case 'r':
1401: if (parent instanceof Ignore && child instanceof Ignore) {
1402: // ignore
1403: return true;
1404: }
1405:
1406: // unknown
1407: return false;
1408:
1409: //
1410: // S
1411: //
1412: case 's':
1413: if (parent instanceof Status && child instanceof JobStatus) {
1414: ((Status) parent).setJobStatus((JobStatus) child);
1415: return true;
1416: } else if (parent instanceof StatCall) {
1417: StatCall statcall = (StatCall) parent;
1418: if (child instanceof org.griphyn.vdl.invocation.File) {
1419: statcall
1420: .setFile((org.griphyn.vdl.invocation.File) child);
1421: return true;
1422: } else if (child instanceof StatInfo) {
1423: statcall.setStatInfo((StatInfo) child);
1424: return true;
1425: } else if (child instanceof Data) {
1426: statcall.setData((Data) child);
1427: return true;
1428: }
1429: } else if (parent instanceof Job) {
1430: // both, prejob and postjob
1431: Job job = (Job) parent;
1432: if (child instanceof Usage) {
1433: job.setUsage((Usage) child);
1434: return true;
1435: } else if (child instanceof Status) {
1436: job.setStatus((Status) child);
1437: return true;
1438: } else if (child instanceof StatCall) {
1439: job.setExecutable((StatCall) child);
1440: return true;
1441: } else if (child instanceof Arguments) {
1442: job.setArguments((Arguments) child);
1443: return true;
1444: }
1445: }
1446:
1447: // unknown
1448: return false;
1449:
1450: default:
1451: // FIXME: shouldn't this be an exception?
1452: m_log.log("filler", 0,
1453: "Error: unable to join child to parent");
1454: return false;
1455: }
1456: }
1457: }
|