001: /*
002: * This file or a portion of this file is licensed under the terms of
003: * the Globus Toolkit Public License, found in file GTPL, or at
004: * http://www.globus.org/toolkit/download/license.html. This notice must
005: * appear in redistributions of this file, with or without modification.
006: *
007: * Redistributions of this Software, with or without modification, must
008: * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
009: * some other similar material which is provided with the Software (if
010: * any).
011: *
012: * Copyright 1999-2004 University of Chicago and The University of
013: * Southern California. All rights reserved.
014: */
015: package org.griphyn.vdl.toolkit;
016:
017: import java.io.*;
018: import java.sql.SQLException;
019: import java.util.regex.*;
020: import java.util.List;
021: import java.util.ArrayList;
022: import java.util.Set;
023: import java.util.TreeSet;
024: import java.util.StringTokenizer;
025: import java.util.Iterator;
026: import org.griphyn.common.util.Version;
027: import org.griphyn.common.util.Separator;
028: import org.griphyn.vdl.parser.VDLxParser;
029: import org.griphyn.vdl.classes.*;
030: import org.griphyn.vdl.parser.*;
031: import org.griphyn.vdl.router.*;
032: import org.griphyn.vdl.dbschema.*;
033: import org.griphyn.vdl.util.Logging;
034: import org.griphyn.vdl.util.ChimeraProperties;
035: import org.griphyn.vdl.dbschema.*;
036: import org.griphyn.vdl.directive.*;
037: import gnu.getopt.*;
038:
039: /**
040: * This class generates implements the pipeline of the usual suspect
041: * from vdlt2vdlx via insert- or updatevdc to gendax.
042: *
043: * @author Jens-S. Vöckler
044: * @author Yong Zhao
045: * @version $Revision: 50 $
046: *
047: * @see org.griphyn.vdl.parser.VDLtParser
048: * @see org.griphyn.vdl.parser.VDLxParser
049: * @see org.griphyn.vdl.router.Route
050: * @see org.griphyn.vdl.router.BookKeeper
051: */
052: public class VDLc extends VDLHelper {
053: /**
054: * ctor: Constructs a new instance object with the given application name.
055: */
056: public VDLc(String appName) {
057: super (appName);
058: }
059:
060: /**
061: * Implements printing the usage string onto stdout.
062: */
063: public void showUsage() {
064: String linefeed = System.getProperty("line.separator", "\r\n");
065:
066: System.out
067: .println("$Id: VDLc.java 50 2007-05-19 00:48:32Z gmehta $"
068: + linefeed
069: + "VDS version "
070: + Version.instance().toString() + linefeed);
071:
072: System.out.println("Usage: " + this .m_application + ' '
073: + "[options] vdlt|vdlx [..]");
074:
075: System.out
076: .println(linefeed
077: + "Generic options: "
078: + linefeed
079: + " -V|--version print version information and exit."
080: + linefeed
081: + " -d|--dbase dbx associates the dbname with the database, unused."
082: + linefeed
083: + " --verbose increases the verbosity level."
084: + linefeed
085: + " -n|--vdlns ns generates default namespace ns, default is none."
086: + linefeed
087: + " -v|--vdlvs vs generates default version vs, default is none."
088: + linefeed
089: + " -i|--insert insert into the VDC instead of trying to update."
090: + linefeed
091: + " -r|--rejects fn gathers the rejected definitions into file fn."
092: + linefeed
093: + " -l|--label label uses the specified label for the output DAX."
094: + linefeed
095: + " -o|--output DAX writes the generated results into outfn, use - for stdout."
096: + linefeed
097: + " -e|--empty empty output DAX is not an error."
098: + linefeed
099: + " -m|--maxdepth max only search up to the specified depth, default is "
100: + Route.MAXIMUM_DEPTH
101: + "."
102: + linefeed
103: + " For complex or large graphs, you may want to increase this."
104: + linefeed
105: + " -X|--xmlns prefix uses an XML namespace prefix for the generated DAX document."
106: + linefeed
107: + linefeed
108: + "Request refining arguments: "
109: + linefeed
110: + " -D|--dv dv[,..] requests the DV or list of DVs to be produced. Each argument"
111: + linefeed
112: + " is a fully-qualified derivation name namespace::name:version."
113: + linefeed
114: + " In absence of this argument, all DVs seen will be requested."
115: + linefeed
116: + " -D|--derivation is a synonym for the --dv option."
117: + linefeed
118: + " -L|--dvlist lodvs read the DVs from file lodvs, one per line."
119: + linefeed
120: + " -f|--file fn[,..] requests LFN or a list of LFNs to be materialized."
121: + linefeed
122: + " -f|--lfn is a synonym for the --file option."
123: + linefeed
124: + " -F|--filelist lof read the LFNs from file lof, one per line."
125: + linefeed
126: + linefeed
127: + "Mandatory argument(s): "
128: + linefeed
129: + " vdlt One or more files containing VDLt or VDLx."
130: + linefeed);
131:
132: System.out
133: .println("The following exit codes are produced:"
134: + linefeed
135: + " 0 :-) Success"
136: + linefeed
137: + " 1 :-| Empty result while "
138: + m_application
139: + " still ran successfully (but see --empty)."
140: + linefeed
141: + " 2 :-( Runtime error detected by "
142: + m_application
143: + ", please read the message."
144: + linefeed
145: + " 3 8-O Fatal error merits a program abortion. Please carefully check your"
146: + linefeed
147: + " configuration files and setup before filing a bug report."
148: + linefeed);
149: }
150:
151: /**
152: * Creates a set of options.
153: */
154: protected LongOpt[] generateValidOptions() {
155: LongOpt[] lo = new LongOpt[] {
156: new LongOpt("dbase", LongOpt.REQUIRED_ARGUMENT, null,
157: 'd'),
158: new LongOpt("version", LongOpt.NO_ARGUMENT, null, 'V'),
159: new LongOpt("help", LongOpt.NO_ARGUMENT, null, 'h'),
160: new LongOpt("verbose", LongOpt.NO_ARGUMENT, null, 1),
161: new LongOpt("empty", LongOpt.NO_ARGUMENT, null, 'e'),
162:
163: new LongOpt("vdlvs", LongOpt.REQUIRED_ARGUMENT, null,
164: 'v'),
165: new LongOpt("vdlns", LongOpt.REQUIRED_ARGUMENT, null,
166: 'n'),
167: new LongOpt("rejects", LongOpt.REQUIRED_ARGUMENT, null,
168: 'r'),
169: new LongOpt("insert", LongOpt.NO_ARGUMENT, null, 'i'),
170: new LongOpt("label", LongOpt.REQUIRED_ARGUMENT, null,
171: 'l'),
172: new LongOpt("output", LongOpt.REQUIRED_ARGUMENT, null,
173: 'o'),
174: new LongOpt("maxdepth", LongOpt.REQUIRED_ARGUMENT,
175: null, 'm'),
176: new LongOpt("xmlns", LongOpt.REQUIRED_ARGUMENT, null,
177: 'X'),
178:
179: new LongOpt("derivation", LongOpt.REQUIRED_ARGUMENT,
180: null, 'D'),
181: new LongOpt("dv", LongOpt.REQUIRED_ARGUMENT, null, 'D'),
182: new LongOpt("dvlist", LongOpt.REQUIRED_ARGUMENT, null,
183: 'L'),
184: new LongOpt("file", LongOpt.REQUIRED_ARGUMENT, null,
185: 'f'),
186: new LongOpt("lfn", LongOpt.REQUIRED_ARGUMENT, null, 'f'),
187: new LongOpt("filelist", LongOpt.REQUIRED_ARGUMENT,
188: null, 'F') };
189: return lo;
190: }
191:
192: /**
193: * Tries a stab at the basename w/o suffix of the filename.
194: *
195: * @param fn is the filename from the command-line args
196: * @return a basename or null.
197: */
198: public String guessBasename(String fn) {
199: String base = (new File(fn)).getName();
200: if (base.length() == 0)
201: return null;
202:
203: int dot = base.lastIndexOf('.');
204: return (dot == -1 ? base : base.substring(0, dot));
205: }
206:
207: /**
208: * Tries a stab at the basename w/o suffix of the filename.
209: *
210: * @param fn is the filename from the command-line args
211: * @return a basename or null.
212: */
213: public String guessDaxname(String fn) {
214: String base = (new File(fn)).getName();
215: if (base.length() == 0)
216: return null;
217:
218: int dot = base.lastIndexOf('.');
219: return (dot < 0 ? base : base.substring(0, dot)) + ".dax";
220: }
221:
222: /**
223: * Processes the VDLt file(s) into DAX file by requesting each DV
224: * found in the VDLt.
225: *
226: * @param args commandline arguments
227: */
228: public static void main(String[] args) {
229: int result = 0;
230: VDLc me = null;
231:
232: try {
233: me = new VDLc("vdlc");
234: if (args.length == 0) {
235: me.showUsage();
236: return;
237: }
238:
239: // get the commandline options
240: Getopt opts = new Getopt(me.m_application, args,
241: "D:F:L:VX:hd:f:m:n:o:r:l:uv:e", me
242: .generateValidOptions());
243: opts.setOpterr(false);
244:
245: String vdlns = null;
246: String vdlvs = null;
247: String xmlns = null;
248: String label = null;
249: String dbase = null;
250: String outputFilename = null;
251: int maxdepth = -1;
252: String rejectFilename = null; // reject file
253: boolean overwrite = true; // --force
254: java.util.Set derivations = new java.util.HashSet();
255: java.util.Set filenames = new java.util.HashSet();
256: boolean emptydaxok = false;
257:
258: String arg = null;
259: int option = 0;
260: while ((option = opts.getopt()) != -1) {
261: switch (option) {
262: case 1:
263: me.increaseVerbosity();
264: break;
265:
266: case 'D':
267: arg = opts.getOptarg();
268: if (arg != null) {
269: StringTokenizer st = new StringTokenizer(arg,
270: ",", false);
271: while (st.hasMoreTokens())
272: derivations.add(st.nextToken());
273: }
274: break;
275:
276: case 'F':
277: arg = opts.getOptarg();
278: if (arg != null) {
279: int nr = me.readFile(arg, filenames);
280: me.m_logger.log("app", 1, "read " + nr
281: + " LFNs from " + arg);
282: }
283: break;
284:
285: case 'L':
286: arg = opts.getOptarg();
287: if (arg != null) {
288: int nr = me.readFile(arg, derivations);
289: me.m_logger.log("app", 1, "read " + nr
290: + " DV names from " + arg);
291: }
292: break;
293:
294: case 'V':
295: System.out
296: .println("$Id: VDLc.java 50 2007-05-19 00:48:32Z gmehta $");
297: System.out.println("VDS version "
298: + Version.instance().toString());
299: return;
300:
301: case 'X':
302: xmlns = opts.getOptarg();
303: break;
304:
305: case 'd':
306: dbase = opts.getOptarg();
307: break;
308:
309: case 'f':
310: arg = opts.getOptarg();
311: if (arg != null) {
312: StringTokenizer st = new StringTokenizer(arg,
313: ",", false);
314: while (st.hasMoreTokens())
315: filenames.add(st.nextToken());
316: }
317: break;
318:
319: case 'l':
320: arg = opts.getOptarg();
321: if (arg != null)
322: label = arg;
323: break;
324:
325: case 'm':
326: arg = opts.getOptarg();
327: if (arg != null)
328: maxdepth = Integer.valueOf(arg).intValue();
329: break;
330:
331: case 'n':
332: // default namespace option
333: vdlns = opts.getOptarg();
334: break;
335:
336: case 'o':
337: arg = opts.getOptarg();
338: if (arg != null)
339: outputFilename = arg;
340: break;
341:
342: case 'r':
343: rejectFilename = opts.getOptarg();
344: break;
345:
346: case 'i':
347: // if update is not true, the program acts in insert mode,
348: // i.e. definition's already exist will not be overwritten.
349: overwrite = false;
350: break;
351:
352: case 'v':
353: // default version option
354: vdlvs = opts.getOptarg();
355: break;
356:
357: case 'e':
358: emptydaxok = true;
359: break;
360:
361: case 'h':
362: default:
363: me.showUsage();
364: return;
365: }
366: }
367:
368: if (opts.getOptind() >= args.length) {
369: // nothing to process -- what is this?
370: me.showUsage();
371: throw new RuntimeException(
372: "You must specify at least one input file");
373: }
374:
375: // guesstimate a label and/or output filename
376: if (label == null || outputFilename == null) {
377: for (int i = opts.getOptind(); i < args.length; ++i) {
378:
379: // bug#83.3
380: if (label == null) {
381: label = me.guessBasename(args[i]);
382: if (label != null)
383: me.m_logger.log("app", 0, "using label \""
384: + label + '"');
385: }
386:
387: // bug#83.2
388: if (outputFilename == null) {
389: outputFilename = me.guessDaxname(args[i]);
390: if (outputFilename != null)
391: me.m_logger.log("app", 0,
392: "using output file \""
393: + outputFilename + '"');
394: }
395: }
396: }
397:
398: // rejects
399: Writer reject = null;
400: if (rejectFilename != null && rejectFilename.length() > 0)
401: reject = new BufferedWriter(new FileWriter(
402: rejectFilename));
403:
404: // Connect the database.
405: String schemaName = ChimeraProperties.instance()
406: .getVDCSchemaName();
407: Connect connect = new Connect();
408: DatabaseSchema dbschema = connect
409: .connectDatabase(schemaName);
410: Define define = new Define(dbschema);
411: if (derivations.isEmpty() && filenames.isEmpty())
412: define.setDerivationMemory(true);
413:
414: // Add definitions to the database backend while parsing
415: Set badfile = me.addFilesToVDC(args, opts.getOptind(),
416: define, reject, overwrite);
417: int errcount = badfile.size();
418: if (errcount > 0) {
419: // previous section saw one or more errors, better give up.
420: for (Iterator i = badfile.iterator(); i.hasNext();) {
421: System.err.println("errors in "
422: + ((String) i.next()));
423: }
424: throw new RuntimeException("Detected " + errcount
425: + " error" + (errcount == 1 ? " " : "s ")
426: + "while parsing VDL");
427: }
428:
429: // request all derivations we encountered.
430: if (derivations.isEmpty() && filenames.isEmpty())
431: derivations = define.getDerivationMemory();
432: define = null; // free memory
433: // Runtime.getRuntime().gc(); // really free memory
434:
435: Explain explain = new Explain(dbschema);
436: if (maxdepth >= 0)
437: explain.setMaximumDepth(maxdepth);
438:
439: if (filenames.size() > 0)
440: explain.requestLFN(filenames);
441:
442: if (derivations.size() > 0) {
443: int size = derivations.size();
444: int count = 1;
445: for (Iterator i = derivations.iterator(); i.hasNext(); count++) {
446: String what = (String) i.next();
447: me.m_logger.log("app", 2, "requesting " + what
448: + " (" + count + "/" + size + ")");
449: explain.requestDerivation(what);
450: }
451: }
452:
453: // show the DAX
454: Writer bw = null;
455: if (outputFilename != null && !outputFilename.equals("-")) {
456: // save to file
457: me.m_logger.log("app", 1, "saving output to "
458: + outputFilename);
459: bw = new BufferedWriter(new FileWriter(outputFilename));
460: } else {
461: // somebody may have redirected stdout, thus buffer!
462: bw = new BufferedWriter(new PrintWriter(System.out));
463: }
464:
465: // write resulting DAX
466: explain.writeDAX(bw, label, xmlns);
467: bw.flush();
468: bw.close();
469:
470: // fail on empty requested?
471: if (explain.isEmpty() && !emptydaxok) {
472: System.err.println("ERROR: The resulting DAX is empty");
473: result = 1;
474: }
475:
476: dbschema.close();
477: } catch (IOException ioe) {
478: System.err.println("ERROR: " + ioe.getMessage());
479: result = 2;
480: } catch (RuntimeException rte) {
481: System.err.println("ERROR: " + rte.getMessage());
482: result = 2;
483: } catch (Exception e) {
484: e.printStackTrace();
485: System.err.println("FATAL: " + e.getMessage());
486: result = 3;
487: }
488: if (result != 0)
489: System.exit(result);
490: }
491: }
|