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.cPlanner.parser;
0016:
0017: import org.griphyn.cPlanner.classes.Data;
0018: import org.griphyn.cPlanner.classes.PCRelation;
0019: import org.griphyn.cPlanner.classes.PegasusFile;
0020: import org.griphyn.cPlanner.classes.SubInfo;
0021:
0022: import org.griphyn.cPlanner.common.LogManager;
0023: import org.griphyn.cPlanner.common.PegasusProperties;
0024:
0025: import org.griphyn.cPlanner.namespace.Condor;
0026: import org.griphyn.cPlanner.namespace.Dagman;
0027: import org.griphyn.cPlanner.namespace.ENV;
0028: import org.griphyn.cPlanner.namespace.Globus;
0029: import org.griphyn.cPlanner.namespace.Hints;
0030: import org.griphyn.cPlanner.namespace.Namespace;
0031: import org.griphyn.cPlanner.namespace.VDS;
0032:
0033: import org.griphyn.cPlanner.parser.dax.Callback;
0034:
0035: import org.xml.sax.Attributes;
0036: import org.xml.sax.SAXException;
0037:
0038: import java.io.BufferedReader;
0039: import java.io.File;
0040: import java.io.FileReader;
0041:
0042: import java.util.HashMap;
0043: import java.util.LinkedList;
0044: import java.util.List;
0045: import java.util.StringTokenizer;
0046: import java.util.Vector;
0047: import java.util.Set;
0048: import java.util.HashSet;
0049:
0050: /**
0051: * This class parses the XML file whichis generated by Abstract Planner and ends
0052: * up making an ADag object which contains theinformation to make the Condor
0053: * submit files. The parser used to parse the file is Xerces.
0054: *
0055: * @author Karan Vahi
0056: * @author Gaurang Mehta
0057: * @version $Revision: 373 $
0058: *
0059: * @see org.griphyn.cPlanner.classes.SubInfo
0060: * @see org.griphyn.cPlanner.classes.DagInfo
0061: * @see org.griphyn.cPlanner.classes.ADag
0062: * @see org.griphyn.cPlanner.classes.PCRelation
0063: */
0064:
0065: public class DaxParser extends Parser {
0066:
0067: /**
0068: * The "not-so-official" location URL of the DAX schema definition.
0069: */
0070: public static final String SCHEMA_LOCATION = "http://pegasus.isi.edu/schema/dax-2.1.xsd";
0071:
0072: /**
0073: * URI namespace
0074: */
0075: public static final String SCHEMA_NAMESPACE = "http://pegasus.isi.edu/schema/DAX";
0076:
0077: /**
0078: * The constant designating the version when the double negative transfer
0079: * and registration flags were removed.
0080: */
0081: private static final String DAX_VERSION_WITHOUT_DOUBLE_NEGATIVE = "2.1";
0082:
0083: public String mDaxSchemaVersion;
0084:
0085: /**
0086: * A boolean variable set to true when we have got all the logical filenames.
0087: * After this all the filename tags are not added in Vector mLogicalFilesInADag
0088: * This is because the DAX file specifies all the input and output files
0089: * in the starting, and then in the job tags also the filename tags are nested.
0090: */
0091: private boolean infoAboutAllFilesRecv = false;
0092:
0093: /**
0094: * The handle to the class implementing the callback interface.
0095: */
0096: private Callback mCallback;
0097:
0098: /**
0099: * For holding the key attribute in profile tag.
0100: */
0101: private String mProfileKey = new String();
0102:
0103: /**
0104: * For holding the environment variables if specified in the Profile Element.
0105: *
0106: */
0107: private ENV mEnvNS;
0108:
0109: /**
0110: * Holds the extra options for Condor which maybe specified in the profile tags
0111: * with namespace Condor.
0112: */
0113: private Condor mCondorNS;
0114:
0115: /**
0116: * Objects that handle the various namespaces. For generating the rslstring
0117: * if specified.
0118: */
0119: private Globus mGlobusNS;
0120:
0121: /**
0122: * Holds the information got in the profile tag for hint namespace.
0123: */
0124: private Hints mHintNS;
0125:
0126: /**
0127: * Holds the information got in the profile tag for vds namespace.
0128: */
0129: private VDS mVdsNS;
0130:
0131: /**
0132: * Holds the information got in the profile tag for dagman namespace.
0133: */
0134: private Dagman mDagmanNS;
0135:
0136: /**
0137: * For holding the namespace if specified in the Profile Element.
0138: */
0139: private String mNamespace = new String();
0140:
0141: /**
0142: * Set as and when Profile and Argument tags are started and ended.
0143: * Need to in order to determine the nested filename tags which may appear in
0144: * these elements.
0145: */
0146: private boolean mProfileTag = false;
0147: private boolean mArgumentTag = false;
0148:
0149: /**
0150: * These store the current child element for the child parent relationship.
0151: * We get nested parent elements in a child element. Hence the child remains
0152: * the same while the parent id for the relationship varies.
0153: */
0154: private String mCurrentChildId = new String();
0155:
0156: /**
0157: * The list of parents of a node referred to by mCurrentChildId.
0158: */
0159: private List mParents;
0160:
0161: /**
0162: * Holds information regarding the current job being parsed. It's scope can
0163: * be seen as the job element.
0164: */
0165: private SubInfo mCurrentJobSubInfo = new SubInfo();
0166:
0167: /**
0168: * All the arguments to a particular job.
0169: */
0170: private String mWholeCommandString = new String();
0171:
0172: /**
0173: * Holds the input files for a particular job making the aDag. They are Vector
0174: * of PegasusFile Objects which store the transiency information of each
0175: * logical file.
0176: *
0177: * @see org.griphyn.cPlanner.classes.PegasusFile
0178: */
0179: private Set mVJobInpFiles = new HashSet();
0180:
0181: /**
0182: * Holds the output files for a particular job making the aDag.
0183: * They are vector of PegasusFile Objects which store the transiency
0184: * information of each logical file.
0185: *
0186: * @see org.griphyn.cPlanner.classes.PegasusFile
0187: */
0188: private Set mVJobOutFiles = new HashSet();
0189:
0190: /**
0191: * A boolean indicating whether to use the double negative flags for
0192: * transfer and register or not.
0193: */
0194: private boolean mUseDoubleNegative;
0195:
0196: /**
0197: * The default constructor
0198: *
0199: * @param properties the <code>PegasusProperties</code> to be used.
0200: */
0201: public DaxParser(PegasusProperties properties) { //default constructor
0202: super (properties);
0203: mGlobusNS = new Globus();
0204: mCondorNS = new Condor();
0205: mEnvNS = new ENV();
0206: mDagmanNS = new Dagman();
0207: mHintNS = new Hints();
0208: mVdsNS = new VDS();
0209: mUseDoubleNegative = false;
0210:
0211: }
0212:
0213: /**
0214: * The constructor initialises the parser, and turns on the validation feature
0215: * in Xerces.
0216: *
0217: * @param daxFileName the file which you want to parse.
0218: * @param properties the <code>PegasusProperties</code> to be used.
0219: * @param callback the object which implements the callback.
0220: */
0221: public DaxParser(String daxFileName, PegasusProperties properties,
0222: Callback callback) {
0223: super (properties);
0224:
0225: try {
0226: this .testForFile(daxFileName);
0227: } catch (Exception e) {
0228: throw new RuntimeException(e);
0229: }
0230:
0231: //try to get the version number
0232: //of the dax
0233: mDaxSchemaVersion = getVersionOfDAX(daxFileName);
0234: mLogger.log("Version of DAX as picked up from the DAX"
0235: + mDaxSchemaVersion, LogManager.DEBUG_MESSAGE_LEVEL);
0236: String schemaLoc = getSchemaLocation();
0237: mLogger.log("Picking schema for DAX" + schemaLoc,
0238: LogManager.CONFIG_MESSAGE_LEVEL);
0239: String list = DaxParser.SCHEMA_NAMESPACE + " " + schemaLoc;
0240: setSchemaLocations(list);
0241:
0242: //figure out whether to pick up the double negative flags or not
0243: mUseDoubleNegative = useDoubleNegative(mDaxSchemaVersion);
0244: mLogger.log(
0245: "Picking up the dontTransfer and dontRegister flags "
0246: + mUseDoubleNegative,
0247: LogManager.DEBUG_MESSAGE_LEVEL);
0248:
0249: mLogger.log("Parsing the DAX", LogManager.INFO_MESSAGE_LEVEL);
0250:
0251: mCurrentJobSubInfo.condorUniverse = "vanilla"; //default value
0252:
0253: //initialising the namespace handles
0254: mCondorNS = new Condor();
0255: mEnvNS = new ENV();
0256: mGlobusNS = new Globus();
0257: mDagmanNS = new Dagman();
0258: mHintNS = new Hints();
0259: mVdsNS = new VDS();
0260:
0261: mCallback = callback;
0262:
0263: startParser(daxFileName);
0264: mLogger.logCompletion("Parsing the DAX",
0265: LogManager.INFO_MESSAGE_LEVEL);
0266: }
0267:
0268: /**
0269: * This starts the parsing of the file by the parser.
0270: *
0271: * @param daxFileName the path/uri to the XML file you want to parse.
0272: */
0273: public void startParser(String daxFileName) {
0274: try {
0275: mParser.parse(daxFileName);
0276: } catch (Exception e) {
0277: //if a locator error then
0278: String message = (mLocator == null) ? "While parsing the file "
0279: + daxFileName
0280: : "While parsing file " + mLocator.getSystemId()
0281: + " at line " + mLocator.getLineNumber()
0282: + " at column "
0283: + mLocator.getColumnNumber();
0284: throw new RuntimeException(message, e);
0285: }
0286:
0287: }
0288:
0289: /**
0290: * Overriding the empty implementation provided by
0291: * DefaultHandler of ContentHandler. This receives the notification
0292: * from the sacks parser when start tag of an element comes
0293: */
0294: public void startElement(String uri, String local, String raw,
0295: Attributes attrs) throws SAXException {
0296:
0297: //setting the command line option only if textContent > 0
0298: if (mTextContent.length() > 0) {
0299: mWholeCommandString = mWholeCommandString
0300: .concat(new String(mTextContent));
0301: //System.out.println("\n Text Content is:" + new String(mTextContent));
0302: //resetting the buffer
0303: mTextContent.setLength(0);
0304: }
0305:
0306: //dealing with ADag tag
0307: if (local.trim().equalsIgnoreCase("adag")) {
0308: handleAdagTagStart(local, attrs);
0309: }
0310:
0311: //dealing with filename tags
0312: else if (local.trim().equalsIgnoreCase("filename")) {
0313: handleFilenameTagStart(local, attrs);
0314: }
0315:
0316: //dealing with the uses tag July 18
0317: else if (local.trim().equalsIgnoreCase("uses")) {
0318: handleUsesTagStart(local, attrs);
0319: }
0320:
0321: //dealing with the job tags
0322: else if (local.trim().equalsIgnoreCase("job")) {
0323: handleJobTagStart(local, attrs);
0324: }
0325:
0326: //dealing with profile tag
0327: else if (local.trim().equalsIgnoreCase("profile")) {
0328: handleProfileTagStart(local, attrs);
0329: }
0330:
0331: //dealing with the making of parent child relationship pairs
0332: else if (local.trim().equalsIgnoreCase("child")) {
0333: handleChildTagStart(local, attrs);
0334: } else if (local.trim().equalsIgnoreCase("parent")) {
0335: handleParentTagStart(local, attrs);
0336: }
0337:
0338: //dealing with the start of argument tag
0339: else if (local.trim().equalsIgnoreCase("argument")) {
0340: handleArgumentTagStart(local, attrs);
0341: }
0342:
0343: //dealing with stdout for current job
0344: else if (local.trim().equalsIgnoreCase("stdout")) {
0345: handleStdoutTagStart(local, attrs);
0346: }
0347:
0348: //dealing with stdin for current job
0349: else if (local.trim().equalsIgnoreCase("stdin")) {
0350: handleStdinTagStart(local, attrs);
0351: }
0352:
0353: //dealing with stderr for current job
0354: else if (local.trim().equalsIgnoreCase("stderr")) {
0355: handleStderrTagStart(local, attrs);
0356: }
0357:
0358: }
0359:
0360: /**
0361: * A convenience method that tries to determine the version of the dax
0362: * schema by reading ahead in the DAX file, and searching for
0363: * the version attribue in the file.
0364: *
0365: * @param file the name of the dax file.
0366: */
0367: public String getVersionOfDAX(String file) {
0368: String schema = getSchemaOfDocument(file);
0369: return extractVersionFromSchema(schema);
0370:
0371: }
0372:
0373: /**
0374: * Determines the version of the DAX as specified in a schema string.
0375: *
0376: * @param schema the schema string as specified in the root element of
0377: * the DAX.
0378: *
0379: * @return the version.
0380: */
0381: public String extractVersionFromSchema(String schema) {
0382: String token = null;
0383: String version = null;
0384:
0385: if (schema == null)
0386: return null;
0387:
0388: StringTokenizer st = new StringTokenizer(schema);
0389: while (st.hasMoreTokens()) {
0390: token = st.nextToken();
0391: if (token.endsWith(".xsd")) {
0392: //we got our match
0393: String name = new File(token).getName();
0394: int p1 = name.indexOf("dax-");
0395: int p2 = name.lastIndexOf(".xsd");
0396: //extract the version number
0397: version = ((p1 > -1) && (p2 > -1)) ? name.substring(
0398: p1 + 4, p2) : null;
0399: return version;
0400:
0401: }
0402: }
0403:
0404: mLogger.log(
0405: "Could not find the version number in DAX schema name",
0406: LogManager.WARNING_MESSAGE_LEVEL);
0407: return version;
0408:
0409: }
0410:
0411: /**
0412: * A convenience method that tries to get the name of the schema the document
0413: * refers to. It returns the value of the xsi:schemaLocation.
0414: *
0415: * @param file the name of the dax file.
0416: */
0417: public String getSchemaOfDocument(String file) {
0418: StringTokenizer st = null;
0419: String key = null;
0420: String value = null;
0421:
0422: try {
0423: BufferedReader in = new BufferedReader(new FileReader(file));
0424: String line = null;
0425: int p1, p2, c = 0;
0426:
0427: while ((line = (in.readLine()).trim()) != null) {
0428:
0429: if (c == 0) {
0430: //try to check if it is an xml file
0431: if (((p1 = line.indexOf("<?xml")) > -1)
0432: && ((p2 = line.indexOf("?>", p1)) > -1)) {
0433: //xml file is valid.
0434: c++;
0435:
0436: } else {
0437: //throw a exception
0438: throw new java.lang.RuntimeException(
0439: "Dax File is not xml " + file);
0440: }
0441:
0442: } else {
0443: if ((p1 = line.indexOf("<adag")) > -1) {
0444: line = line.substring(p1 + "<adag".length());
0445: c++;
0446:
0447: } else {
0448: if (c < 2)
0449: //goto next line
0450: continue;
0451: }
0452:
0453: st = new StringTokenizer(line, "= \"");
0454: while (st.hasMoreTokens()) {
0455: c++;
0456: if (c % 2 == 1) {
0457: key = st.nextToken().trim();
0458: } else {
0459: if (key
0460: .equalsIgnoreCase("xsi:schemaLocation")) {
0461: value = st.nextToken("=\"");
0462: return value;
0463: } else {
0464: value = st.nextToken();
0465: }
0466:
0467: }
0468:
0469: }
0470: }
0471: }
0472: } catch (java.io.IOException e) {
0473: mLogger.log("Parsing the dax file for version number "
0474: + " :" + e.getMessage(),
0475: LogManager.ERROR_MESSAGE_LEVEL);
0476:
0477: }
0478: return null;
0479:
0480: }
0481:
0482: /**
0483: * Invoked when the starting of the adag element is got.
0484: * Information received is
0485: * name : the name of the ADag
0486: * count: Chimera can generate multiple abstract dags for a request.
0487: * index: what is the index of the ADag being passed. Should
0488: * vary between 0 and count - 1.
0489: */
0490: private void handleAdagTagStart(String local, Attributes attrs) {
0491: HashMap mp = new HashMap();
0492: String key;
0493: String value;
0494:
0495: for (int i = 0; i < attrs.getLength(); i++) {
0496: key = attrs.getLocalName(i);
0497: value = attrs.getValue(i);
0498: //should probably check for valid attributes before setting
0499: mp.put(key, value);
0500: //System.out.println(key + " --> " + value);
0501: }
0502: //call the callback interface
0503: mCallback.cbDocument(mp);
0504:
0505: }
0506:
0507: /**
0508: * Invoked when the starting of the filename element is got.
0509: */
0510: private void handleFilenameTagStart(String local, Attributes attrs) {
0511: String linkType = new String(); //holds the link info about a logical file corr to a job
0512: String fileName = new String();
0513: String isTemp = new String();
0514:
0515: fileName = attrs.getValue("", "file").trim();
0516:
0517: PegasusFile pf = new PegasusFile(fileName);
0518:
0519: if (!infoAboutAllFilesRecv) {
0520: //this means we are dealing with filename tags in
0521: //the starting of the dax. These tags
0522: //contain the linkage information
0523: //logicalFilesInADag.addElement(fileName);
0524:
0525: /*
0526: Now linkage information is only gotten from the individual jobs.
0527:
0528: linkType = attrs.getValue("", "link").trim();
0529:
0530: String type = "n";
0531:
0532: //adding logical i/p and o/p files for the ADAG
0533: if (linkType.equalsIgnoreCase("input")) {
0534: mVADagInputFiles.addElement(pf);
0535: type = "i";
0536: }
0537: else if (linkType.equalsIgnoreCase("output")) {
0538: mVADagOutputFiles.addElement(pf);
0539: type = "o";
0540: }
0541: else if (linkType.equalsIgnoreCase("inout")) {
0542: mVADagInputFiles.addElement(pf);
0543: mVADagOutputFiles.addElement(pf);
0544: type = "b";
0545: }
0546:
0547: //putting the filename and the
0548: //type information in the map
0549: mDagInfo.lfnMap.put(fileName,type);
0550: */
0551: } else if (mArgumentTag) {
0552: //means that the filename tag is nested in
0553: //an argument tag. Since dax 1.6
0554: //no linkage information comes
0555: //in this.
0556: mWholeCommandString = mAdjFName ?
0557: //as per the default behaviour adding
0558: //a whitespace between two adjacent
0559: //filename tags
0560: mWholeCommandString + " " + fileName
0561: :
0562: //else doing a simple concatenation
0563: mWholeCommandString + fileName;
0564:
0565: mAdjFName = true;
0566: }
0567: //dealing with profile tags
0568: else if (mProfileTag) { //means that filename tag is nested in a profile tag
0569: fileName = attrs.getValue("", "file");
0570:
0571: //an extra check
0572: if (mNamespace.equalsIgnoreCase("env")) {
0573: mEnvNS.checkKeyInNS(mProfileKey, fileName);
0574: }
0575: }
0576:
0577: } //end of dealing with fileName tags in argument tag
0578:
0579: /**
0580: * Invoked when the starting of the uses element is got. Uses tag is used to
0581: * denote all the files a particular job uses, be it as input , output or
0582: * silent.
0583: */
0584: private void handleUsesTagStart(String local, Attributes attrs) {
0585: String fileName = attrs.getValue("", "file");
0586: String linkType = attrs.getValue("", "link");
0587: String isTemp = attrs.getValue("", "isTemporary");
0588: String type = attrs.getValue("", "type");
0589: //since dax 1.6, the isTemporary
0590: //is broken into two transient
0591: //attributes dontTransfer and dontRegister
0592: // System.out.println( "DontRegister is " + attrs.getValue("","dontRegister") );
0593: // System.out.println( "Register is " + attrs.getValue("","register") );
0594:
0595: //pick up the registration flag
0596: boolean register = (mUseDoubleNegative) ?
0597: //pick up the dR flag
0598: !new Boolean(attrs.getValue("", "dontRegister")).booleanValue()
0599: :
0600: //pick up the register flag
0601: new Boolean(attrs.getValue("", "register"))
0602: .booleanValue();
0603:
0604: //boolean dontRegister = new Boolean(attrs.getValue("","dontRegister")).booleanValue();
0605:
0606: //notion of optional file since dax 1.8
0607: boolean optionalFile = new Boolean(attrs.getValue("",
0608: "optional")).booleanValue();
0609:
0610: //value of dontTransfer is tri state (true,false,optional) since dax 1.7
0611: String transfer = (mUseDoubleNegative) ? attrs.getValue("",
0612: "dontTransfer") : attrs.getValue("", "transfer");
0613: //String dontTransfer = attrs.getValue("","dontTransfer");
0614: PegasusFile pf = new PegasusFile(fileName);
0615:
0616: //handling the transient file feature
0617: if (isTemp != null) {
0618: //this for dax 1.5 handling
0619: boolean temp = new Boolean(isTemp.trim()).booleanValue();
0620: if (temp) {
0621: //set the transient flags
0622: pf.setTransferFlag(PegasusFile.TRANSFER_NOT);
0623: register = false;
0624: }
0625: } else {
0626: //set the transfer mode for the file
0627: //for dax 1.5 onwards
0628: pf.setTransferFlag(transfer, mUseDoubleNegative);
0629: }
0630: //handling the dR flag
0631: if (!register)
0632: pf.setTransientRegFlag();
0633:
0634: //handling the optional attribute
0635: if (optionalFile)
0636: pf.setFileOptional();
0637:
0638: //handle type of file
0639: if (type != null)
0640: pf.setType(type);
0641:
0642: //adding the file to input vector or the output vector
0643: if (linkType.trim().equalsIgnoreCase("input")) {
0644: mVJobInpFiles.add(pf);
0645: } else if (linkType.trim().equalsIgnoreCase("output")) {
0646: mVJobOutFiles.add(pf);
0647: //the notion of an optional file as an output would mean it
0648: //has the optional transfer flag set.
0649: if (pf.fileOptional()
0650: && pf.getTransferFlag() == PegasusFile.TRANSFER_MANDATORY) {
0651: //update the transfer flag to optional
0652: pf.setTransferFlag(PegasusFile.TRANSFER_OPTIONAL);
0653: }
0654: } else if (linkType.trim().equalsIgnoreCase("inout")) {
0655: mVJobInpFiles.add(pf);
0656: mVJobOutFiles.add(pf);
0657: }
0658:
0659: }
0660:
0661: /**
0662: * Invoked when the starting of the job element is got. The following
0663: * information is got from the tag
0664: *
0665: * name : name of the job, which is the logical name of the job.
0666: * namespace : the namespace with which the transformation corresponding to
0667: * the job is associated.
0668: * version : the version of the transformation.
0669: */
0670: private void handleJobTagStart(String local, Attributes attrs) {
0671: String jobId = new String();
0672: String jobName = attrs.getValue("", "name");
0673:
0674: mCurrentJobSubInfo = new SubInfo();
0675: mCurrentJobSubInfo.condorUniverse = "vanilla";
0676: mCurrentJobSubInfo.namespace = attrs.getValue("", "namespace");
0677: mCurrentJobSubInfo.version = attrs.getValue("", "version");
0678: mCurrentJobSubInfo.dvName = attrs.getValue("", "dv-name");
0679: mCurrentJobSubInfo.dvNamespace = attrs.getValue("",
0680: "dv-namespace");
0681: mCurrentJobSubInfo.dvVersion = attrs.getValue("", "dv-version");
0682: mCurrentJobSubInfo.level = (attrs.getValue("", "level") == null) ? -1
0683: : Integer.parseInt(attrs.getValue("", "level"));
0684: mCurrentJobSubInfo.logicalName = jobName;
0685:
0686: infoAboutAllFilesRecv = true;
0687:
0688: jobId = attrs.getValue("", "id");
0689: mCurrentJobSubInfo.logicalId = jobId;
0690: mLogger.log("Parsing job with logical id " + jobId,
0691: LogManager.DEBUG_MESSAGE_LEVEL);
0692:
0693: //mvJobIds.addElement(jobId);
0694:
0695: //concatenating jobname and id into job name
0696: jobName = jobName.concat("_");
0697: jobName = jobName.concat(jobId);
0698:
0699: mCurrentJobSubInfo.jobName = jobName;
0700: //mvJobsInADag.addElement(jobName);
0701:
0702: }
0703:
0704: /**
0705: * Invoked when the end of the job tag is reached.
0706: */
0707: private void handleJobTagEnd() {
0708: //adding the information about the job to mCurrentJobSubInfo
0709: mCurrentJobSubInfo.setInputFiles(mVJobInpFiles);
0710: mCurrentJobSubInfo.setOutputFiles(mVJobOutFiles);
0711:
0712: //update the namespaces information
0713: //that is gotten through the profiles.
0714: mCurrentJobSubInfo.envVariables = mEnvNS;
0715: mCurrentJobSubInfo.hints = mHintNS;
0716: mCurrentJobSubInfo.condorVariables = mCondorNS;
0717: mCurrentJobSubInfo.dagmanVariables = mDagmanNS;
0718: mCurrentJobSubInfo.vdsNS = mVdsNS;
0719: mCurrentJobSubInfo.globusRSL = mGlobusNS; // shallow copy!
0720:
0721: //The job id for the compute jobs
0722: //is the name of the job itself.
0723: //All the jobs in the DAX are
0724: //compute jobs
0725: mCurrentJobSubInfo.jobClass = SubInfo.COMPUTE_JOB;
0726: mCurrentJobSubInfo.jobID = mCurrentJobSubInfo.jobName;
0727:
0728: //send the job to the appropriate callback implementing class
0729: mCallback.cbJob(mCurrentJobSubInfo);
0730:
0731: //reset the variables
0732: mCondorNS = new Condor();
0733: mGlobusNS = new Globus();
0734: mVdsNS = new VDS();
0735: mEnvNS = new ENV();
0736: mHintNS = new Hints();
0737: mDagmanNS = new Dagman();
0738:
0739: mVJobInpFiles = new HashSet();
0740: mVJobOutFiles = new HashSet();
0741:
0742: }
0743:
0744: /**
0745: * Invoked when the starting of the profile element is got.
0746: */
0747: private void handleProfileTagStart(String local, Attributes attrs) {
0748: mProfileKey = attrs.getValue("key");
0749: mNamespace = attrs.getValue("namespace");
0750: mProfileTag = true;
0751: }
0752:
0753: /**
0754: * Invoked when the end of the profile element is got.
0755: *
0756: * Here we handle all the namespaces supported by Chimera at present.
0757: */
0758: private void handleProfileTagEnd() {
0759: mProfileTag = false;
0760:
0761: //setting the command line option only if textContent > 0
0762: if (mTextContent.length() > 0) {
0763:
0764: //check if namespace is valid
0765: mNamespace = mNamespace.toLowerCase();
0766: if (!Namespace.isNamespaceValid(mNamespace)) {
0767: //reset buffer
0768: mTextContent.setLength(0);
0769: mLogger.log(
0770: "Namespace specified in the DAX not supported. ignoring "
0771: + mNamespace,
0772: LogManager.WARNING_MESSAGE_LEVEL);
0773: return;
0774: }
0775:
0776: switch (mNamespace.charAt(0)) {
0777:
0778: case 'c'://condor
0779: mCondorNS.checkKeyInNS(mProfileKey, mTextContent
0780: .toString().trim());
0781: break;
0782:
0783: case 'd'://dagman
0784: mDagmanNS.checkKeyInNS(mProfileKey, mTextContent
0785: .toString().trim());
0786: break;
0787:
0788: case 'e'://env
0789: mEnvNS.checkKeyInNS(mProfileKey, mTextContent
0790: .toString().trim());
0791: break;
0792:
0793: case 'g'://globus
0794: mGlobusNS.checkKeyInNS(mProfileKey, mTextContent
0795: .toString().trim());
0796: break;
0797:
0798: case 'h'://hint
0799: mHintNS.checkKeyInNS(mProfileKey, mTextContent
0800: .toString().trim());
0801: break;
0802:
0803: case 'p'://pegasus
0804: mVdsNS.checkKeyInNS(mProfileKey, mTextContent
0805: .toString().trim());
0806: break;
0807:
0808: default:
0809: //ignore should not come here ever.
0810: mLogger.log("Namespace not supported. ignoring "
0811: + mNamespace, LogManager.WARNING_MESSAGE_LEVEL);
0812: break;
0813:
0814: }
0815:
0816: //resetting the buffer
0817: mTextContent.setLength(0);
0818: mProfileKey = "";
0819: mNamespace = "";
0820:
0821: }
0822: }
0823:
0824: /**
0825: * Invoked when the starting of the child element is got. The child element
0826: * gives us the child of an edge of the dag. The edge being parent->child.
0827: */
0828: private void handleChildTagStart(String local, Attributes attrs) {
0829: mCurrentChildId = "";
0830: mCurrentChildId = attrs.getValue("", "ref");
0831: mParents = new LinkedList();
0832: }
0833:
0834: /**
0835: * This passes the child and it's parents list to the callback object.
0836: */
0837: private void handleChildTagEnd() {
0838: //String childName = lookupName(mCurrentChildId);
0839: mCallback.cbParents(mCurrentChildId, mParents);
0840: }
0841:
0842: /**
0843: * Invoked when the starting of the parent element is got. The child element
0844: * gives us the child of an edge of the dag. The edge being parent->child.
0845: */
0846: private void handleParentTagStart(String local, Attributes attrs) {
0847: //stores the child parent Relation
0848: PCRelation parentChildRelation = new PCRelation();
0849:
0850: String childName = new String();
0851: String parentName = new String();
0852: String parentId = attrs.getValue("", "ref");
0853:
0854: //looking up the parent name
0855: //parentName = lookupName(parentId);
0856: mParents.add(parentId);
0857: }
0858:
0859: /**
0860: * Invoked when the starting of the Argument Tag is reached. Just set a
0861: * boolean variable
0862: */
0863: private void handleArgumentTagStart(String local, Attributes attrs) {
0864: //setting the boolean variable.
0865: mArgumentTag = true;
0866: //set the adjacency flag for
0867: //adjacent filename to false
0868: mAdjFName = false;
0869: }
0870:
0871: /**
0872: * Invoked when the end of the Argument Tag is reached.
0873: *
0874: * The buffers are reset
0875: */
0876: private void handleArgumentTagEnd() {
0877: mArgumentTag = false;
0878: mWholeCommandString = mWholeCommandString.concat(new String(
0879: mTextContent));
0880:
0881: mWholeCommandString = this
0882: .ignoreWhitespace(mWholeCommandString);
0883: //adding the commmand string
0884: mCurrentJobSubInfo.strargs = new String(mWholeCommandString);
0885:
0886: //resetting mWholeCommandString
0887: mWholeCommandString = "";
0888:
0889: //resetting the buffer
0890: mTextContent.setLength(0);
0891:
0892: }
0893:
0894: /**
0895: * Invoked when the starting of the stdout tag is reached.
0896: * Used to specify the stdout of the application by the user. It can be
0897: * a file also.
0898: */
0899: private void handleStdoutTagStart(String local, Attributes attrs) {
0900: mCurrentJobSubInfo.stdOut = attrs.getValue("", "file");
0901: }
0902:
0903: /**
0904: * Invoked when the starting of the stdin tag is reached.
0905: * Used to specify the stdout of the application by the user. It can be
0906: * a file also.
0907: */
0908: private void handleStdinTagStart(String local, Attributes attrs) {
0909: mCurrentJobSubInfo.stdIn = attrs.getValue("", "file");
0910: }
0911:
0912: /**
0913: * Invoked when the starting of the stdout tag is reached.
0914: * Used to specify the stderr of the application by the user. It can be
0915: * a file also.
0916: */
0917: private void handleStderrTagStart(String local, Attributes attrs) {
0918: mCurrentJobSubInfo.stdErr = attrs.getValue("", "file");
0919: }
0920:
0921: /**
0922: * Overrides the default implementation when the elements end tag comes.
0923: * This method is called automatically by the Sax parser when the end tag of
0924: * an element comes in the xml file.
0925: */
0926:
0927: public void endElement(String uri, String localName, String qName) {
0928: /*System.out.println("element end tag ---------");
0929: System.out.println("line number "+ locator.getLineNumber());
0930: System.out.println("URI: "+ uri);
0931: System.out.println("local name " + localName);
0932: System.out.println("qname: "+qName);*/
0933:
0934: boolean temp = true;
0935: String universe = "vanilla"; //by default jobs are vanilla
0936:
0937: //when we get the end tag of argument, we change reset the currentCommOpt
0938: if (localName.equals("argument")) { // || localName.trim().equalsIgnoreCase("job")){
0939: handleArgumentTagEnd();
0940: } else if (localName.equals("job")) {
0941: handleJobTagEnd();
0942: } else if (localName.equals("profile")) {
0943: handleProfileTagEnd();
0944: } else if (localName.equals("child")) {
0945: handleChildTagEnd();
0946: } else if (localName.equals("adag")) {
0947: //call the callback interface
0948: mCallback.cbDone();
0949: return;
0950: }
0951: }
0952:
0953: /**
0954: * Here we have all the elements in our data structure. This is called
0955: * automatically when the end of the XML file is reached.
0956: */
0957: public void endDocument() {
0958:
0959: }
0960:
0961: /**
0962: * The main program. The DaxParser can be run standalone, by which it just
0963: * parses the file and populates the required data objects.
0964: *
0965: */
0966:
0967: public static void main(String args[]) {
0968: //System.setProperty("vds.home","/nfs/asd2/vahi/test/chimera/");
0969: //DaxParser d = new DaxParser("sdss.xml","isi",null);
0970: //DaxParser d = new DaxParser("sonal.xml",new DAX2CDAG("./sonal.xml"));
0971: //DaxParser d = new DaxParser("./testcases/black-diamond/blackdiamond_dax_1.7.xml");
0972: //DaxParser d = new DaxParser("/nfs/asd2/vahi/gurmeet_dax.xml");
0973:
0974: /*DagInfo dagInfo = d.getDagInfo();
0975:
0976: Vector vSubInfo = d.getSubInfo();
0977:
0978: ADag adag = new ADag(dagInfo, vSubInfo);
0979:
0980: System.out.println(adag);
0981: */
0982:
0983: }
0984:
0985: /**
0986: * Helps the load database to locate the DAX XML schema, if available.
0987: * Please note that the schema location URL in the instance document
0988: * is only a hint, and may be overriden by the findings of this method.
0989: *
0990: * @return a location pointing to a definition document of the XML
0991: * schema that can read VDLx. Result may be null, if such a document
0992: * is unknown or unspecified.
0993: */
0994: public String getSchemaLocation() {
0995: // treat URI as File, yes, I know - I need the basename
0996: File uri = new File(DaxParser.SCHEMA_LOCATION);
0997:
0998: //get the default version with decimal point shifted right
0999: float defaultVersion = shiftRight(extractVersionFromSchema(uri
1000: .getName()));
1001:
1002: float schemaVersion = shiftRight(mDaxSchemaVersion);
1003:
1004: String child = (schemaVersion == -1 || schemaVersion > defaultVersion) ?
1005: //use the default
1006: uri.getName()
1007: :
1008: //use the schema version specified in the dax
1009: "dax-" + mDaxSchemaVersion + ".xsd";
1010:
1011: // create a pointer to the default local position
1012: File dax = new File(this .mProps.getSysConfDir(), child);
1013:
1014: //System.out.println("\nDefault Location of Dax is " + dax.getAbsolutePath());
1015:
1016: // Nota bene: vds.schema.dax may be a networked URI...
1017: return this .mProps.getDAXSchemaLocation(dax.getAbsolutePath());
1018: }
1019:
1020: /**
1021: * Determines whether to use a doubleNegative or not.
1022: *
1023: * @param daxVersion the version of the dax as determined.
1024: *
1025: * @return boolean
1026: */
1027: protected boolean useDoubleNegative(String daxVersion) {
1028: float current = shiftRight(daxVersion);
1029: boolean result = false;
1030: //sanity check
1031: if (current == -1) {
1032: //we were unable to parse the dax version
1033: //means we assume double negative is turned off
1034: return result;
1035: }
1036:
1037: float base = shiftRight(this .DAX_VERSION_WITHOUT_DOUBLE_NEGATIVE);
1038:
1039: //we turned off double negative after >= base
1040: return base > current;
1041: }
1042:
1043: /**
1044: * Returns a float with the decimal point shifted right till the end.
1045: * Is necessary for comparing a String "1.10" with a String "1.9".
1046: *
1047: * @param value the value that has to be shifted right.
1048: *
1049: * @return the float value, with the decimal point shifted or -1 in case
1050: * of error.
1051: */
1052: public float shiftRight(String value) {
1053: float result = -1;
1054:
1055: //sanity check in case of null value
1056: if (value == null)
1057: return result;
1058:
1059: value = value.trim();
1060: int i = 0;
1061: for (i = 0; i < value.length(); i++) {
1062: char c = value.charAt(i);
1063:
1064: //parse till the first '.'
1065: if (c >= '0' && c <= '9') {
1066: continue;
1067: } else if (c == '.') {
1068: i++;
1069: break;
1070: } else {
1071: //invalid string
1072: return result;
1073: }
1074: }
1075:
1076: //determine the multiplicative factor
1077: int factor = 1;
1078: for (i = i; i < value.length(); i++, factor *= 10) {
1079: char c = value.charAt(i);
1080:
1081: //exit if any of the trailing characters are non digits
1082: if (!(c >= '0' && c <= '9'))
1083: return result;
1084: }
1085:
1086: result = Float.parseFloat(value) * factor;
1087:
1088: return result;
1089: }
1090:
1091: }
|